Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

559 lines
24 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Provides IAsyncFileRequest and IAsyncFileSystem Interfaces
  4. // and supporting objects and values
  5. //
  6. // $NoKeywords: $
  7. //===========================================================================//
  8. #ifndef IASYNCFILESYSTEM_H
  9. #define IASYNCFILESYSTEM_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include <limits.h>
  14. #include "tier0/threadtools.h"
  15. #include "tier0/memalloc.h"
  16. #include "tier0/tslist.h"
  17. #include "tier1/interface.h"
  18. #include "tier1/utlsymbol.h"
  19. #include "tier1/functors.h"
  20. #include "tier1/checksum_crc.h"
  21. #include "tier1/utlqueue.h"
  22. #include "appframework/iappsystem.h"
  23. #include "tier2/tier2.h"
  24. //-----------------------------------------------------------------------------
  25. // "New" (circa 2009) Async FileSystem Interface
  26. //-----------------------------------------------------------------------------
  27. // This is a "newer" asynchronous-only file system interface. Using the
  28. // global that exposes it is intended to guarantee that no file I/O operations
  29. // will be blocking (unless you submit them synchronously).
  30. //
  31. //-----------------------------------------------------------------------------
  32. // Forward declarations we need
  33. //-----------------------------------------------------------------------------
  34. class CIOCompletionQueue;
  35. class IAsyncFileRequest;
  36. class IAsyncSearchRequest;
  37. //-----------------------------------------------------------------------------
  38. // AsyncRequestStatus_t - Contains the success / error status of an
  39. // asynchronous file operation
  40. //-----------------------------------------------------------------------------
  41. enum AsyncRequestStatus_t
  42. {
  43. ASYNC_REQUEST_ERROR_BADPTR = -99, // The request Pointer passed in is bad
  44. ASYNC_REQUEST_ERROR_ALREADYSUBMITTED = -98, // The request was already submitted
  45. ASYNC_REQUEST_ERROR_BADOPER = -97, // The operation type (read, write, append, etc) is invalid
  46. ASYNC_REQUEST_ERROR_BADUSERBUFFER = -96, // The supplied user buffer is incomplete
  47. ASYNC_REQUEST_ERROR_NOBUFFER = -95, // The operation requested requires a valid user buffer
  48. ASYNC_REQUEST_ERROR_NONOTIFICATION = -94, // User did not specify a callback or an IOResultQueue to message
  49. ASYNC_REQUEST_ERROR_NOTSUBMITTED = -93, // The request has not yet been submitted
  50. ASYNC_REQUEST_ERROR_ALREADYSERVICED = -92, // The request has already been serviced
  51. ASYNC_REQUEST_ERROR_PATHTOOLONG = -89, // The filepath+name is too long
  52. ASYNC_REQUEST_ERROR_INVALIDFILENAME = -88, // The Filename contains invalid characters
  53. ASYNC_REQUEST_ERROR_BADPATHSPEC = -87, // adjacent path separators in the filename or ends in path char
  54. ASYNC_REQUEST_ERROR_FILENAMETOOLONG = -86, // the filename is too long...
  55. ASYNC_REQUEST_ERROR_NOTVALIDSYNCRONOUS = -85, // Request (callbacks) not valid in synchronous mode
  56. // these mirror the existing async file system return codes. remove when changed
  57. ASYNC_REQUEST_ERROR_ALIGNMENT = -16, // read parameters invalid for unbuffered IO
  58. ASYNC_REQUEST_ERROR_FAILURE = -15, // hard subsystem failure
  59. ASYNC_REQUEST_ERROR_READING = -14, // read error on file
  60. ASYNC_REQUEST_ERROR_NOMEMORY = -13, // out of memory for file read
  61. ASYNC_REQUEST_ERROR_UNKNOWNID = -12, // caller's provided id is not recognized
  62. ASYNC_REQUEST_ERROR_FILEOPEN = -11, // filename could not be opened (bad path, not exist, etc)
  63. ASYNC_REQUEST_STATUS_UNDEFINED = -1, // should never be this (indicates incomplete code path)
  64. ASYNC_REQUEST_OK = 0, // operation is successful
  65. ASYNC_REQUEST_FORCE_INT32 = INT32_MAX // force AsyncRequestStatus_t to 32 bits
  66. };
  67. //-----------------------------------------------------------------------------
  68. // AsyncRequestState_t - indicates what state / stage of processing that an
  69. // async request is in
  70. //-----------------------------------------------------------------------------
  71. enum AsyncRequestState_t
  72. {
  73. ASYNC_REQUEST_STATE_UNDEFINED = 0, // The request is probably invalid
  74. ASYNC_REQUEST_STATE_COMPOSING = 1, // The request is being composed (open for edit)
  75. ASYNC_REQUEST_STATE_SUBMITTED, // The request is in the priority queue waiting to be serviced
  76. ASYNC_REQUEST_STATE_SERVICING, // The request is being processed by a job thread
  77. ASYNC_REQUEST_STATE_AWATING_FINISH, // The request has completed IO, and waiting to be post-processed by user code
  78. ASYNC_REQUEST_STATE_COMPLETED, // The request has completed all tasks
  79. ASYNC_REQUEST_STATE_FORCE_INT32 = INT32_MAX // force AsyncRequestStatus_t to 32 bits
  80. };
  81. //-----------------------------------------------------------------------------
  82. // AsyncFileOperation_t - list of I/O options the new async system supports
  83. //
  84. //-----------------------------------------------------------------------------
  85. enum AsyncFileOperation_t
  86. {
  87. ASYNC_OP_UNDEFINED = 0, // mapping undefined to 0 so that a value must be set (constructors memsets to 0)
  88. ASYNC_OP_READFILE, // This is a read request
  89. ASYNC_OP_WRITEFILE, // Write data to a file, delete if existing??
  90. ASYNC_OP_APPENDFILE, // Append to end of file, must file exist?
  91. ASYNC_OP_SCANDIR, // Scan a directory looking for name-matched files
  92. ASYNC_OP_COUNT, // Automatic list count
  93. ASYNC_OP_GROUP, // Object is a container of requests
  94. ASYNC_OP_FORCE_INT32 = INT32_MAX
  95. };
  96. //-----------------------------------------------------------------------------
  97. // IAsyncRequestBase - Interface common to all types of
  98. // asynchronous file IO requests
  99. //
  100. //-----------------------------------------------------------------------------
  101. class IAsyncRequestBase
  102. {
  103. friend class CAsyncFileSystem;
  104. friend class CAsyncGroupRequest;
  105. public:
  106. // functions to query operation
  107. virtual AsyncFileOperation_t GetAsyncOperationType() = 0; // Interface to determine what the derived type is
  108. // Completion options
  109. virtual void AssignCallback( CFunctor* pCallback ) = 0; // Add a completion callback to this request
  110. virtual void AssignResultQueue( CIOCompletionQueue* pMsgQueue ) = 0; // Send a completion notification to this queue object
  111. virtual void AssignCallbackAndQueue( CIOCompletionQueue* pMsgQueue, CFunctor* pCallback ) = 0; // assign a callback and a completion queue
  112. // Completion processing functions
  113. virtual void ProcessCallback( bool bReleaseRequest = true ) = 0; // Perform any assigned callbacks
  114. virtual void KeepRequestPostCallback() = 0; // User wants to keep request alive after the callback completes
  115. virtual void DontKeepRequestPostCallback() = 0; // User doesn't want to keep request after the callback completes
  116. virtual void Release() = 0; // lets user manually release the async request (only valid when completed)
  117. // Priority Functions
  118. virtual void SetPriority( int32 nPriority ) = 0; // lets the user set or change the priority of this request
  119. virtual int32 GetPriority() = 0; // queries the priority of this request
  120. // Status & Results functions
  121. virtual AsyncRequestState_t GetRequestState() = 0; // Returns what phase of the Async Process the request is in
  122. virtual AsyncRequestStatus_t GetRequestStatus() = 0; // Returns the error status of the last IO operation performed by this request
  123. private:
  124. virtual class CAsyncRequestBase* GetBase() = 0; // Used internally by the AsyncFileSystem
  125. };
  126. //-----------------------------------------------------------------------------
  127. // IAsyncRequestGroup - Interface for grouping requests together
  128. //
  129. //
  130. //-----------------------------------------------------------------------------
  131. class IAsyncGroupRequest : public IAsyncRequestBase
  132. {
  133. public:
  134. virtual void AddAsyncRequest( IAsyncRequestBase* pRequest ) = 0;
  135. virtual int32 GetAsyncRequestCount() = 0;
  136. virtual IAsyncRequestBase* GetAsyncRequest( int32 nRNum ) = 0;
  137. virtual IAsyncFileRequest* GetAsyncFileRequest( int32 nRNum ) = 0;
  138. virtual IAsyncSearchRequest* GetAsyncSearchRequest( int32 nRNum ) = 0;
  139. virtual void ReleaseAsyncRequest( int32 nRNum ) = 0;
  140. };
  141. //-----------------------------------------------------------------------------
  142. // IAsyncFileRequest - Interface for setting and reading the results of an
  143. // asynchronous file IO request
  144. //
  145. //-----------------------------------------------------------------------------
  146. class IAsyncFileRequest : public IAsyncRequestBase
  147. {
  148. public:
  149. // functions to set filename and operation
  150. virtual void LoadFile( const char* pFileName ) = 0; // make this a 'read data from file' request
  151. virtual void SaveFile( const char* pFileName ) = 0; // make this a 'write data to file' request
  152. virtual void AppendFile( const char* pFileName ) = 0; // make this a 'append data to file' request
  153. virtual void SetFileName( const char* pFileName ) = 0; // assign the filename to use
  154. virtual const char* GetFileName() = 0; // get the filename we've assigned
  155. // Buffer control functions - user supplied data buffer
  156. virtual void SetUserBuffer( void* pDataBuffer, size_t nBufferSize ) = 0; // User supplies a memory buffer to use, which they own the memory for
  157. virtual void* GetUserBuffer() = 0; // returns the address of the user supplied buffer
  158. virtual size_t GetUserBufferSize() = 0; // returns the size of the user supplied buffer
  159. virtual void ProvideDataBuffer() = 0; // Let the async file system provide a buffer to hold the data transferred (valid for Load/Read only)
  160. // Buffer results - the data buffer can be user supplied or async system supplied
  161. virtual void* GetResultBuffer() = 0; // Returns the address of the data transferred
  162. virtual size_t GetResultBufferSize() = 0; // Returns the size of the buffer holding the data transferred
  163. virtual size_t GetIOTransferredSize() = 0; // Returns the number of bytes of data actually transferred
  164. // Memory control functions for buffers allocated by the async file system
  165. virtual void KeepResultBuffer() = 0; // User wants to keeps buffer allocated by the file system
  166. virtual void ReleaseResultBuffer() = 0; // User decides they want the request to take care of releasing the buffer
  167. // file position functions
  168. virtual void ReadFileDataAt( int64 nFileOffset, size_t nReadSize = 0 ) = 0; // Read file data starting at supplied offset, optional max size to read
  169. virtual void WriteFileDataAt( int64 nFileOffset, size_t nWriteSize = 0 ) = 0; // Write data to file at supplied offset, optional size to write (max size of buffer)
  170. };
  171. //-----------------------------------------------------------------------------
  172. // CDirectoryEntryInfo_t - File Information gathered by async directory searches
  173. // Designed to be cross platform
  174. //
  175. //-----------------------------------------------------------------------------
  176. struct CDirectoryEntryInfo_t
  177. {
  178. public:
  179. char m_FullFileName[MAX_PATH];
  180. };
  181. //-----------------------------------------------------------------------------
  182. // IAsyncSearchRequest - Interface for setting and reading the results
  183. // of an asynchronous directory search request
  184. //
  185. //-----------------------------------------------------------------------------
  186. class IAsyncSearchRequest : public IAsyncRequestBase
  187. {
  188. public:
  189. // functions to define the request
  190. virtual void SetSearchFilespec( const char* pFullSearchSpec ) = 0;
  191. virtual void SetSearchPathAndFileSpec( const char* pPathId, const char* pRelativeSearchSpec ) = 0;
  192. virtual void SetSearchPathAndFileSpec( const char* pPathId, const char* pRelativeSearchPath, const char* pSearchSpec ) = 0;
  193. virtual void SetSubdirectoryScan( const bool bInclude ) = 0;
  194. virtual bool GetSubdirectoryScan() = 0;
  195. // Functions to return the results.
  196. virtual int GetResultCount() = 0;
  197. virtual CDirectoryEntryInfo_t* GetResult( int rNum = 0 ) = 0;
  198. virtual const char* GetMatchedFile( int rNum = 0 ) = 0;
  199. };
  200. //-----------------------------------------------------------------------------
  201. // CAsyncIOResult_t - Holds the result of an async file I/O request in a
  202. // CIOCompletionQueue
  203. //-----------------------------------------------------------------------------
  204. struct CAsyncIOResult_t
  205. {
  206. public:
  207. IAsyncRequestBase* m_pRequest; // Handle of the job
  208. AsyncRequestStatus_t m_Status; // Result status
  209. inline CAsyncIOResult_t();
  210. inline void ProcessCallback();
  211. };
  212. //-----------------------------------------------------------------------------
  213. // CAsyncIOResult_t - Inline method Implementations
  214. //
  215. //
  216. //-----------------------------------------------------------------------------
  217. //-----------------------------------------------------------------------------
  218. // CAsyncIOResult_t - Constructor
  219. //-----------------------------------------------------------------------------
  220. inline CAsyncIOResult_t::CAsyncIOResult_t()
  221. {
  222. m_pRequest = NULL;
  223. m_Status = ASYNC_REQUEST_STATUS_UNDEFINED;
  224. }
  225. //-----------------------------------------------------------------------------
  226. // CAsyncIOResult_t - process the user callback
  227. //-----------------------------------------------------------------------------
  228. inline void CAsyncIOResult_t::ProcessCallback()
  229. {
  230. if ( m_pRequest != NULL )
  231. {
  232. m_pRequest->ProcessCallback();
  233. }
  234. }
  235. //-----------------------------------------------------------------------------
  236. // CIOCompletionQueue - Dedicated Queue containing Async IO Notifications
  237. //-----------------------------------------------------------------------------
  238. class CIOCompletionQueue
  239. {
  240. private:
  241. CTSQueue< CAsyncIOResult_t > m_TSIOResultQueue;
  242. public:
  243. inline void Insert( CAsyncIOResult_t& theResult);
  244. inline bool IsEmpty();
  245. inline bool IsNotEmpty();
  246. inline void ProcessAllResultCallbacks();
  247. inline bool RemoveAtHead( CAsyncIOResult_t& theResult );
  248. };
  249. //-----------------------------------------------------------------------------
  250. // CIOCompletionQueue - Inline Implementation
  251. //-----------------------------------------------------------------------------
  252. //-----------------------------------------------------------------------------
  253. // CIOCompletionQueue - insert message into queue
  254. //-----------------------------------------------------------------------------
  255. inline void CIOCompletionQueue::Insert( CAsyncIOResult_t& theResult)
  256. {
  257. m_TSIOResultQueue.PushItem( theResult );
  258. }
  259. //-----------------------------------------------------------------------------
  260. // CIOCompletionQueue - check if queue empty
  261. //-----------------------------------------------------------------------------
  262. inline bool CIOCompletionQueue::IsEmpty()
  263. {
  264. return ( m_TSIOResultQueue.Count() == 0 );
  265. }
  266. //-----------------------------------------------------------------------------
  267. // CIOCompletionQueue - check if queue is not empty
  268. //-----------------------------------------------------------------------------
  269. inline bool CIOCompletionQueue::IsNotEmpty()
  270. {
  271. return ( m_TSIOResultQueue.Count() != 0 );
  272. }
  273. //-----------------------------------------------------------------------------
  274. // CIOCompletionQueue constructor
  275. //-----------------------------------------------------------------------------
  276. inline void CIOCompletionQueue::ProcessAllResultCallbacks()
  277. {
  278. CAsyncIOResult_t IOResult;
  279. while ( m_TSIOResultQueue.PopItem( &IOResult ) )
  280. {
  281. IOResult.ProcessCallback(); // no lock needed here, we are outside of the queue
  282. };
  283. }
  284. //-----------------------------------------------------------------------------
  285. // CIOCompletionQueue - pop off the first item
  286. //-----------------------------------------------------------------------------
  287. inline bool CIOCompletionQueue::RemoveAtHead( CAsyncIOResult_t& theResult )
  288. {
  289. return ( m_TSIOResultQueue.PopItem( &theResult ) );
  290. }
  291. //-----------------------------------------------------------------------------
  292. // IAsyncFileSystem - Interface to new async user methods
  293. //
  294. //-----------------------------------------------------------------------------
  295. class IAsyncFileSystem : public IAppSystem
  296. {
  297. public:
  298. //------------------------------------
  299. // Global operations
  300. //------------------------------------
  301. virtual AsyncRequestStatus_t SubmitAsyncFileRequest( const IAsyncRequestBase* pRequest ) = 0;
  302. virtual AsyncRequestStatus_t SubmitSyncFileRequest( const IAsyncRequestBase* pRequest ) = 0;
  303. virtual AsyncRequestStatus_t GetAsyncFileRequestStatus( const IAsyncRequestBase* pRequest ) = 0;
  304. virtual AsyncRequestStatus_t AbortAsyncFileRequest( const IAsyncRequestBase* pRequest ) = 0;
  305. virtual void SuspendAllAsyncIO( bool bWaitForIOCompletion = true ) = 0;
  306. virtual void ResumeAllAsyncIO() = 0;
  307. virtual AsyncRequestStatus_t AbortAllAsyncIO( bool bWaitForIOCompletion = true ) = 0;
  308. virtual IAsyncFileRequest* CreateNewFileRequest() = 0;
  309. virtual IAsyncSearchRequest* CreateNewSearchRequest() = 0;
  310. virtual IAsyncGroupRequest* CreateNewAsyncRequestGroup() = 0;
  311. virtual void ReleaseAsyncRequest( const IAsyncRequestBase* pRequest ) = 0;
  312. virtual bool BlockUntilAsyncIOComplete( const IAsyncRequestBase* pRequest ) = 0;
  313. virtual void* AllocateBuffer( size_t nBufferSize, int nAlignment = 4 ) = 0;
  314. virtual void ReleaseBuffer( void* pBuffer ) = 0;
  315. };
  316. //-----------------------------------------------------------------------------
  317. // Globals Exposed
  318. //-----------------------------------------------------------------------------
  319. DECLARE_TIER2_INTERFACE( IAsyncFileSystem, g_pAsyncFileSystem );
  320. //-----------------------------------------------------------------------------
  321. // New Async Filesystem Request Helpers
  322. //-----------------------------------------------------------------------------
  323. // These are functions that simplify and clarify the setup of common file
  324. // operations in the new asynchronous file system.
  325. //
  326. // Placed inline for linkage convenience
  327. //
  328. // If you have a generic helper you commonly use, add it to this list
  329. //
  330. //-----------------------------------------------------------------------------
  331. // ::AsyncReadFile() - Helper function to setup a New Async Request
  332. // load an entire file file, allocate a buffer, use all other defaults
  333. //-----------------------------------------------------------------------------
  334. inline IAsyncFileRequest* AsyncReadFile( const char* pFileName )
  335. {
  336. IAsyncFileRequest* theRequest = g_pAsyncFileSystem->CreateNewFileRequest(); // Open a new request
  337. theRequest->LoadFile( pFileName ); // specify file and set request type to read
  338. theRequest->ProvideDataBuffer(); // Let the request provide and own the memory
  339. return theRequest; // return request object pointer
  340. }
  341. //-----------------------------------------------------------------------------
  342. // ::AsyncReadFileToBuffer() - Helper function to setup a New Async Request
  343. // load an entire file file, to a supplied buffer, use all defaults
  344. //-----------------------------------------------------------------------------
  345. inline IAsyncFileRequest* AsyncReadFileToBuffer( const char* pFileName, void* pBuffer, size_t nBufferSize )
  346. {
  347. IAsyncFileRequest* theRequest = g_pAsyncFileSystem->CreateNewFileRequest(); // Open a new request
  348. theRequest->LoadFile( pFileName ); // specify file and set request type to read
  349. theRequest->SetUserBuffer( pBuffer, nBufferSize ); // Specify the buffer we are using
  350. return theRequest; // return request object pointer
  351. }
  352. //-----------------------------------------------------------------------------
  353. // ::AsyncReadFileBlock() - Helper function to setup a New Async Request
  354. // load an portion of a file, allocate a buffer, use all defaults
  355. //-----------------------------------------------------------------------------
  356. inline IAsyncFileRequest* AsyncReadFileBlock( const char* pFileName, int64 nOffset, size_t nLoadSize )
  357. {
  358. IAsyncFileRequest* theRequest = g_pAsyncFileSystem->CreateNewFileRequest(); // Open a new request
  359. theRequest->LoadFile( pFileName ); // specify file and set request type to read
  360. theRequest->ReadFileDataAt( nOffset, nLoadSize ); // Specify the part of the file we want to read
  361. theRequest->ProvideDataBuffer(); // Let the request provide and own the memory
  362. return theRequest; // return request object pointer
  363. }
  364. //-----------------------------------------------------------------------------
  365. // ::AsyncReadFileBlockToBuffer() - Helper function to setup a New Async Request
  366. // load an portion of a file, to a supplied buffer, use all defaults
  367. //-----------------------------------------------------------------------------
  368. inline IAsyncFileRequest* AsyncReadFileBlockToBuffer( const char* pFileName, int64 nOffset, size_t nLoadSize, void* pBuffer, size_t nBufferSize )
  369. {
  370. IAsyncFileRequest* theRequest = g_pAsyncFileSystem->CreateNewFileRequest(); // Open a new request
  371. theRequest->LoadFile( pFileName ); // specify file and set request type to read
  372. theRequest->ReadFileDataAt( nOffset, nLoadSize ); // Specify the part of the file we want to read
  373. theRequest->SetUserBuffer( pBuffer, nBufferSize ); // Specify the buffer we are using
  374. return theRequest; // return request object pointer
  375. }
  376. //-----------------------------------------------------------------------------
  377. // ::AsyncWriteBufferToFile() - Helper function to setup a New Async Request
  378. // write a buffer to a file, overwriting existing, use all defaults
  379. //-----------------------------------------------------------------------------
  380. inline IAsyncFileRequest* AsyncWriteBufferToFile( const char* pFileName, void* pBuffer, size_t nBufferSize )
  381. {
  382. IAsyncFileRequest* theRequest = g_pAsyncFileSystem->CreateNewFileRequest(); // Open a new request
  383. theRequest->SaveFile( pFileName ); // Specify file and set request type to write
  384. theRequest->SetUserBuffer( pBuffer, nBufferSize ); // Specify the buffer we are using
  385. return theRequest; // return request object pointer
  386. }
  387. //-----------------------------------------------------------------------------
  388. // ::AsyncAppendBufferToFile() - Helper function to setup a New Async Request
  389. // write a buffer to a file, append to if existing, use all defaults
  390. //-----------------------------------------------------------------------------
  391. inline IAsyncFileRequest* AsyncAppendBufferToFile( const char* pFileName, void* pBuffer, size_t nBufferSize )
  392. {
  393. IAsyncFileRequest* theRequest = g_pAsyncFileSystem->CreateNewFileRequest(); // Open a new request
  394. theRequest->AppendFile( pFileName ); // Specify file and set request type to append data to
  395. theRequest->SetUserBuffer( pBuffer, nBufferSize ); // Specify the buffer we are using
  396. return theRequest; // return request object pointer
  397. }
  398. //-----------------------------------------------------------------------------
  399. // ::AsyncRequestRelease() - Helper function to release Async Request
  400. // calls release, sets the handle to null
  401. //-----------------------------------------------------------------------------
  402. inline void AsyncRequestRelease( IAsyncRequestBase* pRequest )
  403. {
  404. g_pAsyncFileSystem->ReleaseAsyncRequest( pRequest );
  405. pRequest = NULL;
  406. }
  407. //-----------------------------------------------------------------------------
  408. // ::NewAsyncRequestGroup() - Helper function to set up a new file search
  409. // used with a search path..
  410. //-----------------------------------------------------------------------------
  411. inline IAsyncSearchRequest* AsyncFindFiles( const char* pPathID, const char* pSearchSpec )
  412. {
  413. IAsyncSearchRequest* theRequest = g_pAsyncFileSystem->CreateNewSearchRequest(); // Open a new request
  414. theRequest->SetSearchPathAndFileSpec( pPathID, pSearchSpec );
  415. theRequest->SetSubdirectoryScan( false );
  416. return theRequest; // return request object pointer
  417. }
  418. //-----------------------------------------------------------------------------
  419. // ::NewAsyncRequestGroup() - Helper function to set up a new request group
  420. // object
  421. //-----------------------------------------------------------------------------
  422. inline IAsyncGroupRequest* NewAsyncRequestGroup()
  423. {
  424. return g_pAsyncFileSystem->CreateNewAsyncRequestGroup();
  425. }
  426. #endif // IASYNCFILESYSTEM_H