Advertisement
Guest User

Asynchronous resource loading - header

a guest
Nov 20th, 2012
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.31 KB | None | 0 0
  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. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement