blob: 5f3dd64aa7bf023dd6bf50a25d722cd9f79e05a5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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 <atomic>
#include <memory>
#include "scope_guard.h"
namespace zen
{
//solve static destruction order fiasco by providing scoped ownership and serialized access to global variables
template <class T>
class Global
{
public:
Global() {}
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 (spinLock.exchange(true)) ;
ZEN_ON_SCOPE_EXIT(spinLock = false);
if (inst)
return *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 (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<T>::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<T>* inst = nullptr;
//serialize access: can't use std::mutex because of non-trival destructor
std::atomic<bool> spinLock { false };
};
}
#endif //GLOBALS_H_8013740213748021573485
|