Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:46

0001 // MIT License
0002 //
0003 // Copyright (c) 2020 Jonathan R. Madsen
0004 //
0005 // Permission is hereby granted, free of charge, to any person obtaining a copy
0006 // of this software and associated documentation files (the "Software"), to deal
0007 // in the Software without restriction, including without limitation the rights
0008 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0009 // copies of the Software, and to permit persons to whom the Software is
0010 // furnished to do so, subject to the following conditions:
0011 //
0012 // The above copyright notice and this permission notice shall be included in
0013 // all copies or substantial portions of the Software.
0014 //
0015 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0018 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0019 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0020 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0021 // SOFTWARE.
0022 //
0023 //
0024 
0025 #pragma once
0026 
0027 #include <atomic>
0028 #include <functional>
0029 #include <memory>
0030 #include <mutex>
0031 #include <set>
0032 #include <thread>
0033 #include <type_traits>
0034 
0035 namespace PTL
0036 {
0037 /// \class PTL::Singleton
0038 /// \brief Singleton object that allows a deleter class to be specified
0039 ///
0040 template <typename Type,
0041           typename PointerT = std::unique_ptr<Type, std::default_delete<Type>>>
0042 class Singleton
0043 {
0044 public:
0045     using this_type     = Singleton<Type, PointerT>;
0046     using thread_id_t   = std::thread::id;
0047     using mutex_t       = std::recursive_mutex;
0048     using auto_lock_t   = std::unique_lock<mutex_t>;
0049     using pointer       = Type*;
0050     using list_t        = std::set<pointer>;
0051     using smart_pointer = PointerT;
0052     using deleter_t     = std::function<void(PointerT&)>;
0053 
0054     template <bool B, typename T = int>
0055     using enable_if_t = typename std::enable_if<B, T>::type;
0056 
0057 public:
0058     // Constructor and Destructors
0059     Singleton();
0060     Singleton(pointer);
0061     ~Singleton();
0062 
0063     Singleton(const Singleton&) = delete;
0064     Singleton(Singleton&&)      = delete;
0065     Singleton& operator=(const Singleton&) = delete;
0066     Singleton& operator=(Singleton&&) = delete;
0067 
0068 public:
0069     // public static functions
0070     static pointer     GetInstance();
0071     static pointer     GetMasterInstance();
0072     static thread_id_t GetMasterThreadID() { return f_master_thread(); }
0073     static list_t      Children() { return f_children(); }
0074     static bool        IsMaster(pointer ptr) { return ptr == GetRawMasterInstance(); }
0075     static bool        IsMasterThread();
0076     static void        Insert(pointer);
0077     static void        Remove(pointer);
0078     static mutex_t&    GetMutex() { return f_mutex(); }
0079 
0080 public:
0081     // public member function
0082     void Initialize();
0083     void Initialize(pointer);
0084     void Destroy();
0085     void Reset(pointer);
0086     void Reset();
0087 
0088     // since we are overloading delete we overload new
0089     void* operator new(size_t)
0090     {
0091         this_type* ptr = ::new this_type();
0092         return static_cast<void*>(ptr);
0093     }
0094 
0095     // overload delete so that f_master_instance is guaranteed to be
0096     // a nullptr after deletion
0097     void operator delete(void* ptr)
0098     {
0099         this_type* _instance = (this_type*) (ptr);
0100         ::delete _instance;
0101         if(std::this_thread::get_id() == f_master_thread())
0102             f_master_instance() = nullptr;
0103     }
0104 
0105 protected:
0106     friend class Type;
0107 
0108     // instance functions that do not Initialize
0109     smart_pointer&        GetSmartInstance() { return _local_instance(); }
0110     static smart_pointer& GetSmartMasterInstance() { return _master_instance(); }
0111 
0112     // for checking but not allocating
0113     pointer GetRawInstance()
0114     {
0115         return IsMasterThread() ? f_master_instance() : _local_instance().get();
0116     }
0117     static pointer GetRawMasterInstance() { return f_master_instance(); }
0118 
0119 private:
0120     // Private functions
0121     static smart_pointer& _local_instance()
0122     {
0123         static thread_local smart_pointer _instance = smart_pointer();
0124         return _instance;
0125     }
0126 
0127     static smart_pointer& _master_instance()
0128     {
0129         static smart_pointer _instance = smart_pointer();
0130         return _instance;
0131     }
0132 
0133     void* operator new[](std::size_t) noexcept { return nullptr; }
0134     void  operator delete[](void*) noexcept {}
0135 
0136     template <typename Tp = Type, typename PtrT = PointerT,
0137               enable_if_t<(std::is_same<PtrT, std::shared_ptr<Tp>>::value)> = 0>
0138     deleter_t& GetDeleter()
0139     {
0140         static deleter_t _instance = [](PointerT&) {};
0141         return _instance;
0142     }
0143 
0144     template <typename Tp = Type, typename PtrT = PointerT,
0145               enable_if_t<!(std::is_same<PtrT, std::shared_ptr<Tp>>::value)> = 0>
0146     deleter_t& GetDeleter()
0147     {
0148         static deleter_t _instance = [](PointerT& _master) {
0149             auto& del = _master.get_deleter();
0150             del(_master.get());
0151             _master.reset(nullptr);
0152         };
0153         return _instance;
0154     }
0155 
0156 private:
0157     // Private variables
0158     struct persistent_data
0159     {
0160         thread_id_t m_master_thread = std::this_thread::get_id();
0161         mutex_t     m_mutex;
0162         pointer     m_master_instance = nullptr;
0163         list_t      m_children        = {};
0164 
0165         persistent_data()                       = default;
0166         ~persistent_data()                      = default;
0167         persistent_data(const persistent_data&) = delete;
0168         persistent_data(persistent_data&&)      = delete;
0169         persistent_data& operator=(const persistent_data&) = delete;
0170         persistent_data& operator=(persistent_data&&) = delete;
0171 
0172         persistent_data(pointer _master, std::thread::id _tid)
0173         : m_master_thread(_tid)
0174         , m_master_instance(_master)
0175         {}
0176 
0177         void reset()
0178         {
0179             m_master_instance = nullptr;
0180             m_children.clear();
0181         }
0182     };
0183 
0184     bool                m_IsMaster = false;
0185     static thread_id_t& f_master_thread();
0186     static mutex_t&     f_mutex();
0187     static pointer&     f_master_instance();
0188     static list_t&      f_children();
0189 
0190     static persistent_data& f_persistent_data()
0191     {
0192         static persistent_data _instance;
0193         return _instance;
0194     }
0195 };
0196 
0197 //======================================================================================//
0198 
0199 template <typename Type, typename PointerT>
0200 typename Singleton<Type, PointerT>::thread_id_t&
0201 Singleton<Type, PointerT>::f_master_thread()
0202 {
0203     return f_persistent_data().m_master_thread;
0204 }
0205 
0206 //--------------------------------------------------------------------------------------//
0207 
0208 template <typename Type, typename PointerT>
0209 typename Singleton<Type, PointerT>::pointer&
0210 Singleton<Type, PointerT>::f_master_instance()
0211 {
0212     return f_persistent_data().m_master_instance;
0213 }
0214 
0215 //--------------------------------------------------------------------------------------//
0216 
0217 template <typename Type, typename PointerT>
0218 typename Singleton<Type, PointerT>::mutex_t&
0219 Singleton<Type, PointerT>::f_mutex()
0220 {
0221     return f_persistent_data().m_mutex;
0222 }
0223 
0224 //--------------------------------------------------------------------------------------//
0225 
0226 template <typename Type, typename PointerT>
0227 typename Singleton<Type, PointerT>::list_t&
0228 Singleton<Type, PointerT>::f_children()
0229 {
0230     return f_persistent_data().m_children;
0231 }
0232 
0233 //--------------------------------------------------------------------------------------//
0234 
0235 template <typename Type, typename PointerT>
0236 Singleton<Type, PointerT>::Singleton()
0237 {
0238     Initialize();
0239 }
0240 
0241 //--------------------------------------------------------------------------------------//
0242 
0243 template <typename Type, typename PointerT>
0244 Singleton<Type, PointerT>::Singleton(pointer ptr)
0245 {
0246     Initialize(ptr);
0247 }
0248 
0249 //--------------------------------------------------------------------------------------//
0250 
0251 template <typename Type, typename PointerT>
0252 Singleton<Type, PointerT>::~Singleton()
0253 {
0254     auto& del = GetDeleter();
0255     del(_master_instance());
0256 }
0257 
0258 //--------------------------------------------------------------------------------------//
0259 
0260 template <typename Type, typename PointerT>
0261 void
0262 Singleton<Type, PointerT>::Initialize()
0263 {
0264     if(!f_master_instance())
0265     {
0266         f_master_thread()   = std::this_thread::get_id();
0267         f_master_instance() = new Type();
0268     }
0269 }
0270 
0271 //--------------------------------------------------------------------------------------//
0272 
0273 template <typename Type, typename PointerT>
0274 void
0275 Singleton<Type, PointerT>::Initialize(pointer ptr)
0276 {
0277     if(!f_master_instance())
0278     {
0279         f_master_thread()   = std::this_thread::get_id();
0280         f_master_instance() = ptr;
0281     }
0282 }
0283 
0284 //--------------------------------------------------------------------------------------//
0285 
0286 template <typename Type, typename PointerT>
0287 void
0288 Singleton<Type, PointerT>::Destroy()
0289 {
0290     if(std::this_thread::get_id() == f_master_thread() && f_master_instance())
0291     {
0292         delete f_master_instance();
0293         f_master_instance() = nullptr;
0294     }
0295     else
0296     {
0297         remove(_local_instance().get());
0298     }
0299 }
0300 
0301 //--------------------------------------------------------------------------------------//
0302 
0303 template <typename Type, typename PointerT>
0304 typename Singleton<Type, PointerT>::pointer
0305 Singleton<Type, PointerT>::GetInstance()
0306 {
0307     if(std::this_thread::get_id() == f_master_thread())
0308         return GetMasterInstance();
0309     else if(!_local_instance().get())
0310     {
0311         _local_instance().reset(new Type());
0312         Insert(_local_instance().get());
0313     }
0314     return _local_instance().get();
0315 }
0316 
0317 //--------------------------------------------------------------------------------------//
0318 
0319 template <typename Type, typename PointerT>
0320 typename Singleton<Type, PointerT>::pointer
0321 Singleton<Type, PointerT>::GetMasterInstance()
0322 {
0323     if(!f_master_instance())
0324     {
0325         f_master_thread()   = std::this_thread::get_id();
0326         f_master_instance() = new Type();
0327     }
0328     return f_master_instance();
0329 }
0330 
0331 //--------------------------------------------------------------------------------------//
0332 
0333 template <typename Type, typename PointerT>
0334 void
0335 Singleton<Type, PointerT>::Reset(pointer ptr)
0336 {
0337     if(IsMaster(ptr))
0338     {
0339         if(_master_instance().get())
0340             _master_instance().reset();
0341         else if(f_master_instance())
0342         {
0343             auto& del = GetDeleter();
0344             del(_master_instance());
0345             f_master_instance() = nullptr;
0346         }
0347         f_persistent_data().reset();
0348     }
0349     else
0350     {
0351         _local_instance().reset();
0352     }
0353 }
0354 
0355 //--------------------------------------------------------------------------------------//
0356 
0357 template <typename Type, typename PointerT>
0358 void
0359 Singleton<Type, PointerT>::Reset()
0360 {
0361     if(IsMasterThread())
0362         _master_instance().reset();
0363     _local_instance().reset();
0364     f_persistent_data().reset();
0365 }
0366 
0367 //--------------------------------------------------------------------------------------//
0368 
0369 template <typename Type, typename PointerT>
0370 bool
0371 Singleton<Type, PointerT>::IsMasterThread()
0372 {
0373     return std::this_thread::get_id() == f_master_thread();
0374 }
0375 
0376 //--------------------------------------------------------------------------------------//
0377 
0378 template <typename Type, typename PointerT>
0379 void
0380 Singleton<Type, PointerT>::Insert(pointer itr)
0381 {
0382     auto_lock_t l(f_mutex());
0383     f_children().insert(itr);
0384 }
0385 
0386 //--------------------------------------------------------------------------------------//
0387 
0388 template <typename Type, typename PointerT>
0389 void
0390 Singleton<Type, PointerT>::Remove(pointer itr)
0391 {
0392     auto_lock_t l(f_mutex());
0393     for(auto litr = f_children().begin(); litr != f_children().end(); ++litr)
0394     {
0395         if(*litr == itr)
0396         {
0397             f_children().erase(litr);
0398             break;
0399         }
0400     }
0401 }
0402 
0403 //--------------------------------------------------------------------------------------//
0404 
0405 }  // namespace PTL