5.1 作为全局对象的单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

struct Database
{
Database() {}
};

Database& get_database()
{
static Database database;
return database;
}

int main(void)
{
Database& sf = get_database();

return 0;
}

5.2 单例模式的经典实现

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
#include <iostream>
/*
struct Database
{
Database()
{
static int instance_count {0};
if (++instance_count > 1)
throw expection("Cannot make >1 database!");
}
};
*/

struct Database
{
protected:
Database(){}
public:
static Database& get()
{
// thread-safe since C++11
static Database database;
return database;
}
Database(Database const&) = delete;
Database(Database&&) = delete;
Database& operator=(Database const&) = delete;
Database& operator=(Database &&) = delete;
};
int main(void)
{
Database& k = Database::get();

return 0;
}

线程安全

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
#include <iostream>
#include <boost/atomic.hpp>
#include <boost/thread.hpp>

struct Database
{
// same members as before, but then...
static Database& instance();
private:
static boost::atomic<Database*> instance;
static boost::mutex mtx;
};

Database& Database::instance()
{
Database* db = instance.load(boost::memory_order_consume);
if (!db)
{
boost::mutex::scoped_lock lock(mtx);
db = instance.load(boost::memory_order_consume);
if (!db)
{
db = new Database();
instance.store(db, boost::memory_order_release);
}
}
}

int main(void)
{
Database& k;

return 0;
}

5.3 单例模式存在的问题

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <iostream>
#include <map>
#include <vector>

class Database
{
public:
virtual int get_population(const std::string& name) = 0;
};

class SingletonDatabase : public Database
{
SingletonDatabase() {/* read data from datebase*/
capitals["nk"] = 22;
capitals["uk"] = 30;
}
std::map<std::string, int> capitals;
public:
SingletonDatabase(SingletonDatabase const&) = delete;
void operator=(SingletonDatabase const&) = delete;

static SingletonDatabase& get()
{
static SingletonDatabase db;
return db;
}

int get_population(const std::string& name) override
{
return capitals[name];
}
};

struct SingletonRecordFinder
{
int total_population(std::vector<std::string> names)
{
int result = 0;
for (auto& name : names)
result += SingletonDatabase::get().get_population(name);
return result;
}
};

int main(void)
{
std::vector<std::string> names{"nk", "uk"};
SingletonRecordFinder find;
std::cout << find.total_population(names) << std::endl;
return 0;
}



-------------------------------------------------------------------------


#include <iostream>
#include <map>
#include <vector>
#include <memory>

class Database
{
public:
virtual int get_population(const std::string& name) = 0;
};
/*
class SingletonDatabase : public Database
{
SingletonDatabase() {/* read data from datebase*/
/* capitals["nk"] = 22;
capitals["uk"] = 30;
}
std::map<std::string, int> capitals;
public:
SingletonDatabase(SingletonDatabase const&) = delete;
void operator=(SingletonDatabase const&) = delete;

static SingletonDatabase& get()
{
static SingletonDatabase db;
return db;
}

int get_population(const std::string& name) override
{
return capitals[name];
}
};*/
/*
struct SingletonRecordFinder
{
int total_population(std::vector<std::string> names)
{
int result = 0;
for (auto& name : names)
result += SingletonDatabase::get().get_population(name);
return result;
}
};
*/

struct ConfigurableRecordFinder
{
explicit ConfigurableRecordFinder(Database& db)
: db{db} {}

int total_population(std::vector<std::string> names)
{
int result = 0;
for (auto& name : names)
result += db.get_population(name);
return result;
}

Database& db;
};

class DummyDatabase : public Database
{
std::map<std::string, int> capitals;
public:
DummyDatabase()
{
capitals["alpha"] = 1;
capitals["beta"] = 2;
capitals["gamma"] = 3;
}
int get_population(const std::string& name) override {
return capitals[name];
}
};

int main(void)
{
DummyDatabase kk;
ConfigurableRecordFinder find(kk);
std::vector<std::string> names{"alpha", "beta"};
std::cout << find.total_population(names) << std::endl;
return 0;
}

5.3.1 每线程单例

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
#include <iostream>
#include <thread>

class PerThreadSingleton
{
PerThreadSingleton()
{
id = std::this_thread::get_id();
}
public:
std::thread::id id;
static PerThreadSingleton& get()
{
thread_local PerThreadSingleton instance;
return instance;
}
};

int main(void)
{
std::thread t1([]()
{
// for (int i = 0; i < 1000; i++) std::cout << "xxx: " << i << std::endl;
std::cout << "t1: " << PerThreadSingleton::get().id << std::endl;
});
std::thread t2([]()
{
// for (int i = 0; i < 1000; i++) std::cout << "yyy: "<< i << std::endl;
std::cout << "t2: " << PerThreadSingleton::get().id << std::endl;
std::cout << "t2 again: " << PerThreadSingleton::get().id << std::endl;
});

t1.join();
t2.join();
return 0;
}

5.3.2 环境上下文

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
#include <iostream>
#include <stack>

class BuildingContext final
{
public:
int height{0};
BuildingContext() = default;
static std::stack<BuildingContext> Stack;
std::stack<BuildingContext> BuildingContext::Stack({BuildingContext{}});
};

static BuildingContext current()
{
return Stack.top();
}


class Token
{
public:
~Token()
{
if (Stack.size() > 1) Stack.pop();
}
};

static Token with_height(int height)
{
auto copy = current();
copy.height = height;
Stack.push(copy);
return Token{};
}


int main(void)
{
return 0;
}