From 16487c9cf58a2cabb53980e7a53c1c7e9c864256 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Tue, 27 Jun 2023 15:14:59 +0100 Subject: [PATCH 1/8] ValuePlug : Avoid extra refcount operations This produces the following reductions in runtime : - ValuePlugTest.testCacheOverhead : 7% - ValuePlugTest.testContentionForOneItem : 25% --- include/Gaffer/ValuePlug.inl | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/include/Gaffer/ValuePlug.inl b/include/Gaffer/ValuePlug.inl index 992c915baf9..8e78d1b0172 100644 --- a/include/Gaffer/ValuePlug.inl +++ b/include/Gaffer/ValuePlug.inl @@ -43,28 +43,18 @@ template boost::intrusive_ptr ValuePlug::getObjectValue( const IECore::MurmurHash *precomputedHash ) const { IECore::ConstObjectPtr value = getValueInternal( precomputedHash ); - boost::intrusive_ptr result = IECore::runTimeCast( value ); - if( !result ) + if( value && value->isInstanceOf( T::staticTypeId() ) ) { - if( !value ) - { - // This is quite a serious error, and it may occur when a calculation has already been cancelled, - // which could result in the exception that first cancelled the calculation being displayed, but - // not this error - print the error as a message as well as throwing an exception - const std::string error = fmt::format( - "{} : getValueInternal() returned NULL. This should be impossible, something has gone badly wrong internally to Gaffer.", - fullName() - ); - IECore::msg( IECore::Msg::Error, "ValuePlug::getObjectValue", error ); - throw IECore::Exception( error ); - } - - throw IECore::Exception( fmt::format( - "{} : getValueInternal() didn't return expected type (wanted {} but got {}). Is the hash being computed correctly?", - fullName(), T::staticTypeName(), value->typeName() - ) ); + // Steal the reference from `value`, to avoid incrementing and decrementing the refcount + // unnecessarily. + /// \todo Add a move-aware variant of `IECore::runTimeCast()` and use it instead. + return boost::intrusive_ptr( static_cast( value.detach() ), /* add_ref = */ false ); } - return result; + + throw IECore::Exception( fmt::format( + "{} : getValueInternal() didn't return expected type (wanted {} but got {}). Is the hash being computed correctly?", + fullName(), T::staticTypeName(), value ? value->typeName() : "nullptr" + ) ); } } // namespace Gaffer From d961b0e3c38ea79a49a13b5575746129c0c7c17d Mon Sep 17 00:00:00 2001 From: John Haddon Date: Tue, 27 Jun 2023 15:51:43 +0100 Subject: [PATCH 2/8] ValuePlug : Avoid unnecessary `typeId()` call The common case is that a plug has no input, so it's worth avoiding the overhead of calling `typeId()`. This knocks ~2% off the runtime of `ValuePlugTest.testCacheOverhead`. --- src/Gaffer/ValuePlug.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Gaffer/ValuePlug.cpp b/src/Gaffer/ValuePlug.cpp index bb87f9ce033..3a738219e7f 100644 --- a/src/Gaffer/ValuePlug.cpp +++ b/src/Gaffer/ValuePlug.cpp @@ -69,9 +69,13 @@ namespace /// and avoids the creation of lots of unnecessary cache entries. inline const ValuePlug *sourcePlug( const ValuePlug *p ) { - const IECore::TypeId typeId = p->typeId(); - const ValuePlug *in = p->getInput(); + if( !in ) + { + return p; + } + + const IECore::TypeId typeId = p->typeId(); while( in && in->typeId() == typeId ) { p = in; From 3f6f8e20e76f60ab20f9d5c00b87704682853def Mon Sep 17 00:00:00 2001 From: John Haddon Date: Tue, 27 Jun 2023 15:58:37 +0100 Subject: [PATCH 3/8] NumericPlug : Inline `getValue()` This produces the following reductions in runtime : - ValuePlugTest.testCacheOverhead : 5% - ValuePlugTest.testContentionForOneItem : 13% --- include/Gaffer/NumericPlug.h | 4 ++- include/Gaffer/NumericPlug.inl | 48 ++++++++++++++++++++++++++++++++++ src/Gaffer/NumericPlug.cpp | 6 ----- 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 include/Gaffer/NumericPlug.inl diff --git a/include/Gaffer/NumericPlug.h b/include/Gaffer/NumericPlug.h index fab3d059341..c0eec8f5ad3 100644 --- a/include/Gaffer/NumericPlug.h +++ b/include/Gaffer/NumericPlug.h @@ -45,7 +45,7 @@ namespace Gaffer { template -class GAFFER_API NumericPlug : public ValuePlug +class IECORE_EXPORT NumericPlug : public ValuePlug { public : @@ -103,3 +103,5 @@ IE_CORE_DECLAREPTR( FloatPlug ); IE_CORE_DECLAREPTR( IntPlug ); } // namespace Gaffer + +#include "Gaffer/NumericPlug.inl" diff --git a/include/Gaffer/NumericPlug.inl b/include/Gaffer/NumericPlug.inl new file mode 100644 index 00000000000..9abd8016249 --- /dev/null +++ b/include/Gaffer/NumericPlug.inl @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2023, Cinesite VFX Ltd. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#pragma once + +namespace Gaffer +{ + +template +inline T NumericPlug::getValue( const IECore::MurmurHash *precomputedHash ) const +{ + return getObjectValue( precomputedHash )->readable(); +} + +} // namespace Gaffer diff --git a/src/Gaffer/NumericPlug.cpp b/src/Gaffer/NumericPlug.cpp index 6221b38a9d6..fca2059c8ec 100644 --- a/src/Gaffer/NumericPlug.cpp +++ b/src/Gaffer/NumericPlug.cpp @@ -142,12 +142,6 @@ void NumericPlug::setValue( T value ) setObjectValue( new DataType( value ) ); } -template -T NumericPlug::getValue( const IECore::MurmurHash *precomputedHash ) const -{ - return getObjectValue( precomputedHash )->readable(); -} - template void NumericPlug::setFrom( const ValuePlug *other ) { From 780345954da344df843d2c11bd8abe0f8ae1263f Mon Sep 17 00:00:00 2001 From: John Haddon Date: Tue, 27 Jun 2023 16:32:01 +0100 Subject: [PATCH 4/8] ValuePlug : Avoid additional refcount operations on cache hit This produces the following reductions in runtime : - ValuePlugTest.testCacheOverhead : 7% - ValuePlugTest.testContentionForOneItem : 20% --- src/Gaffer/ValuePlug.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Gaffer/ValuePlug.cpp b/src/Gaffer/ValuePlug.cpp index 3a738219e7f..809968ffe89 100644 --- a/src/Gaffer/ValuePlug.cpp +++ b/src/Gaffer/ValuePlug.cpp @@ -645,7 +645,8 @@ class ValuePlug::ComputeProcess : public Process // the same item from the cache, leading to deadlock. if( auto result = g_cache.getIfCached( processKey ) ) { - return *result; + // Move avoids unnecessary additional addRef/removeRef. + return std::move( *result ); } ComputeProcess process( processKey ); // Store the value in the cache, but only if it isn't there From e170cdca0b3fe6d49ababee524ab085b9ee39490 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Tue, 27 Jun 2023 16:42:05 +0100 Subject: [PATCH 5/8] Plug : Inline `direction()` and `node()` This produces the following reductions in runtime : - ValuePlugTest.testCacheOverhead : 5% - ValuePlugTest.testContentionForOneItem : 1% --- include/Gaffer/Plug.inl | 18 +++++++++++++++++- src/Gaffer/Plug.cpp | 15 --------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/include/Gaffer/Plug.inl b/include/Gaffer/Plug.inl index 4a9ab15d341..2122e37a356 100644 --- a/include/Gaffer/Plug.inl +++ b/include/Gaffer/Plug.inl @@ -37,9 +37,26 @@ #pragma once +#include "Gaffer/Node.h" + namespace Gaffer { +inline Node *Plug::node() +{ + return ancestor(); +} + +inline const Node *Plug::node() const +{ + return ancestor(); +} + +inline Plug::Direction Plug::direction() const +{ + return m_direction; +} + template T *Plug::getInput() { @@ -52,7 +69,6 @@ const T *Plug::getInput() const return IECore::runTimeCast( m_input ); } - template T *Plug::source() { diff --git a/src/Gaffer/Plug.cpp b/src/Gaffer/Plug.cpp index 2523f18d5de..5de181e1cdd 100644 --- a/src/Gaffer/Plug.cpp +++ b/src/Gaffer/Plug.cpp @@ -136,21 +136,6 @@ bool Plug::acceptsParent( const GraphComponent *potentialParent ) const return potentialParent->isInstanceOf( (IECore::TypeId)NodeTypeId ) || potentialParent->isInstanceOf( Plug::staticTypeId() ); } -Node *Plug::node() -{ - return ancestor(); -} - -const Node *Plug::node() const -{ - return ancestor(); -} - -Plug::Direction Plug::direction() const -{ - return m_direction; -} - unsigned Plug::getFlags() const { return m_flags; From ff3460529ed646fd041c52c019d2e2635d1d5c93 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Tue, 27 Jun 2023 16:56:48 +0100 Subject: [PATCH 6/8] Changes.md : Update to summarise recent performance improvements --- Changes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes.md b/Changes.md index 77921afb0fc..905c3407bc5 100644 --- a/Changes.md +++ b/Changes.md @@ -110,6 +110,7 @@ API - Handle::AngularDrag : Added `isLinearDrag()` method. - Widget : Added per-widget control over colour display transforms via new `setDisplayTransform()`, `getDisplayTransform()` and `displayTransform()` methods. - VisibleSet : Added `VisibleSet::Visibility` struct containing `drawMode` and `descendantsVisible` members. +- ValuePlug : Improved `getValue()` performance, particularly when retrieving previously computed values from the cache. One benchmark shows a 50% reduction in runtime when the cache is under heavy contention from many threads. Breaking Changes ---------------- From 89bbb747983e8822e8be105702b5d3ab78a60be5 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 29 Jun 2023 16:09:59 +0100 Subject: [PATCH 7/8] Typed[Object]Plug : Move `.inl` to `Implementation.h` We use `.inl` files to store inline implementation that we want the compiler to see, but which we don't want to clutter up the header with, so the headers are more human-readable. These files don't match that pattern - they're to be included in a single `.cpp` file and used to explicitly instantiate the template. --- Changes.md | 2 ++ .../{TypedObjectPlug.inl => TypedObjectPlugImplementation.h} | 0 include/Gaffer/{TypedPlug.inl => TypedPlugImplementation.h} | 0 src/Gaffer/TypedObjectPlug.cpp | 2 +- src/Gaffer/TypedPlug.cpp | 2 +- src/GafferImage/AtomicFormatPlug.cpp | 2 +- 6 files changed, 5 insertions(+), 3 deletions(-) rename include/Gaffer/{TypedObjectPlug.inl => TypedObjectPlugImplementation.h} (100%) rename include/Gaffer/{TypedPlug.inl => TypedPlugImplementation.h} (100%) diff --git a/Changes.md b/Changes.md index 905c3407bc5..c30f751a995 100644 --- a/Changes.md +++ b/Changes.md @@ -161,6 +161,8 @@ Breaking Changes - gaffer test : Replaced `-performanceOnly` flag with `-category` argument which may be set to `performance` for the same as the old `-performanceOnly`, or `standard` for the converse. - VisibleSet : Renamed `VisibleSet::match()` to `visibility()` and changed return type. - SceneView : Removed `gridPlug()` method. +- TypedPlug : Moved implementation code from `TypedPlug.inl` to `TypedPlugImplementation.h`. +- TypedObjectPlug : Moved implementation code from `TypedObjectPlug.inl` to `TypedObjectPlugImplementation.h`. Build ----- diff --git a/include/Gaffer/TypedObjectPlug.inl b/include/Gaffer/TypedObjectPlugImplementation.h similarity index 100% rename from include/Gaffer/TypedObjectPlug.inl rename to include/Gaffer/TypedObjectPlugImplementation.h diff --git a/include/Gaffer/TypedPlug.inl b/include/Gaffer/TypedPlugImplementation.h similarity index 100% rename from include/Gaffer/TypedPlug.inl rename to include/Gaffer/TypedPlugImplementation.h diff --git a/src/Gaffer/TypedObjectPlug.cpp b/src/Gaffer/TypedObjectPlug.cpp index 54ebe3b00c2..7cf2a8b78d2 100644 --- a/src/Gaffer/TypedObjectPlug.cpp +++ b/src/Gaffer/TypedObjectPlug.cpp @@ -38,7 +38,7 @@ #include "Gaffer/TypedObjectPlug.h" #include "Gaffer/StringPlug.h" -#include "Gaffer/TypedObjectPlug.inl" +#include "Gaffer/TypedObjectPlugImplementation.h" #include "boost/algorithm/string/classification.hpp" #include "boost/algorithm/string/split.hpp" diff --git a/src/Gaffer/TypedPlug.cpp b/src/Gaffer/TypedPlug.cpp index c6080c33050..1377c843990 100644 --- a/src/Gaffer/TypedPlug.cpp +++ b/src/Gaffer/TypedPlug.cpp @@ -39,7 +39,7 @@ #include "Gaffer/NumericPlug.h" #include "Gaffer/StringPlug.h" -#include "Gaffer/TypedPlug.inl" +#include "Gaffer/TypedPlugImplementation.h" namespace Gaffer { diff --git a/src/GafferImage/AtomicFormatPlug.cpp b/src/GafferImage/AtomicFormatPlug.cpp index ff1d78c2f21..3ef6693e1c8 100644 --- a/src/GafferImage/AtomicFormatPlug.cpp +++ b/src/GafferImage/AtomicFormatPlug.cpp @@ -42,7 +42,7 @@ #include "Gaffer/Context.h" #include "Gaffer/Process.h" #include "Gaffer/TypedPlug.h" -#include "Gaffer/TypedPlug.inl" +#include "Gaffer/TypedPlugImplementation.h" using namespace Gaffer; using namespace GafferImage; From 0945ec9065cb2c9a6c1fa8fabff920ea90caf383 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 29 Jun 2023 16:22:37 +0100 Subject: [PATCH 8/8] Typed[Object]Plug : Inline `getValue()` call This also means declaring AtomicFormatPlug's specialisations publicly so that we don't get the publicly visible default `getValue()` implementation being compiled instead. And the part I don't understand : we need to link `libGafferImage` to far more libraries now, to avoid undefined symbols related to AtomicFormatPlug with MSVC. It seems that the mere existence of the inlined `getValue()` - even though it is invalidated by the specialization - is enough to make MSVC greedily do a bunch of implicit template instantiations that it wasn't doing before, and which ultimately depend on `GafferImage::Format`. --- SConstruct | 8 ++-- include/Gaffer/TypedObjectPlug.h | 2 + include/Gaffer/TypedObjectPlug.inl | 48 +++++++++++++++++++ .../Gaffer/TypedObjectPlugImplementation.h | 6 --- include/Gaffer/TypedPlug.h | 2 + include/Gaffer/TypedPlug.inl | 48 +++++++++++++++++++ include/Gaffer/TypedPlugImplementation.h | 6 --- include/GafferImage/AtomicFormatPlug.h | 11 +++++ 8 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 include/Gaffer/TypedObjectPlug.inl create mode 100644 include/Gaffer/TypedPlug.inl diff --git a/SConstruct b/SConstruct index 8dce6cd3837..83e304fdb53 100644 --- a/SConstruct +++ b/SConstruct @@ -1093,7 +1093,7 @@ libraries = { "GafferSceneTest" : { "envAppends" : { - "LIBS" : [ "Gaffer", "GafferDispatch", "GafferScene", "IECoreScene$CORTEX_LIB_SUFFIX" ], + "LIBS" : [ "Gaffer", "GafferDispatch", "GafferScene", "GafferImage", "IECoreScene$CORTEX_LIB_SUFFIX" ], }, "pythonEnvAppends" : { "LIBS" : [ "Gaffer", "GafferDispatch", "GafferBindings", "GafferScene", "GafferSceneTest" ], @@ -1106,7 +1106,7 @@ libraries = { "LIBS" : [ "Gaffer", "GafferUI", "GafferImage", "GafferImageUI", "GafferScene", "Iex$IMATH_LIB_SUFFIX", "IECoreGL$CORTEX_LIB_SUFFIX", "IECoreImage$CORTEX_LIB_SUFFIX", "IECoreScene$CORTEX_LIB_SUFFIX" ], }, "pythonEnvAppends" : { - "LIBS" : [ "IECoreGL$CORTEX_LIB_SUFFIX", "GafferBindings", "GafferScene", "GafferUI", "GafferImageUI", "GafferSceneUI", "IECoreScene$CORTEX_LIB_SUFFIX" ], + "LIBS" : [ "IECoreGL$CORTEX_LIB_SUFFIX", "GafferBindings", "GafferScene", "GafferImage", "GafferUI", "GafferImageUI", "GafferSceneUI", "IECoreScene$CORTEX_LIB_SUFFIX" ], }, }, @@ -1246,7 +1246,7 @@ libraries = { "GafferOSLUI" : { "envAppends" : { - "LIBS" : [ "Gaffer", "GafferUI", "GafferOSL" ], + "LIBS" : [ "Gaffer", "GafferImage", "GafferUI", "GafferOSL" ], }, "pythonEnvAppends" : { "LIBS" : [ "IECoreGL$CORTEX_LIB_SUFFIX", "GafferBindings", "GafferScene", "GafferUI", "GafferImageUI", "GafferOSLUI" ], @@ -1351,7 +1351,7 @@ libraries = { "GafferUSD" : { "envAppends" : { - "LIBS" : [ "Gaffer", "GafferDispatch", "GafferScene", "IECoreScene$CORTEX_LIB_SUFFIX" ] + [ "${USD_LIB_PREFIX}" + x for x in ( [ "sdf", "arch", "tf", "vt" ] if not env["USD_MONOLITHIC"] else [ "usd_ms" ] ) ], + "LIBS" : [ "Gaffer", "GafferDispatch", "GafferScene", "GafferImage", "IECoreScene$CORTEX_LIB_SUFFIX" ] + [ "${USD_LIB_PREFIX}" + x for x in ( [ "sdf", "arch", "tf", "vt" ] if not env["USD_MONOLITHIC"] else [ "usd_ms" ] ) ], # USD includes "at least one deprecated or antiquated header", so we # have to drop our usual strict warning levels. "CXXFLAGS" : [ "-Wno-deprecated" if env["PLATFORM"] != "win32" else "/wd4996" ], diff --git a/include/Gaffer/TypedObjectPlug.h b/include/Gaffer/TypedObjectPlug.h index 0938bd5f2e1..8996d173653 100644 --- a/include/Gaffer/TypedObjectPlug.h +++ b/include/Gaffer/TypedObjectPlug.h @@ -181,3 +181,5 @@ IE_CORE_DECLAREPTR( AtomicCompoundDataPlug ); IE_CORE_DECLAREPTR( PathMatcherDataPlug ); } // namespace Gaffer + +#include "TypedObjectPlug.inl" diff --git a/include/Gaffer/TypedObjectPlug.inl b/include/Gaffer/TypedObjectPlug.inl new file mode 100644 index 00000000000..6975e5cb872 --- /dev/null +++ b/include/Gaffer/TypedObjectPlug.inl @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2023, Cinesite VFX Ltd. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#pragma once + +namespace Gaffer +{ + +template +inline typename TypedObjectPlug::ConstValuePtr TypedObjectPlug::getValue( const IECore::MurmurHash *precomputedHash ) const +{ + return getObjectValue( precomputedHash ); +} + +} // namespace Gaffer diff --git a/include/Gaffer/TypedObjectPlugImplementation.h b/include/Gaffer/TypedObjectPlugImplementation.h index 334c5c6d7b7..cfe0b3ff0d2 100644 --- a/include/Gaffer/TypedObjectPlugImplementation.h +++ b/include/Gaffer/TypedObjectPlugImplementation.h @@ -95,12 +95,6 @@ void TypedObjectPlug::setValue( ConstValuePtr value ) setObjectValue( value ); } -template -typename TypedObjectPlug::ConstValuePtr TypedObjectPlug::getValue( const IECore::MurmurHash *precomputedHash ) const -{ - return getObjectValue( precomputedHash ); -} - template void TypedObjectPlug::setFrom( const ValuePlug *other ) { diff --git a/include/Gaffer/TypedPlug.h b/include/Gaffer/TypedPlug.h index bf8eb1d9951..c8e70e37c68 100644 --- a/include/Gaffer/TypedPlug.h +++ b/include/Gaffer/TypedPlug.h @@ -107,3 +107,5 @@ IE_CORE_DECLAREPTR( AtomicBox3fPlug ); IE_CORE_DECLAREPTR( AtomicBox2iPlug ); } // namespace Gaffer + +#include "Gaffer/TypedPlug.inl" diff --git a/include/Gaffer/TypedPlug.inl b/include/Gaffer/TypedPlug.inl new file mode 100644 index 00000000000..0fc9033ae71 --- /dev/null +++ b/include/Gaffer/TypedPlug.inl @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2023, Cinesite VFX Ltd. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#pragma once + +namespace Gaffer +{ + +template +inline T TypedPlug::getValue( const IECore::MurmurHash *precomputedHash ) const +{ + return getObjectValue( precomputedHash )->readable(); +} + +} // namespace Gaffer diff --git a/include/Gaffer/TypedPlugImplementation.h b/include/Gaffer/TypedPlugImplementation.h index b392cb9b992..f4a37de81b1 100644 --- a/include/Gaffer/TypedPlugImplementation.h +++ b/include/Gaffer/TypedPlugImplementation.h @@ -95,12 +95,6 @@ void TypedPlug::setValue( const T &value ) setObjectValue( new DataType( value ) ); } -template -T TypedPlug::getValue( const IECore::MurmurHash *precomputedHash ) const -{ - return getObjectValue( precomputedHash )->readable(); -} - template void TypedPlug::setFrom( const ValuePlug *other ) { diff --git a/include/GafferImage/AtomicFormatPlug.h b/include/GafferImage/AtomicFormatPlug.h index c30b2a780fa..671d558b600 100644 --- a/include/GafferImage/AtomicFormatPlug.h +++ b/include/GafferImage/AtomicFormatPlug.h @@ -49,3 +49,14 @@ using AtomicFormatPlug = Gaffer::TypedPlug; IE_CORE_DECLAREPTR( AtomicFormatPlug ); } // namespace GafferImage + +namespace Gaffer +{ + +template<> +GafferImage::Format GafferImage::AtomicFormatPlug::getValue( const IECore::MurmurHash *precomputedHash ) const; + +template<> +IECore::MurmurHash GafferImage::AtomicFormatPlug::hash() const; + +} // namespace Gaffer