diff --git a/Changes.md b/Changes.md index df78c107e21..aabdf43abd7 100644 --- a/Changes.md +++ b/Changes.md @@ -92,7 +92,9 @@ API - OpenColorIOAlgo : Added a new namespace that allows the OpenColorIO config and working space to be defined via the Gaffer context. - OpenColorIOConfigPlug : Added a new plug type to aid in configuring the OpenColorIO context for a ScriptNode. - ImageReader/ImageWriter : Added a `config` argument to the `DefaultColorSpaceFunction` definition. This is passed the OpenColorIO config currently being used by the node. -- ValuePlugs : Added Python bindings for `ValueType` type alias. +- ValuePlug : + - Added Python bindings for derived classes' `ValueType` type alias. + - Added `now` argument to `clearHashCache()` method. - Color4fVectorDataPlug : Added a plug type for storing arrays of `Color4f`. - TypedObjectPlug : Added default value for `direction` and `defaultValue` constructor arguments. - VectorDataWidget : Added `setErrored()` and `getErrored()` methods to control an error state. Errors are reflected by a red background colour. diff --git a/include/Gaffer/ValuePlug.h b/include/Gaffer/ValuePlug.h index 80192d46eee..4913e88e953 100644 --- a/include/Gaffer/ValuePlug.h +++ b/include/Gaffer/ValuePlug.h @@ -185,9 +185,11 @@ class GAFFER_API ValuePlug : public Plug /// Returns the total number of entries in both global and per-thread hash caches static size_t hashCacheTotalUsage(); /// Clears the hash cache. - /// > Note : Clearing occurs on a per-thread basis as and when - /// > each thread next accesses the cache. - static void clearHashCache(); + /// > Note : By default, clearing occurs on a per-thread basis as + /// > and when each thread next accesses its cache. Pass `now = true` + /// > to force all thread-local caches to be cleared immediately + /// > (this is not thread-safe with respect to concurrent computations). + static void clearHashCache( bool now = false ); /// The standard hash cache mode relies on correctly implemented /// affects() methods to selectively clear the cache for dirtied diff --git a/src/Gaffer/ValuePlug.cpp b/src/Gaffer/ValuePlug.cpp index 3af7e9fb256..28d229c41c2 100644 --- a/src/Gaffer/ValuePlug.cpp +++ b/src/Gaffer/ValuePlug.cpp @@ -331,7 +331,7 @@ class ValuePlug::HashProcess : public Process g_globalCache.setMaxCost( g_cacheSizeLimit ); } - static void clearCache() + static void clearCache( bool now = false ) { g_globalCache.clear(); // It's not documented explicitly, but it is safe to iterate over an @@ -341,11 +341,20 @@ class ValuePlug::HashProcess : public Process tbb::enumerable_thread_specific::iterator it, eIt; for( it = g_threadData.begin(), eIt = g_threadData.end(); it != eIt; ++it ) { - // We can't clear the cache now, because it is most likely - // in use by the owning thread. Instead we set this flag to - // politely request that the thread clears the cache itself - // at its earliest convenience - in the HashProcess constructor. - it->clearCache.store( 1, std::memory_order_release ); + if( now ) + { + // Not thread-safe - caller is responsible for ensuring there + // are no concurrent computes. + it->cache.clear(); + } + else + { + // We can't clear the cache now, because it is most likely + // in use by the owning thread. Instead we set this flag to + // politely request that the thread clears the cache itself + // at its earliest convenience - in the HashProcess constructor. + it->clearCache.store( 1, std::memory_order_release ); + } } } @@ -1239,9 +1248,9 @@ void ValuePlug::setHashCacheSizeLimit( size_t maxEntriesPerThread ) HashProcess::setCacheSizeLimit( maxEntriesPerThread ); } -void ValuePlug::clearHashCache() +void ValuePlug::clearHashCache( bool now ) { - HashProcess::clearCache(); + HashProcess::clearCache( now ); } size_t ValuePlug::hashCacheTotalUsage() diff --git a/src/GafferModule/ValuePlugBinding.cpp b/src/GafferModule/ValuePlugBinding.cpp index ed572f100dd..f3fdef36bea 100644 --- a/src/GafferModule/ValuePlugBinding.cpp +++ b/src/GafferModule/ValuePlugBinding.cpp @@ -139,7 +139,7 @@ void GafferModule::bindValuePlug() .staticmethod( "setHashCacheSizeLimit" ) .def( "hashCacheTotalUsage", &ValuePlug::hashCacheTotalUsage ) .staticmethod( "hashCacheTotalUsage" ) - .def( "clearHashCache", &ValuePlug::clearHashCache ) + .def( "clearHashCache", &ValuePlug::clearHashCache, arg( "now" ) = false ) .staticmethod( "clearHashCache" ) .def( "getHashCacheMode", &ValuePlug::getHashCacheMode ) .staticmethod( "getHashCacheMode" )