1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
/*=========================================================================
*
* Copyright NumFOCUS
*
* 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
*
* https://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.
*
*=========================================================================*/
#ifndef itkSingleton_h
#define itkSingleton_h
#include "itkMacro.h"
#include "itkSingletonMacro.h"
#include <map>
#include <functional>
#ifndef ITK_FUTURE_LEGACY_REMOVE
/** \brief A function which does nothing
* \deprecated Preferably use the C++ `[[maybe_unused]]` attribute instead!
*
* This function is to be used to mark parameters as unused to suppress
* compiler warning. It can be used when the parameter needs to be named
* (i.e. itkNotUsed cannot be used) but is not always used.
*/
template <typename T>
[[deprecated("Preferably use the C++ `[[maybe_unused]]` attribute instead!")]] inline void
Unused(const T &){};
#endif
namespace itk
{
/** \class SingletonIndex
* \brief Implementation detail.
*
* \ingroup ITKCommon
*/
class ITKCommon_EXPORT SingletonIndex
{
public:
/** Standard class types. */
using Self = SingletonIndex;
#ifndef ITK_LEGACY_REMOVE
using SingletonData [[deprecated("The internal representation of the singleton data is private, and may not "
"correspond with SingletonData anymore.")]] =
std::map<std::string, std::tuple<void *, std::function<void(void *)>, std::function<void()>>>;
#endif
// obtain a global registered in the singleton index under the
// globalName, if unknown then nullptr will be returned.
template <typename T>
T *
GetGlobalInstance(const char * globalName)
{
return static_cast<T *>(this->GetGlobalInstancePrivate(globalName));
}
// It is assumed that the global will remain valid until the start
// of globals being destroyed.
template <typename T>
void
SetGlobalInstance(const char * globalName, T * global, std::function<void()> deleteFunc)
{
this->SetGlobalInstancePrivate(globalName, GlobalObject{ global, std::move(deleteFunc) });
}
#ifndef ITK_FUTURE_LEGACY_REMOVE
template <typename T>
[[deprecated("Prefer calling the SetGlobalInstance(globalName, global, deleteFunc) overload (without the unused func "
"parameter)!")]] bool
SetGlobalInstance(const char * globalName,
T * global,
std::function<void(void *)> itkNotUsed(func),
std::function<void()> deleteFunc)
{
this->SetGlobalInstance(globalName, global, std::move(deleteFunc));
// Just returns true for backward compatibility (legacy only).
return true;
}
#endif
/** Set/Get the pointer to GlobalSingleton.
* Note that SetGlobalSingleton is not concurrent thread safe. */
static Self *
GetInstance();
static void
SetInstance(Self * instance);
~SingletonIndex();
private:
// Internal struct to store the instance pointer and the delete function object of a global object.
struct GlobalObject
{
void * Instance{};
std::function<void()> DeleteFunc{};
};
// may return nullptr if string is not registered already
//
// access something like a std::map<std::string, void *> or
// registered globals, it may be possible to restrict the held
// classes to be derived from itk::LightObject, so dynamic cast can
// work, and could use some type of Holder<T> class for intrinsic types
void *
GetGlobalInstancePrivate(const char * globalName);
// global is added or set to the singleton index under globalName
void
SetGlobalInstancePrivate(const char * globalName, GlobalObject globalObject);
/** The static GlobalSingleton. This is initialized to nullptr as the first
* stage of static initialization. It is then populated on the first call to
* itk::Singleton::Modified() but it can be overridden with SetGlobalSingleton().
* */
std::map<std::string, GlobalObject> m_GlobalObjects;
static Self * m_Instance;
// static SingletonIndexPrivate * m_GlobalSingleton;
};
// A wrapper for a global variable registered in the singleton index.
template <typename T>
T *
Singleton(const char * globalName, std::function<void()> deleteFunc)
{
[[maybe_unused]] static SingletonIndex * singletonIndex = SingletonIndex::GetInstance();
T * instance = SingletonIndex::GetInstance()->GetGlobalInstance<T>(globalName);
if (instance == nullptr)
{
instance = new T;
SingletonIndex::GetInstance()->SetGlobalInstance<T>(globalName, instance, std::move(deleteFunc));
}
return instance;
}
#ifndef ITK_FUTURE_LEGACY_REMOVE
template <typename T>
[[deprecated("Prefer calling the Singleton(globalName, deleteFunc) overload (without the unused func parameter)!")]] T *
Singleton(const char * globalName, std::function<void(void *)> itkNotUsed(func), std::function<void()> deleteFunc)
{
return Singleton<T>(globalName, std::move(deleteFunc));
}
#endif
} // end namespace itk
#endif
|