From 8d66e8a2b8cfe4eef4b946a1ab64354dfd7da00b Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Sat, 29 Oct 2016 11:34:19 +0200 Subject: 8.4 --- zen/globals.h | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 zen/globals.h (limited to 'zen/globals.h') diff --git a/zen/globals.h b/zen/globals.h new file mode 100644 index 00000000..5f3dd64a --- /dev/null +++ b/zen/globals.h @@ -0,0 +1,57 @@ +// ***************************************************************************** +// * 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 +#include +#include "scope_guard.h" + +namespace zen +{ +//solve static destruction order fiasco by providing scoped ownership and serialized access to global variables +template +class Global +{ +public: + Global() {} + explicit Global(std::unique_ptr&& newInst) { set(std::move(newInst)); } + ~Global() { set(nullptr); } + + std::shared_ptr get() //=> return std::shared_ptr to let instance life time be handled by caller (MT usage!) + { + while (spinLock.exchange(true)) ; + ZEN_ON_SCOPE_EXIT(spinLock = false); + if (inst) + return *inst; + return nullptr; + } + + void set(std::unique_ptr&& newInst) + { + std::shared_ptr* tmpInst = nullptr; + if (newInst) + tmpInst = new std::shared_ptr(std::move(newInst)); + { + while (spinLock.exchange(true)) ; + ZEN_ON_SCOPE_EXIT(spinLock = false); + std::swap(inst, tmpInst); + } + delete tmpInst; + } + +private: + //avoid static destruction order fiasco: there may be accesses to "Global::get()" during process shutdown + //e.g. show message in debug_minidump.cpp or some detached thread assembling an error message! + //=> use trivially-destructible POD only!!! + std::shared_ptr* inst = nullptr; + //serialize access: can't use std::mutex because of non-trival destructor + std::atomic spinLock { false }; +}; +} + +#endif //GLOBALS_H_8013740213748021573485 -- cgit