// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // /* * This header is not meant to be included in a .h file. * Complain if we see this header twice through. */ #ifdef PXR_BASE_TF_INSTANTIATE_SINGLETON_H #error This file should only be included once in any given source (.cpp) file. #endif #define PXR_BASE_TF_INSTANTIATE_SINGLETON_H /// \file tf/instantiateSingleton.h /// \ingroup group_tf_ObjectCreation /// Manage a single instance of an object. #include "pxr/pxr.h" #include "pxr/base/tf/singleton.h" #include "pxr/base/tf/mallocTag.h" #include "pxr/base/arch/demangle.h" PXR_NAMESPACE_OPEN_SCOPE template std::mutex* TfSingleton::_mutex = 0; template T* TfSingleton::_instance = 0; template T& TfSingleton::_CreateInstance() { // Why is TfSingleton::_mutex a pointer requiring allocation and // construction and not simply an object? Because the default // std::mutex c'tor on MSVC 2015 isn't constexpr . That means the // mutex is dynamically initialized. That can be too late for // singletons, which are often accessed via ARCH_CONSTRUCTOR() // functions. static std::once_flag once; std::call_once(once, [](){ TfSingleton::_mutex = new std::mutex; }); TfAutoMallocTag2 tag2("Tf", "TfSingleton::_CreateInstance"); TfAutoMallocTag tag("Create Singleton " + ArchGetDemangled()); std::lock_guard lock(*TfSingleton::_mutex); if (!TfSingleton::_instance) { ARCH_PRAGMA_PUSH ARCH_PRAGMA_MAY_NOT_BE_ALIGNED T *inst = new T; ARCH_PRAGMA_POP // T's constructor could cause this to be created and set // already, so guard against that. if (!TfSingleton::_instance) { TfSingleton::_instance = inst; } } return *TfSingleton::_instance; } template void TfSingleton::_DestroyInstance() { std::lock_guard lock(*TfSingleton::_mutex); delete TfSingleton::_instance; TfSingleton::_instance = 0; } /// Source file definition that a type is being used as a singleton. /// /// To use a type \c T in conjunction with \c TfSingleton, add /// TF_INSTANTIATE_SINGLETON(T) in one source file (typically the .cpp) file /// for class \c T. /// /// \hideinitializer #define TF_INSTANTIATE_SINGLETON(T) \ template class PXR_NS_GLOBAL::TfSingleton PXR_NAMESPACE_CLOSE_SCOPE