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
26class SafePerson {
27public:
28 std::string GetName() const {
29 return *name;
30 }
31 void SetName(const std::string& newName) {
32 *name = newName;
33 }
34
35private:
36 boost::synchronized_value<std::string> name;
37};
38
39class Person {
40public:
41 std::string GetName() const {
42 return name;
43 }
44 void SetName(const std::string& newName) {
45 name = newName;
46 }
47private:
48 std::string name;
49};
50typedef 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
78class SafeMemberPerson {
79public:
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 }
89private:
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
101class Person2 {
102public:
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
115private:
116 std::string name_;
117 unsigned int age_;
118};
119typedef 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
152class HelperPerson {
153public:
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 }
175private:
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
190class Person3 {
191public:
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 }
203private:
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
211typedef boost::synchronized_value<Person3> Person3_ts;
212
213int 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

source code of boost/libs/thread/example/synchronized_person.cpp