2015-06-10 03:14:50 -04:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
# include "RuntimeAssetCachePrivatePCH.h"
# include "RuntimeAssetCache.h"
# include "RuntimeAssetCachePluginInterface.h"
# include "RuntimeAssetCacheFilesystemBackend.h"
# include "RuntimeAssetCacheBucket.h"
# include "RuntimeAssetCacheAsyncWorker.h"
# include "RuntimeAssetCacheEntryMetadata.h"
2015-06-19 03:13:33 -04:00
# include "RuntimeAssetCacheInterface.h"
# include "RuntimeAssetCacheBPHooks.h"
2015-06-10 03:14:50 -04:00
DEFINE_STAT ( STAT_RAC_ASyncWaitTime ) ;
FRuntimeAssetCache : : FRuntimeAssetCache ( )
{
FString BucketName ;
int32 BucketSize ;
TArray < FString > BucketNames ;
GConfig - > GetArray ( TEXT ( " RuntimeAssetCache " ) , TEXT ( " BucketConfigs " ) , BucketNames , GEngineIni ) ;
for ( FString & Bucket : BucketNames )
{
if ( FParse : : Value ( * Bucket , TEXT ( " Name= " ) , BucketName ) )
{
BucketSize = FRuntimeAssetCacheBucket : : DefaultBucketSize ;
FParse : : Value ( * Bucket , TEXT ( " Size= " ) , BucketSize ) ;
FRuntimeAssetCacheBucket * BucketDesc = FRuntimeAssetCacheBackend : : Get ( ) . PreLoadBucket ( FName ( * BucketName ) , BucketSize ) ;
Buckets . Add ( FName ( * BucketName ) , BucketDesc ) ;
}
}
}
FRuntimeAssetCache : : ~ FRuntimeAssetCache ( )
{
for ( auto & Bucket : Buckets )
{
delete Bucket . Value ;
}
Buckets . Empty ( ) ;
}
int32 FRuntimeAssetCache : : GetCacheSize ( FName Bucket ) const
{
return Buckets [ Bucket ] - > GetSize ( ) ;
}
2015-06-19 03:13:33 -04:00
int32 FRuntimeAssetCache : : GetAsynchronous ( IRuntimeAssetCacheBuilder * CacheBuilder , const FOnRuntimeAssetCacheAsyncComplete & OnComplete )
2015-06-10 03:14:50 -04:00
{
int32 Handle = GetNextHandle ( ) ;
/** Must return a valid handle */
check ( Handle ! = 0 ) ;
/** Make sure task isn't processed twice. */
check ( ! PendingTasks . Contains ( Handle ) ) ;
2015-06-29 03:57:39 -04:00
checkf ( CacheBuilder - > IsBuildThreadSafe ( ) , TEXT ( " CacheBuilder %s Build function is not thread safe, but builder was used in asynchronous code. Use GetSynchronous instead. " ) , CacheBuilder - > GetBuilderName ( ) ) ;
2015-06-19 03:13:33 -04:00
FAsyncTask < FRuntimeAssetCacheAsyncWorker > * AsyncTask = new FAsyncTask < FRuntimeAssetCacheAsyncWorker > ( CacheBuilder , & Buckets , Handle , OnComplete ) ;
2015-06-10 03:14:50 -04:00
{
FScopeLock ScopeLock ( & SynchronizationObject ) ;
PendingTasks . Add ( Handle , AsyncTask ) ;
}
AddToAsyncCompletionCounter ( 1 ) ;
2015-06-29 03:57:39 -04:00
2015-06-10 03:14:50 -04:00
AsyncTask - > StartBackgroundTask ( ) ;
2015-06-29 03:57:39 -04:00
2015-06-10 03:14:50 -04:00
return Handle ;
}
2015-06-29 03:57:39 -04:00
2015-06-19 03:13:33 -04:00
int32 FRuntimeAssetCache : : GetAsynchronous ( IRuntimeAssetCacheBuilder * CacheBuilder )
2015-06-10 03:14:50 -04:00
{
2015-06-19 03:13:33 -04:00
return GetAsynchronous ( CacheBuilder , FOnRuntimeAssetCacheAsyncComplete ( ) ) ;
}
2015-06-29 21:12:06 -04:00
FVoidPtrParam FRuntimeAssetCache : : GetSynchronous ( IRuntimeAssetCacheBuilder * CacheBuilder )
2015-06-19 03:13:33 -04:00
{
2015-06-29 03:57:39 -04:00
checkf ( ! CacheBuilder - > ShouldBuildAsynchronously ( ) , TEXT ( " CacheBuilder %s can be only called asynchronously. " ) , CacheBuilder - > GetBuilderName ( ) ) ;
2015-06-19 03:13:33 -04:00
FAsyncTask < FRuntimeAssetCacheAsyncWorker > * AsyncTask = new FAsyncTask < FRuntimeAssetCacheAsyncWorker > ( CacheBuilder , & Buckets , - 1 , FOnRuntimeAssetCacheAsyncComplete ( ) ) ;
2015-06-10 03:14:50 -04:00
AddToAsyncCompletionCounter ( 1 ) ;
AsyncTask - > StartSynchronousTask ( ) ;
2015-06-29 21:12:06 -04:00
return AsyncTask - > GetTask ( ) . GetDataAndSize ( ) ;
2015-06-10 03:14:50 -04:00
}
bool FRuntimeAssetCache : : ClearCache ( )
{
/** Tell backend to clean itself up. */
bool bResult = FRuntimeAssetCacheBackend : : Get ( ) . ClearCache ( ) ;
if ( ! bResult )
{
return bResult ;
}
/** If backend is cleaned up, clean up all buckets. */
for ( auto & Bucket : Buckets )
{
Bucket . Value - > Reset ( ) ;
}
return bResult ;
}
2015-06-19 10:16:40 -04:00
bool FRuntimeAssetCache : : ClearCache ( FName BucketName )
2015-06-10 03:14:50 -04:00
{
/** Tell backend to clean bucket up. */
2015-06-19 10:16:40 -04:00
bool bResult = FRuntimeAssetCacheBackend : : Get ( ) . ClearCache ( BucketName ) ;
2015-06-10 03:14:50 -04:00
if ( ! bResult )
{
return bResult ;
}
/** If backend is cleaned up, clean up all buckets. */
for ( auto & Bucket : Buckets )
{
Bucket . Value - > Reset ( ) ;
}
return bResult ;
}
void FRuntimeAssetCache : : AddToAsyncCompletionCounter ( int32 Value )
{
PendingTasksCounter . Add ( Value ) ;
check ( PendingTasksCounter . GetValue ( ) > = 0 ) ;
}
2015-06-19 03:13:33 -04:00
void FRuntimeAssetCache : : WaitAsynchronousCompletion ( int32 Handle )
2015-06-10 03:14:50 -04:00
{
STAT ( double ThisTime = 0 ) ;
{
SCOPE_SECONDS_COUNTER ( ThisTime ) ;
FAsyncTask < FRuntimeAssetCacheAsyncWorker > * AsyncTask = NULL ;
{
FScopeLock ScopeLock ( & SynchronizationObject ) ;
AsyncTask = PendingTasks . FindRef ( Handle ) ;
}
check ( AsyncTask ) ;
AsyncTask - > EnsureCompletion ( ) ;
}
INC_FLOAT_STAT_BY ( STAT_RAC_ASyncWaitTime , ( float ) ThisTime ) ;
}
2015-06-29 21:12:06 -04:00
FVoidPtrParam FRuntimeAssetCache : : GetAsynchronousResults ( int32 Handle )
2015-06-10 03:14:50 -04:00
{
2015-06-19 03:13:33 -04:00
FAsyncTask < FRuntimeAssetCacheAsyncWorker > * AsyncTask = nullptr ;
2015-06-10 03:14:50 -04:00
{
FScopeLock ScopeLock ( & SynchronizationObject ) ;
PendingTasks . RemoveAndCopyValue ( Handle , AsyncTask ) ;
2015-06-19 03:13:33 -04:00
AsyncTask - > GetTask ( ) . FireCompletionDelegate ( ) ;
2015-06-10 03:14:50 -04:00
}
check ( AsyncTask ) ;
2015-06-19 03:13:33 -04:00
2015-06-29 21:12:06 -04:00
FVoidPtrParam Data = AsyncTask - > GetTask ( ) . GetDataAndSize ( ) ;
2015-06-10 03:14:50 -04:00
delete AsyncTask ;
2015-06-19 03:13:33 -04:00
return Data ;
2015-06-10 03:14:50 -04:00
}
2015-06-19 03:13:33 -04:00
bool FRuntimeAssetCache : : PollAsynchronousCompletion ( int32 Handle )
2015-06-10 03:14:50 -04:00
{
2015-06-19 03:13:33 -04:00
FAsyncTask < FRuntimeAssetCacheAsyncWorker > * AsyncTask = nullptr ;
2015-06-10 03:14:50 -04:00
{
FScopeLock ScopeLock ( & SynchronizationObject ) ;
AsyncTask = PendingTasks . FindRef ( Handle ) ;
}
check ( AsyncTask ) ;
return AsyncTask - > IsDone ( ) ;
}
2015-06-19 03:13:33 -04:00
void FRuntimeAssetCache : : Tick ( )
{
FScopeLock ScopeLock ( & SynchronizationObject ) ;
for ( auto Kvp : PendingTasks )
{
if ( Kvp . Value - > IsDone ( ) )
{
Kvp . Value - > GetTask ( ) . FireCompletionDelegate ( ) ;
}
}
}