Library of Assembled Shared Sources
singleton.inl
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2024 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43
44
45#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_SINGLETON_INL
46#define LASS_GUARDIAN_OF_INCLUSION_UTIL_SINGLETON_INL
47
48
49#include "singleton.h"
50#include "thread.h"
51#include <atomic>
52
53namespace lass
54{
55namespace util
56{
57
58
59template <class T, int DP>
60Singleton<T, DP>::Singleton():
61 impl::SingletonBase(),
62 instance_(new TInstance)
63{
64}
65
66
67
68template <class T, int DP>
69Singleton<T, DP>::~Singleton()
70{
71 deadReference(true);
72}
73
74
75
76/** Return pointer to singleton instance.
77 * An instance is created on first call.
78 * Return NULL if instance is dead already (after first destruction of singletons).
79 * @note this should be thread safe over all singletons.
80 */
81template <class T, int DP>
82typename Singleton<T, DP>::TInstance* Singleton<T, DP>::instance()
83{
84 static std::atomic<TSelf*> neo{ nullptr };
85 static std::atomic<int> semaphore{ 1 };
86
87 if (deadReference(false))
88 {
89 std::cerr << "[LASS RUN MSG] Dead reference detected at '" << neo.load(std::memory_order_relaxed)
90 << "' of singleton '" << typeid(TInstance).name() << "' with destruction priority '"
91 << destructionPriority << "'" << std::endl;
92 return nullptr;
93 }
94
95 TSelf* one = neo.load(std::memory_order_acquire);
96 if (!one)
97 {
98 LASS_LOCK_INTEGRAL(semaphore)
99 {
100 one = neo.load(std::memory_order_relaxed);
101 if (!one)
102 {
103 one = new TSelf;
104 one->subscribeInstance(destructionPriority);
105 neo.store(one, std::memory_order_release);
106 }
107 }
108 }
109 LASS_ASSERT(one);
110#if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
111# pragma warning(suppress: 6011) // Dereferencing NULL pointer 'one'
112#endif
113 return one->instance_.get();
114}
115
116
117
118/** return true if singleton is destructed.
119 * @param iSetReferenceToDead - call this method with true on destruction of singleton
120 * - call this method with false to check it.
121 */
122template <class T, int DP>
123bool Singleton<T, DP>::deadReference(bool setReferenceToDead)
124{
125 static std::atomic<int> dead{ false };
126 if (setReferenceToDead)
127 {
128 dead.store(true, std::memory_order_release);
129 return true;
130 }
131 else
132 {
133 return dead.load(std::memory_order_acquire);
134 }
135}
136
137
138}
139}
140
141#endif
static TInstance * instance()
Return pointer to singleton instance.
Definition singleton.inl:82
void subscribeInstance(int iDestructionPriority)
Subscribe to the singleton guard.
general utility, debug facilities, ...
Library for Assembled Shared Sources.
Definition config.h:53