diff options
Diffstat (limited to 'zen/globals.h')
-rwxr-xr-x[-rw-r--r--] | zen/globals.h | 125 |
1 files changed, 61 insertions, 64 deletions
diff --git a/zen/globals.h b/zen/globals.h index 123028c7..a1fd2764 100644..100755 --- a/zen/globals.h +++ b/zen/globals.h @@ -1,64 +1,61 @@ -// ***************************************************************************** -// * This file is part of the FreeFileSync project. It is distributed under * -// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 * -// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved * -// ***************************************************************************** - -#ifndef GLOBALS_H_8013740213748021573485 -#define GLOBALS_H_8013740213748021573485 - -#include <atomic> -#include <memory> -#include "scope_guard.h" - -namespace zen -{ -//solve static destruction order fiasco by providing shared ownership and serialized access to global variables -template <class T> -class Global -{ -public: - Global() { static_assert(std::is_trivially_destructible<Pod>::value, "this memory needs to live forever"); } - explicit Global(std::unique_ptr<T>&& newInst) { set(std::move(newInst)); } - ~Global() { set(nullptr); } - - std::shared_ptr<T> get() //=> return std::shared_ptr to let instance life time be handled by caller (MT usage!) - { - while (pod.spinLock.exchange(true)) ; - ZEN_ON_SCOPE_EXIT(pod.spinLock = false); - if (pod.inst) - return *pod.inst; - return nullptr; - } - - void set(std::unique_ptr<T>&& newInst) - { - std::shared_ptr<T>* tmpInst = nullptr; - if (newInst) - tmpInst = new std::shared_ptr<T>(std::move(newInst)); - { - while (pod.spinLock.exchange(true)) ; - ZEN_ON_SCOPE_EXIT(pod.spinLock = false); - std::swap(pod.inst, tmpInst); - } - delete tmpInst; - } - -private: - //avoid static destruction order fiasco: there may be accesses to "Global<T>::get()" during process shutdown - //e.g. _("") used by message in debug_minidump.cpp or by some detached thread assembling an error message! - //=> use trivially-destructible POD only!!! - struct Pod - { - std::shared_ptr<T>* inst = nullptr; - //serialize access; can't use std::mutex: has non-trival destructor - std::atomic<bool> spinLock { false }; - } pod; -}; - -#if defined _MSC_VER && _MSC_VER < 1900 - #error function scope static initialization is not yet thread-safe! -#endif -} - -#endif //GLOBALS_H_8013740213748021573485 +// *****************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
+// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
+// *****************************************************************************
+
+#ifndef GLOBALS_H_8013740213748021573485
+#define GLOBALS_H_8013740213748021573485
+
+#include <atomic>
+#include <memory>
+#include "scope_guard.h"
+
+namespace zen
+{
+//solve static destruction order fiasco by providing shared ownership and serialized access to global variables
+template <class T>
+class Global
+{
+public:
+ Global() { static_assert(std::is_trivially_destructible<Pod>::value, "this memory needs to live forever"); }
+ explicit Global(std::unique_ptr<T>&& newInst) { set(std::move(newInst)); }
+ ~Global() { set(nullptr); }
+
+ std::shared_ptr<T> get() //=> return std::shared_ptr to let instance life time be handled by caller (MT usage!)
+ {
+ while (pod.spinLock.exchange(true)) ;
+ ZEN_ON_SCOPE_EXIT(pod.spinLock = false);
+ if (pod.inst)
+ return *pod.inst;
+ return nullptr;
+ }
+
+ void set(std::unique_ptr<T>&& newInst)
+ {
+ std::shared_ptr<T>* tmpInst = nullptr;
+ if (newInst)
+ tmpInst = new std::shared_ptr<T>(std::move(newInst));
+ {
+ while (pod.spinLock.exchange(true)) ;
+ ZEN_ON_SCOPE_EXIT(pod.spinLock = false);
+ std::swap(pod.inst, tmpInst);
+ }
+ delete tmpInst;
+ }
+
+private:
+ //avoid static destruction order fiasco: there may be accesses to "Global<T>::get()" during process shutdown
+ //e.g. _("") used by message in debug_minidump.cpp or by some detached thread assembling an error message!
+ //=> use trivially-destructible POD only!!!
+ struct Pod
+ {
+ std::shared_ptr<T>* inst = nullptr;
+ //serialize access; can't use std::mutex: has non-trival destructor
+ std::atomic<bool> spinLock { false };
+ } pod;
+};
+
+}
+
+#endif //GLOBALS_H_8013740213748021573485
|