aboutsummaryrefslogtreecommitdiff
path: root/dep/include/zthread/Singleton.h
diff options
context:
space:
mode:
Diffstat (limited to 'dep/include/zthread/Singleton.h')
-rw-r--r--dep/include/zthread/Singleton.h249
1 files changed, 249 insertions, 0 deletions
diff --git a/dep/include/zthread/Singleton.h b/dep/include/zthread/Singleton.h
new file mode 100644
index 00000000000..b66c9d0898a
--- /dev/null
+++ b/dep/include/zthread/Singleton.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTSINGLETON_H__
+#define __ZTSINGLETON_H__
+
+#include "zthread/Guard.h"
+#include "zthread/FastMutex.h"
+#include <assert.h>
+
+namespace ZThread {
+
+//
+// This policy controls how an object is instantiated
+// as well as how and when its destroyed. Phoenix-style
+// singletons are not supported easily with type of policy,
+// this is intentional since I do not believe that is in
+// the true spirit of a singleton.
+//
+// InstantiationPolicContract {
+//
+// create(pointer_type&)
+//
+// }
+
+/**
+ * @class LocalStaticInstantiation
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T17:57:45-0400>
+ * @version 2.2.0
+ *
+ * The LocalStaticInstantiation policy allows the creation
+ * and lifetime of an instance of a particular type
+ * to be managed using static local values. This will
+ * abide by the standard C++ rules for static objects
+ * lifetimes.
+ */
+class LocalStaticInstantiation {
+protected:
+
+ /**
+ * Create an instance of an object, using a local static. The
+ * object will be destroyed by the system.
+ *
+ * @param ptr reference to location to receive the address
+ * of the allocated object
+ */
+ template <class T>
+ static void create(T*& ptr) {
+
+ static T instance;
+ ptr = &instance;
+
+ }
+
+};
+
+//! Helper class
+template <class T>
+class StaticInstantiationHelper {
+ //! Friend class
+ friend class StaticInstantiation;
+ //! Holder
+ static T instance;
+
+ };
+
+ template <class T>
+ T StaticInstantiationHelper<T>::instance;
+
+/**
+ * @class StaticInstantiation
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T17:57:45-0400>
+ * @version 2.2.0
+ *
+ * The StaticInstantiation policy allows the creation
+ * and lifetime of an instance of a particular type
+ * to be managed using static instantiation. This will
+ * abide by the standard C++ rules for static objects
+ * lifetimes.
+ */
+class StaticInstantiation {
+protected:
+
+ /**
+ * Create an instance of an object using by simply allocating it statically.
+ *
+ * @param ptr reference to location to receive the address
+ * of the allocated object
+ */
+ template <class T>
+ static void create(T*& ptr) {
+ ptr = &StaticInstantiationHelper<T>::instance;
+ }
+
+};
+
+//! SingletonDestroyer
+template <class T>
+class Destroyer {
+
+ T* doomed;
+
+ public:
+
+ Destroyer(T* q) : doomed(q) {
+ assert(doomed);
+ }
+
+ ~Destroyer();
+
+};
+
+template <class T>
+Destroyer<T>::~Destroyer() {
+
+ try {
+
+ if(doomed)
+ delete doomed;
+
+ } catch(...) { }
+
+ doomed = 0;
+
+}
+
+
+/**
+ * @class LazyInstantiation
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T17:57:45-0400>
+ * @version 2.2.0
+ *
+ * The LazyInstantiation policy allows the creation
+ * and lifetime of an instance of a particular type
+ * to be managed using dynamic allocation and a singleton
+ * destroyer. This will abide by the standard C++ rules
+ * for static objects lifetimes.
+ */
+class LazyInstantiation {
+protected:
+
+ /**
+ * Create an instance of an object, using new, that will be
+ * destroyed when an associated Destroyer object (allocated
+ * statically) goes out of scope.
+ *
+ * @param ptr reference to location to receive the address
+ * of the allocated object
+ */
+ template <class T>
+ static void create(T*& ptr) {
+
+ ptr = new T;
+ static Destroyer<T> destroyer(ptr);
+
+ }
+
+};
+
+
+/**
+ * @class Singleton
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T17:57:45-0400>
+ * @version 2.2.0
+ *
+ * Based on the work of John Vlissidles in his book 'Pattern Hatching'
+ * an article by Douglas Schmidtt on double-checked locking and policy
+ * templates described by Andrei Alexandrescu.
+ *
+ * This is a thread safe wrapper for creating Singleton classes. The
+ * synchronization method and instantiation methods can be changed
+ * easily by specifying different policy implementations as the
+ * templates parameters.
+ *
+ * @code
+ *
+ * // Most common Singleton
+ * Singletion<LonesomeType>
+ *
+ * // Singleton that uses static storage
+ * Singletion<LonesomeType, StaticInstantiation>
+ *
+ * // Single-threaded singleton that uses static storage (Meyers-like)
+ * Singletion<LonesomeType, LocalStaticInstantiation, NotLocked>
+ *
+ * @endcode
+ */
+template <class T, class InstantiationPolicy=LazyInstantiation, class LockType=FastMutex>
+class Singleton : private InstantiationPolicy, private NonCopyable {
+public:
+
+ /**
+ * Provide access to the single instance through double-checked locking
+ *
+ * @return T* single instance
+ */
+ static T* instance();
+
+};
+
+template <class T, class InstantiationPolicy, class LockType>
+T* Singleton<T, InstantiationPolicy, LockType>::instance() {
+
+ // Uses local static storage to avoid static construction
+ // sequence issues. (regaring when the lock is created)
+ static T* ptr = 0;
+ static LockType lock;
+
+ if(!ptr) {
+
+ Guard<LockType, LockedScope> g(lock);
+ if(!ptr)
+ InstantiationPolicy::create(ptr);
+
+ }
+
+ return const_cast<T*>(ptr);
+
+ }
+
+
+};
+
+#endif
+
+