Pastebin is 300% more awesome when you are logged in. Sign Up, it's FREE!
Guest

Asynchronous resource loading - header

By: a guest on Nov 20th, 2012  |  syntax: C++  |  size: 7.31 KB  |  hits: 31  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2. --------------------------------------------------------------
  3.         AssetGuid
  4. --------------------------------------------------------------
  5. */
  6. typedef mxUUID AssetGuid;
  7.  
  8. bool AssetGuid_CreateNew( AssetGuid & newGuid );
  9. bool AssetGuid_ToString( const AssetGuid& assetId, char *buffer, UINT bufferSize );
  10. bool AssetGuid_IsNull( const AssetGuid& assetId );
  11. bool AssetGuid_IsValid( const AssetGuid& assetId );
  12. bool AssetGuids_AreEqual( const AssetGuid& assetIdA, const AssetGuid& assetIdB );
  13. AssetGuid AssetGuid_GetNull();
  14.  
  15. /*
  16. -----------------------------------------------------------------------------
  17.         AFilePackage
  18.  
  19.         resource/asset data loader interface (resource/content provider)
  20. -----------------------------------------------------------------------------
  21. */
  22. struct AFilePackage : public TSinglyLinkedList< AFilePackage >
  23. {
  24.         // low-level real-only file stream
  25.         //NOTE: this structure must be bitwise-copyable
  26.         struct Stream : DbgNamedObject< FS_MAX_PATH_CHARS >
  27.         {
  28.                 // these fields are for internal use only!
  29.                 // Don't touch them!
  30.                 UINT64  fileHandle;
  31.  
  32.                 UINT    uncompressedSize;
  33.  
  34.                 UINT    sortKey;        // for sorting by file offsets
  35.                 UINT    id;     // internal stream id
  36.  
  37.         public:
  38.                 Stream();
  39.         };
  40.  
  41.         //[must be threadsafe]
  42.         virtual bool OpenFile( const AssetGuid& fileId, Stream *stream ) = 0;
  43.  
  44.         //[must be threadsafe]
  45.         virtual void CloseFile( Stream * stream ) = 0;
  46.  
  47.         // Reads the file into the preallocated buffer
  48.         //[must be threadsafe]
  49.         virtual SizeT ReadFile( Stream * stream, UINT startOffset, void *buffer, UINT bytesToRead ) = 0;
  50.  
  51. protected:
  52.         virtual ~AFilePackage() {}
  53. };
  54.  
  55. /*
  56. --------------------------------------------------------------
  57.         FileSystem
  58.  
  59.         virtual file system (based on package files),
  60.         it simply provides access to individual files by their ids.
  61. --------------------------------------------------------------
  62. */
  63. class FileSystem : SingleInstance< FileSystem >
  64. {
  65.         AFilePackage::Head      m_packages;     // linked list of mounted packages
  66.  
  67. public:
  68.         FileSystem();
  69.         ~FileSystem();
  70.  
  71.         bool MountPackage( AFilePackage* package );
  72.         void UnmountPackage( AFilePackage* package );
  73.  
  74.         //[must be threadsafe]
  75.         AFilePackage* OpenFile( const AssetGuid& fileId, AFilePackage::Stream *stream );
  76. };
  77.  
  78.  
  79. // Load request priority.
  80. enum ELoadPriority
  81. {
  82.         Load_Priority_Low = 0,
  83.         Load_Priority_Normal = 64,
  84.         Load_Priority_High = 128,
  85.         Load_Priority_Critical = 255,
  86.  
  87.         Load_Priority_MAX,
  88. };
  89.  
  90. enum {
  91.         Load_Priority_Collision_Hull = Load_Priority_Critical,
  92.         Load_Priority_Animation = Load_Priority_Critical,
  93.         Load_Priority_Sound = Load_Priority_High,
  94.         Load_Priority_Music = Load_Priority_Normal,
  95.         Load_Priority_Texture = Load_Priority_Low,
  96. };
  97.  
  98. enum ELoadStatus
  99. {
  100.         LoadStatus_HadErrors = 0,
  101.         LoadStatus_Loaded,
  102.         LoadStatus_Unloaded,
  103.         LoadStatus_Pending,
  104.         LoadStatus_Cancelled,
  105. };
  106.  
  107. // load request id, could be 64-bit to prevent wraparound
  108. typedef UINT LoadRequestId;
  109.  
  110. static const LoadRequestId INVALID_LOAD_REQUEST_ID = ~0UL;
  111.  
  112. // parameters for loading data asynchronously in a background thread
  113. struct SLoadContext
  114. {
  115.         void *          buffer;
  116.         UINT            size;
  117.         void *          userData;
  118.         LoadRequestId   requestId;
  119.         //AssetGuid     assetId;
  120. };
  121. // parameters for instantiating a 'live' resource object ('asset instance') in the main thread
  122. struct SFinalizeContext
  123. {
  124.         void *          buffer;
  125.         UINT            size;
  126.         void *          userData;
  127.         LoadRequestId   requestId;
  128.         //AssetGuid     assetId;
  129. };
  130.  
  131. // this is called in the background loading thread
  132. // when the data has been read into the buffer - must be thread-safe!
  133. // (e.g. file parsing, deserialization stuff, pointer fixups)
  134. typedef void F_AsyncLoad( const SLoadContext& context );
  135.  
  136. // this is called in the main thread after F_AsyncLoad()
  137. // (e.g. creating live resource objects from parsed file data)
  138. // NOTE: added another parameter to avoid typecasting errors with F_AsyncLoad()
  139. typedef void F_Finalize( const SFinalizeContext& context );
  140.  
  141.  
  142. // resource load request (main thread => resource loading thread)
  143. // represents a request for loading raw asset data bytes
  144. // from which a 'live' asset object will be constructed
  145. struct SLoadRequest
  146. {
  147.         AssetGuid       assetId;        // filename
  148.         void *          buffer; // output buffer
  149.         UINT            bytesToRead;    // if 0, then the entire file will be read
  150.  
  151.         ELoadPriority   priority;
  152.  
  153.         //callbacks
  154.         void *          userData;
  155.         F_AsyncLoad *   asyncLoad;      //<= must never be null
  156.         F_Finalize *    finalize;       //<= must never be null
  157.  
  158. public:
  159.         SLoadRequest();
  160. };
  161.  
  162. bool SLoadRequest_CheckValid( const SLoadRequest& o );
  163.  
  164. /*
  165. --------------------------------------------------------------
  166.         AsyncReader
  167.         creates a separate 'streaming' thread
  168.         for background resource loading and decompression
  169. --------------------------------------------------------------
  170. */
  171. class AsyncReader : SingleInstance< AsyncReader >
  172. {
  173. public:
  174.         // queued asynchronous data load request
  175.         //NOTE: this structure must be bitwise-copyable
  176.         struct SPendingRequest
  177.         {
  178.                 AFilePackage *  package;
  179.                 AFilePackage::Stream stream;
  180.  
  181.                 ELoadPriority   priority;
  182.  
  183.                 void *  buffer; // output buffer (non-null if user supplied)
  184.                 UINT    bytesToRead;
  185.  
  186.                 //callbacks
  187.                 void *                  userData;
  188.                 F_AsyncLoad *   asyncLoad;      // called in the streaming thread
  189.                 F_Finalize *    finalize;       // called in the main thread
  190.  
  191.                 LoadRequestId   uid;    // unique id
  192.         };
  193.         typedef TArray< SPendingRequest, UINT > PendingRequests;
  194.  
  195.         //NOTE: this structure must be bitwise-copyable
  196.         struct SCompletedRequest
  197.         {
  198.                 void *  buffer;
  199.                 UINT    bytesRead;
  200.  
  201.                 //callbacks
  202.                 void *                  userData;
  203.                 F_Finalize *    finalize;       // called in the main thread
  204.  
  205.                 LoadRequestId   uid;    // unique id
  206.  
  207.         public:
  208.                 //this is called in the main thread
  209.                 inline void Finalize()
  210.                 {
  211.                         SFinalizeContext        args;
  212.                         {
  213.                                 args.buffer             = buffer;
  214.                                 args.size               = bytesRead;
  215.                                 args.userData   = userData;
  216.                                 args.requestId  = uid;
  217.                                 //args.assetId = assetId;
  218.                         }
  219.                         (*finalize)( args );
  220.                 }
  221.         };
  222.         typedef TArray< SCompletedRequest, UINT > CompletedRequests;
  223.  
  224. private:
  225.         PendingRequests         m_pendingRequests;      // queued load requests
  226.         SpinWait                m_pendingRequestsCS;// for serializing access to the load queue
  227.  
  228.         CompletedRequests       m_completedRequests;// executed load requests
  229.         SpinWait                m_completedRequestsCS;
  230.  
  231.         Thread                  m_IOThread;     // worker thread for asynchronous I/O
  232.         EventFlag               m_wakeupEvent;  // tells the thread that there's work to do
  233.         EventFlag               m_workDoneEvent;// signals that the thread has processed all items
  234.         volatile BOOL           m_isRunning;    // this flag is used to stop the I/O thread
  235.  
  236.         LoadRequestId   m_lastRequestId;        // for generating unique ids
  237.  
  238. public:
  239.         AsyncReader();
  240.         ~AsyncReader();
  241.  
  242.         void Initialize();      //[main thread only]
  243.         void Shutdown();        //[main thread only]
  244.  
  245.         bool AddLoadRequest( const SLoadRequest& request, LoadRequestId *id = nil );
  246.  
  247.         bool Cancel( LoadRequestId requestId ); //[main thread only]
  248.         bool WaitFor( LoadRequestId requestId, UINT timeOutMilliseconds = INFINITE );
  249.         void CancelAll();
  250.         void WaitForAll( UINT milliseconds = INFINITE );
  251.  
  252.         void FinalizeCompletedRequests( UINT maxNumRequests = 0 );
  253.  
  254. private:
  255.         //NOTE: the returned pointers cannot be cached
  256.         SPendingRequest* FindPendingRequest_NoLock( LoadRequestId requestId );
  257.         SCompletedRequest* FindCompletedRequest_NoLock( LoadRequestId requestId );
  258.  
  259.         void SortQueuedRequests_NoLock();
  260.  
  261.         static UINT32 PASCAL StaticResourceLoaderThread( void* userData );
  262.         UINT32 ResourceLoaderThread();
  263. };