diff --git a/Common/GTesting/CMakeLists.txt b/Common/GTesting/CMakeLists.txt index 151199ec4..274b0a8c2 100644 --- a/Common/GTesting/CMakeLists.txt +++ b/Common/GTesting/CMakeLists.txt @@ -1,5 +1,6 @@ add_executable(CommonGTest elxBaseComponentGTest.cxx + elxElastixMainGTest.cxx elxTransformIOGTest.cxx itkComputeImageExtremaFilterGTest.cxx ) diff --git a/Common/GTesting/elxElastixMainGTest.cxx b/Common/GTesting/elxElastixMainGTest.cxx new file mode 100644 index 000000000..fbe0532d1 --- /dev/null +++ b/Common/GTesting/elxElastixMainGTest.cxx @@ -0,0 +1,45 @@ +/*========================================================================= + * + * Copyright UMC Utrecht and contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +// First include the header file to be tested: +#include "elxElastixMain.h" + +#include + + +// Tests retrieving the component data base and a component creator in parallel. +GTEST_TEST(ElastixMain, GetComponentDatabaseAndCreatorInParallel) +{ + const elx::xoutManager manager("", false, false); + +#pragma omp parallel for + for (auto i = 0; i <= 9; ++i) + { + const auto creator = elx::ElastixMain::GetComponentDatabase().GetCreator("Elastix", 1); + EXPECT_NE(creator, nullptr); + EXPECT_NE(creator, elx::ComponentDatabase::PtrToCreator{}); + + if (creator != nullptr) + { + const auto elxComponent = creator(); + EXPECT_NE(elxComponent, nullptr); + EXPECT_NE(elxComponent, itk::Object::Pointer{}); + EXPECT_NE(dynamic_cast(elxComponent.GetPointer()), nullptr); + } + } +} diff --git a/Components/Transforms/WeightedCombinationTransform/elxWeightedCombinationTransform.hxx b/Components/Transforms/WeightedCombinationTransform/elxWeightedCombinationTransform.hxx index 0fc845459..72d934110 100644 --- a/Components/Transforms/WeightedCombinationTransform/elxWeightedCombinationTransform.hxx +++ b/Components/Transforms/WeightedCombinationTransform/elxWeightedCombinationTransform.hxx @@ -280,8 +280,7 @@ WeightedCombinationTransformElastix::LoadSubTransforms(void) /** Create a SubTransform. */ typename ObjectType::Pointer subTransform; PtrToCreator testcreator = nullptr; - testcreator = - this->GetElastix()->GetComponentDatabase()->GetCreator(subTransformName, this->m_Elastix->GetDBIndex()); + testcreator = ElastixMain::GetComponentDatabase().GetCreator(subTransformName, this->m_Elastix->GetDBIndex()); // Note that ObjectType::Pointer() yields a default-constructed SmartPointer (null). subTransform = testcreator ? testcreator() : typename ObjectType::Pointer(); diff --git a/Core/ComponentBaseClasses/elxTransformBase.hxx b/Core/ComponentBaseClasses/elxTransformBase.hxx index b911d331d..a665bede5 100644 --- a/Core/ComponentBaseClasses/elxTransformBase.hxx +++ b/Core/ComponentBaseClasses/elxTransformBase.hxx @@ -19,6 +19,7 @@ #define elxTransformBase_hxx #include "elxTransformBase.h" +#include "elxElastixMain.h" #include "elxTransformIO.h" #include "itkPointSet.h" @@ -548,7 +549,7 @@ TransformBase::ReadInitialTransformFromConfiguration( /** Create an InitialTransform. */ const PtrToCreator testcreator = - this->GetElastix()->GetComponentDatabase()->GetCreator(initialTransformName, this->m_Elastix->GetDBIndex()); + ElastixMain::GetComponentDatabase().GetCreator(initialTransformName, this->m_Elastix->GetDBIndex()); const ObjectType::Pointer initialTransform = (testcreator == nullptr) ? nullptr : testcreator(); const auto elx_initialTransform = dynamic_cast(initialTransform.GetPointer()); diff --git a/Core/Install/elxComponentLoader.cxx b/Core/Install/elxComponentLoader.cxx index 8b3989dce..32be3bcde 100644 --- a/Core/Install/elxComponentLoader.cxx +++ b/Core/Install/elxComponentLoader.cxx @@ -87,10 +87,7 @@ ComponentLoader::ComponentLoader() * ****************** Destructor ********************************* */ -ComponentLoader::~ComponentLoader() -{ - this->UnloadComponents(); -} +ComponentLoader::~ComponentLoader() = default; /** @@ -160,22 +157,4 @@ ComponentLoader::LoadComponents(void) } // end LoadComponents - -/** - * ****************** UnloadComponents **************************** - */ - -void -ComponentLoader::UnloadComponents() -{ - /** - * This function used to be more useful when we still used .dll's. - */ - - // Not necessary I think: - // this->m_ComponentDatabase = 0; - -} // end UnloadComponents - - } // end namespace elastix diff --git a/Core/Install/elxComponentLoader.h b/Core/Install/elxComponentLoader.h index 54850a2e7..a05ab630b 100644 --- a/Core/Install/elxComponentLoader.h +++ b/Core/Install/elxComponentLoader.h @@ -63,10 +63,6 @@ class ComponentLoader : public itk::Object int LoadComponents(void); - /** Function to unload components. */ - void - UnloadComponents(void); - protected: /** Standard constructor and destructor. */ ComponentLoader(); diff --git a/Core/Kernel/elxElastixBase.cxx b/Core/Kernel/elxElastixBase.cxx index 7329762de..f43d308b2 100644 --- a/Core/Kernel/elxElastixBase.cxx +++ b/Core/Kernel/elxElastixBase.cxx @@ -132,7 +132,6 @@ ElastixBase::ElastixBase() { /** Initialize. */ this->m_Configuration = nullptr; - this->m_ComponentDatabase = nullptr; this->m_DBIndex = 0; /** The default output precision of elxout is set to 6. */ diff --git a/Core/Kernel/elxElastixBase.h b/Core/Kernel/elxElastixBase.h index 2cceb838c..d1c28daa0 100644 --- a/Core/Kernel/elxElastixBase.h +++ b/Core/Kernel/elxElastixBase.h @@ -198,14 +198,6 @@ class ElastixBase return this->m_DBIndex; } - - /** Functions to get/set the ComponentDatabase - * The component database contains pointers to functions - * that create components. - */ - elxGetObjectMacro(ComponentDatabase, ComponentDatabaseType); - elxSetObjectMacro(ComponentDatabase, ComponentDatabaseType); - /** Get the component containers. * The component containers store components, such as * the metric, in the form of an itk::Object::Pointer. @@ -397,9 +389,8 @@ class ElastixBase ElastixBase(); ~ElastixBase() override = default; - ConfigurationPointer m_Configuration; - DBIndexType m_DBIndex; - ComponentDatabasePointer m_ComponentDatabase; + ConfigurationPointer m_Configuration; + DBIndexType m_DBIndex; FlatDirectionCosinesType m_OriginalFixedImageDirection; diff --git a/Core/Kernel/elxElastixMain.cxx b/Core/Kernel/elxElastixMain.cxx index 48346e27c..c7e54f4ef 100644 --- a/Core/Kernel/elxElastixMain.cxx +++ b/Core/Kernel/elxElastixMain.cxx @@ -25,6 +25,7 @@ #endif #include "elxElastixMain.h" +#include "elxComponentLoader.h" #include "elxMacro.h" #include "itkPlatformMultiThreader.h" @@ -182,12 +183,27 @@ ElastixMain::ElastixMain() /** - * ****************** Initialization of static members ********* + * ****************** GetComponentDatabase ********* */ -// Both s_CDB and s_ComponentLoader are defaulted-constructed to null. -ElastixMain::ComponentDatabasePointer ElastixMain::s_CDB; -ElastixMain::ComponentLoaderPointer ElastixMain::s_ComponentLoader; +const ComponentDatabase & +ElastixMain::GetComponentDatabase(void) +{ + // Improved thread-safety by using C++11 "magic statics". + static const auto componentDatabase = [] { + const auto componentDatabase = ComponentDatabase::New(); + const auto componentLoader = ComponentLoader::New(); + componentLoader->SetComponentDatabase(componentDatabase); + + if (componentLoader->LoadComponents() != 0) + { + xout["error"] << "Loading components failed" << std::endl; + } + return componentDatabase; + }(); + return *componentDatabase; +} + /** * ********************** Destructor **************************** @@ -338,7 +354,6 @@ ElastixMain::Run(void) /** Set some information in the ElastixBase. */ this->GetElastixBase()->SetConfiguration(this->m_Configuration); - this->GetElastixBase()->SetComponentDatabase(this->s_CDB); this->GetElastixBase()->SetDBIndex(this->m_DBIndex); /** Populate the component containers. ImageSampler is not mandatory. @@ -635,32 +650,18 @@ ElastixMain::InitDBIndex(void) } } - /** Load the components. */ - if (this->s_CDB.IsNull()) + /** Get the DBIndex from the ComponentDatabase. */ + this->m_DBIndex = GetComponentDatabase().GetIndex(this->m_FixedImagePixelType, + this->m_FixedImageDimension, + this->m_MovingImagePixelType, + this->m_MovingImageDimension); + if (this->m_DBIndex == 0) { - int loadReturnCode = this->LoadComponents(); - if (loadReturnCode != 0) - { - xout["error"] << "Loading components failed" << std::endl; - return loadReturnCode; - } + xout["error"] << "ERROR:" << std::endl; + xout["error"] << "Something went wrong in the ComponentDatabase" << std::endl; + return 1; } - if (this->s_CDB.IsNotNull()) - { - /** Get the DBIndex from the ComponentDatabase. */ - this->m_DBIndex = this->s_CDB->GetIndex(this->m_FixedImagePixelType, - this->m_FixedImageDimension, - this->m_MovingImagePixelType, - this->m_MovingImageDimension); - if (this->m_DBIndex == 0) - { - xout["error"] << "ERROR:" << std::endl; - xout["error"] << "Something went wrong in the ComponentDatabase" << std::endl; - return 1; - } - } // end if s_CDB!=0 - } // end if m_Configuration->Initialized(); else { @@ -727,55 +728,6 @@ ElastixMain::GetTotalNumberOfElastixLevels(void) } // end GetTotalNumberOfElastixLevels() -/** - * ********************* LoadComponents ************************** - * - * Store the install function of each component in the - * component database. - */ - -int -ElastixMain::LoadComponents(void) -{ - /** Create a ComponentDatabase. */ - if (this->s_CDB.IsNull()) - { - this->s_CDB = ComponentDatabaseType::New(); - } - - /** Create a ComponentLoader and set the database. */ - if (this->s_ComponentLoader.IsNull()) - { - this->s_ComponentLoader = ComponentLoaderType::New(); - this->s_ComponentLoader->SetComponentDatabase(s_CDB); - } - - /** Load the components. */ - return this->s_ComponentLoader->LoadComponents(); - -} // end LoadComponents() - - -/** - * ********************* UnloadComponents ************************** - */ - -void -ElastixMain::UnloadComponents(void) -{ - s_CDB = nullptr; - s_ComponentLoader->SetComponentDatabase(nullptr); - - if (s_ComponentLoader) - { - s_ComponentLoader->UnloadComponents(); - } - - s_ComponentLoader = nullptr; - -} // end UnloadComponents() - - /** * ************************* GetElastixBase *************************** */ @@ -806,7 +758,7 @@ ElastixMain::CreateComponent(const ComponentDescriptionType & name) { /** A pointer to the New() function. */ PtrToCreator testcreator = nullptr; - testcreator = this->s_CDB->GetCreator(name, this->m_DBIndex); + testcreator = GetComponentDatabase().GetCreator(name, this->m_DBIndex); // Note that ObjectPointer() yields a default-constructed SmartPointer (null). ObjectPointer testpointer = testcreator ? testcreator() : ObjectPointer(); diff --git a/Core/Kernel/elxElastixMain.h b/Core/Kernel/elxElastixMain.h index 41b727acc..adb377cf2 100644 --- a/Core/Kernel/elxElastixMain.h +++ b/Core/Kernel/elxElastixMain.h @@ -19,7 +19,6 @@ #define elxElastixMain_h #include "elxComponentDatabase.h" -#include "elxComponentLoader.h" #include "elxElastixBase.h" #include "itkParameterMapInterface.h" @@ -169,10 +168,6 @@ class ElastixMain : public itk::Object typedef ComponentDatabaseType::ImageDimensionType ImageDimensionType; typedef ComponentDatabaseType::IndexType DBIndexType; - /** Typedef for class that populates a ComponentDatabase. */ - typedef ComponentLoader ComponentLoaderType; - typedef ComponentLoaderType::Pointer ComponentLoaderPointer; - /** Typedef that is used in the elastix dll version. */ typedef itk::ParameterMapInterface::ParameterMapType ParameterMapType; @@ -315,31 +310,14 @@ class ElastixMain : public itk::Object virtual void SetMaximumNumberOfThreads(void) const; - /** Functions to get/set the ComponentDatabase. */ - static ComponentDatabase * - GetComponentDatabase(void) - { - return s_CDB.GetPointer(); - } - - - static void - SetComponentDatabase(ComponentDatabase * arg) - { - if (s_CDB != arg) - { - s_CDB = arg; - } - } - + /** Function to get the ComponentDatabase. */ + static const ComponentDatabase & + GetComponentDatabase(void); /** GetTransformParametersMap */ virtual ParameterMapType GetTransformParametersMap(void) const; - static void - UnloadComponents(void); - protected: ElastixMain(); ~ElastixMain() override; @@ -383,11 +361,6 @@ class ElastixMain : public itk::Object FlatDirectionCosinesType m_OriginalFixedImageDirection; - static ComponentDatabasePointer s_CDB; - static ComponentLoaderPointer s_ComponentLoader; - virtual int - LoadComponents(void); - /** InitDBIndex sets m_DBIndex by asking the ImageTypes * from the Configuration object and obtaining the corresponding * DB index from the ComponentDatabase. diff --git a/Core/Kernel/elxTransformixMain.cxx b/Core/Kernel/elxTransformixMain.cxx index d54771930..ad5a12458 100644 --- a/Core/Kernel/elxTransformixMain.cxx +++ b/Core/Kernel/elxTransformixMain.cxx @@ -104,7 +104,6 @@ TransformixMain::Run(void) /** Set some information in the ElastixBase. */ this->GetElastixBase()->SetConfiguration(this->m_Configuration); - this->GetElastixBase()->SetComponentDatabase(this->s_CDB); this->GetElastixBase()->SetDBIndex(this->m_DBIndex); /** Populate the component containers. No default is specified for the Transform. */ @@ -268,32 +267,18 @@ TransformixMain::InitDBIndex(void) } } - /** Load the components. */ - if (this->s_CDB.IsNull()) + /** Get the DBIndex from the ComponentDatabase. */ + this->m_DBIndex = this->GetComponentDatabase().GetIndex(this->m_FixedImagePixelType, + this->m_FixedImageDimension, + this->m_MovingImagePixelType, + this->m_MovingImageDimension); + if (this->m_DBIndex == 0) { - int loadReturnCode = this->LoadComponents(); - if (loadReturnCode != 0) - { - xl::xout["error"] << "Loading components failed" << std::endl; - return loadReturnCode; - } + xl::xout["error"] << "ERROR:" << std::endl; + xl::xout["error"] << "Something went wrong in the ComponentDatabase." << std::endl; + return 1; } - if (this->s_CDB.IsNotNull()) - { - /** Get the DBIndex from the ComponentDatabase. */ - this->m_DBIndex = this->s_CDB->GetIndex(this->m_FixedImagePixelType, - this->m_FixedImageDimension, - this->m_MovingImagePixelType, - this->m_MovingImageDimension); - if (this->m_DBIndex == 0) - { - xl::xout["error"] << "ERROR:" << std::endl; - xl::xout["error"] << "Something went wrong in the ComponentDatabase." << std::endl; - return 1; - } - } // end if s_CDB!=0 - } // end if m_Configuration->Initialized(); else { diff --git a/Core/Kernel/elxTransformixMain.h b/Core/Kernel/elxTransformixMain.h index 0cbfd29ae..1fbb8d454 100644 --- a/Core/Kernel/elxTransformixMain.h +++ b/Core/Kernel/elxTransformixMain.h @@ -79,10 +79,6 @@ class TransformixMain : public ElastixMain typedef Superclass::ImageDimensionType ImageDimensionType; typedef Superclass::DBIndexType DBIndexType; - /** Typedef for class that populates a ComponentDatabase. */ - typedef Superclass::ComponentLoaderType ComponentLoaderType; - typedef Superclass::ComponentLoaderPointer ComponentLoaderPointer; - /** Typedef that is used in the elastix dll version. */ typedef Superclass::ParameterMapType ParameterMapType; diff --git a/Core/Main/elastix.cxx b/Core/Main/elastix.cxx index 44de371ae..9bde0d984 100644 --- a/Core/Main/elastix.cxx +++ b/Core/Main/elastix.cxx @@ -335,9 +335,6 @@ main(int argc, char ** argv) fixedMaskContainer = nullptr; movingMaskContainer = nullptr; - /** Close the modules. */ - ElastixMainType::UnloadComponents(); - /** Exit and return the error code. */ return 0; diff --git a/Core/Main/elastixlib.cxx b/Core/Main/elastixlib.cxx index 2b7ee9257..c5a9f04af 100644 --- a/Core/Main/elastixlib.cxx +++ b/Core/Main/elastixlib.cxx @@ -353,9 +353,6 @@ ELASTIX::RegisterImages(ImagePointer fixedImage, movingMaskContainer = nullptr; resultImageContainer = nullptr; - /** Close the modules. */ - ElastixMainType::UnloadComponents(); - /** Exit and return the error code. */ return 0; diff --git a/Core/Main/transformix.cxx b/Core/Main/transformix.cxx index 032f62595..e234feb4f 100644 --- a/Core/Main/transformix.cxx +++ b/Core/Main/transformix.cxx @@ -227,7 +227,6 @@ main(int argc, char ** argv) /** Clean up. */ transformix = nullptr; - TransformixMainType::UnloadComponents(); /** Exit and return the error code. */ return returndummy; diff --git a/Core/Main/transformixlib.cxx b/Core/Main/transformixlib.cxx index 1797af1d2..b9e2d2ccf 100644 --- a/Core/Main/transformixlib.cxx +++ b/Core/Main/transformixlib.cxx @@ -230,7 +230,6 @@ TRANSFORMIX::TransformImage(ImagePointer inputImage, /** Clean up. */ transformix = nullptr; - TransformixMainType::UnloadComponents(); /** Exit and return the error code. */ return returndummy;