1 | // (C) Copyright 2012 Vicente Botet |
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #define BOOST_THREAD_VERSION 4 |
7 | |
8 | #include <iostream> |
9 | #include <string> |
10 | #include <boost/thread/synchronized_value.hpp> |
11 | |
12 | //class SafePerson { |
13 | //public: |
14 | // std::string GetName() const { |
15 | // const_unique_access<std::string> name(nameGuard); |
16 | // return *name; |
17 | // } |
18 | // void SetName(const std::string& newName) { |
19 | // unique_access<std::string> name(nameGuard); |
20 | // *name = newName; |
21 | // } |
22 | //private: |
23 | // unique_access_guard<std::string> nameGuard; |
24 | //}; |
25 | |
26 | class SafePerson { |
27 | public: |
28 | std::string GetName() const { |
29 | return *name; |
30 | } |
31 | void SetName(const std::string& newName) { |
32 | *name = newName; |
33 | } |
34 | |
35 | private: |
36 | boost::synchronized_value<std::string> name; |
37 | }; |
38 | |
39 | class Person { |
40 | public: |
41 | std::string GetName() const { |
42 | return name; |
43 | } |
44 | void SetName(const std::string& newName) { |
45 | name = newName; |
46 | } |
47 | private: |
48 | std::string name; |
49 | }; |
50 | typedef boost::synchronized_value<Person> Person_ts; |
51 | |
52 | |
53 | //class SafeMemberPerson { |
54 | //public: |
55 | // SafeMemberPerson(unsigned int age) : |
56 | // memberGuard(age) |
57 | // { } |
58 | // std::string GetName() const { |
59 | // const_unique_access<Member> member(memberGuard); |
60 | // return member->name; |
61 | // } |
62 | // void SetName(const std::string& newName) { |
63 | // unique_access<Member> member(memberGuard); |
64 | // member->name = newName; |
65 | // } |
66 | //private: |
67 | // struct Member |
68 | // { |
69 | // Member(unsigned int age) : |
70 | // age(age) |
71 | // { } |
72 | // std::string name; |
73 | // unsigned int age; |
74 | // }; |
75 | // unique_access_guard<Member> memberGuard; |
76 | //}; |
77 | |
78 | class SafeMemberPerson { |
79 | public: |
80 | SafeMemberPerson(unsigned int age) : |
81 | member(Member(age)) |
82 | { } |
83 | std::string GetName() const { |
84 | return member->name; |
85 | } |
86 | void SetName(const std::string& newName) { |
87 | member->name = newName; |
88 | } |
89 | private: |
90 | struct Member { |
91 | Member(unsigned int age) : |
92 | age(age) |
93 | { } |
94 | std::string name; |
95 | unsigned int age; |
96 | }; |
97 | boost::synchronized_value<Member> member; |
98 | }; |
99 | |
100 | |
101 | class Person2 { |
102 | public: |
103 | Person2(unsigned int age) : age_(age) |
104 | {} |
105 | std::string GetName() const { |
106 | return name_; |
107 | } |
108 | void SetName(const std::string& newName) { |
109 | name_ = newName; |
110 | } |
111 | unsigned int GetAge() const { |
112 | return age_; |
113 | } |
114 | |
115 | private: |
116 | std::string name_; |
117 | unsigned int age_; |
118 | }; |
119 | typedef boost::synchronized_value<Person2> Person2_ts; |
120 | |
121 | //=================== |
122 | |
123 | //class HelperPerson { |
124 | //public: |
125 | // HelperPerson(unsigned int age) : |
126 | // memberGuard(age) |
127 | // { } |
128 | // std::string GetName() const { |
129 | // const_unique_access<Member> member(memberGuard); |
130 | // Invariant(member); |
131 | // return member->name; |
132 | // } |
133 | // void SetName(const std::string& newName) { |
134 | // unique_access<Member> member(memberGuard); |
135 | // Invariant(member); |
136 | // member->name = newName; |
137 | // } |
138 | //private: |
139 | // void Invariant(const_unique_access<Member>& member) const { |
140 | // if (member->age < 0) throw std::runtime_error("Age cannot be negative"); |
141 | // } |
142 | // struct Member { |
143 | // Member(unsigned int age) : |
144 | // age(age) |
145 | // { } |
146 | // std::string name; |
147 | // unsigned int age; |
148 | // }; |
149 | // unique_access_guard<Member> memberGuard; |
150 | //}; |
151 | |
152 | class HelperPerson { |
153 | public: |
154 | HelperPerson(unsigned int age) : |
155 | member(age) |
156 | { } |
157 | std::string GetName() const { |
158 | #if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS |
159 | auto memberSync = member.synchronize(); |
160 | #else |
161 | boost::const_strict_lock_ptr<Member> memberSync = member.synchronize(); |
162 | #endif |
163 | Invariant(mbr&: memberSync); |
164 | return memberSync->name; |
165 | } |
166 | void SetName(const std::string& newName) { |
167 | #if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS |
168 | auto memberSync = member.synchronize(); |
169 | #else |
170 | boost::strict_lock_ptr<Member> memberSync = member.synchronize(); |
171 | #endif |
172 | Invariant(mbr&: memberSync); |
173 | memberSync->name = newName; |
174 | } |
175 | private: |
176 | struct Member { |
177 | Member(unsigned int age) : |
178 | age(age) |
179 | { } |
180 | std::string name; |
181 | unsigned int age; |
182 | }; |
183 | void Invariant(boost::const_strict_lock_ptr<Member> & mbr) const |
184 | { |
185 | if (mbr->age < 1) throw std::runtime_error("Age cannot be negative" ); |
186 | } |
187 | boost::synchronized_value<Member> member; |
188 | }; |
189 | |
190 | class Person3 { |
191 | public: |
192 | Person3(unsigned int age) : |
193 | age_(age) |
194 | { } |
195 | std::string GetName() const { |
196 | Invariant(); |
197 | return name_; |
198 | } |
199 | void SetName(const std::string& newName) { |
200 | Invariant(); |
201 | name_ = newName; |
202 | } |
203 | private: |
204 | std::string name_; |
205 | unsigned int age_; |
206 | void Invariant() const { |
207 | if (age_ < 1) throw std::runtime_error("Age cannot be negative" ); |
208 | } |
209 | }; |
210 | |
211 | typedef boost::synchronized_value<Person3> Person3_ts; |
212 | |
213 | int main() |
214 | { |
215 | { |
216 | SafePerson p; |
217 | p.SetName("Vicente" ); |
218 | } |
219 | { |
220 | Person_ts p; |
221 | p->SetName("Vicente" ); |
222 | } |
223 | { |
224 | SafeMemberPerson p(1); |
225 | p.SetName("Vicente" ); |
226 | } |
227 | { |
228 | Person2_ts p(1); |
229 | p->SetName("Vicente" ); |
230 | } |
231 | { |
232 | HelperPerson p(1); |
233 | p.SetName("Vicente" ); |
234 | } |
235 | { |
236 | Person3_ts p(1); |
237 | p->SetName("Vicente" ); |
238 | } |
239 | { |
240 | Person3_ts p1(1); |
241 | Person3_ts p2(2); |
242 | Person3_ts p3(3); |
243 | #if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS |
244 | auto lk1 = p1.unique_synchronize(tag: boost::defer_lock); |
245 | auto lk2 = p2.unique_synchronize(tag: boost::defer_lock); |
246 | auto lk3 = p3.unique_synchronize(tag: boost::defer_lock); |
247 | #else |
248 | boost::unique_lock_ptr<Person3> lk1 = p1.unique_synchronize(boost::defer_lock); |
249 | boost::unique_lock_ptr<Person3> lk2 = p2.unique_synchronize(boost::defer_lock); |
250 | boost::unique_lock_ptr<Person3> lk3 = p3.unique_synchronize(boost::defer_lock); |
251 | #endif |
252 | boost::lock(m1&: lk1,m2&: lk2,m3&: lk3); |
253 | |
254 | lk1->SetName("Carmen" ); |
255 | lk2->SetName("Javier" ); |
256 | lk3->SetName("Matias" ); |
257 | } |
258 | #if ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS \ |
259 | && ! defined(BOOST_THREAD_NO_SYNCHRONIZE) |
260 | { |
261 | Person3_ts p1(1); |
262 | Person3_ts p2(2); |
263 | Person3_ts p3(3); |
264 | |
265 | auto t = boost::synchronize(sv&: p1,sv&: p2,sv&: p3); |
266 | std::get<0>(t&: t)->SetName("Carmen" ); |
267 | std::get<1>(t&: t)->SetName("Javier" ); |
268 | std::get<2>(t&: t)->SetName("Matias" ); |
269 | } |
270 | { |
271 | const Person3_ts p1(1); |
272 | Person3_ts p2(2); |
273 | const Person3_ts p3(3); |
274 | |
275 | auto t = boost::synchronize(sv: p1,sv&: p2,sv: p3); |
276 | //std::get<0>(t)->SetName("Carmen"); |
277 | std::get<1>(t&: t)->SetName("Javier" ); |
278 | //std::get<2>(t)->SetName("Matias"); |
279 | } |
280 | #endif |
281 | return 0; |
282 | } |
283 | |