• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
GetName() const28   std::string GetName() const {
29     return *name;
30   }
SetName(const std::string & newName)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:
GetName() const41   std::string GetName() const {
42     return name;
43   }
SetName(const std::string & newName)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:
SafeMemberPerson(unsigned int age)80   SafeMemberPerson(unsigned int age) :
81     member(Member(age))
82   {  }
GetName() const83   std::string GetName() const  {
84     return member->name;
85   }
SetName(const std::string & newName)86   void SetName(const std::string& newName)  {
87     member->name = newName;
88   }
89 private:
90   struct Member  {
MemberSafeMemberPerson::Member91     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:
Person2(unsigned int age)103   Person2(unsigned int age) : age_(age)
104   {}
GetName() const105   std::string GetName() const  {
106     return name_;
107   }
SetName(const std::string & newName)108   void SetName(const std::string& newName)  {
109     name_ = newName;
110   }
GetAge() const111   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:
HelperPerson(unsigned int age)154   HelperPerson(unsigned int age) :
155     member(age)
156   {  }
GetName() const157   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(memberSync);
164     return memberSync->name;
165   }
SetName(const std::string & newName)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(memberSync);
173     memberSync->name = newName;
174   }
175 private:
176   struct Member  {
MemberHelperPerson::Member177     Member(unsigned int age) :
178       age(age)
179     {    }
180     std::string name;
181     unsigned int age;
182   };
Invariant(boost::const_strict_lock_ptr<Member> & mbr) const183   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:
Person3(unsigned int age)192   Person3(unsigned int age) :
193     age_(age)
194   {  }
GetName() const195   std::string GetName() const  {
196     Invariant();
197     return name_;
198   }
SetName(const std::string & newName)199   void SetName(const std::string& newName)  {
200     Invariant();
201     name_ = newName;
202   }
203 private:
204   std::string name_;
205   unsigned int age_;
Invariant() const206   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 
main()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(boost::defer_lock);
245     auto  lk2 = p2.unique_synchronize(boost::defer_lock);
246     auto  lk3 = p3.unique_synchronize(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(lk1,lk2,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(p1,p2,p3);
266     std::get<0>(t)->SetName("Carmen");
267     std::get<1>(t)->SetName("Javier");
268     std::get<2>(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(p1,p2,p3);
276     //std::get<0>(t)->SetName("Carmen");
277     std::get<1>(t)->SetName("Javier");
278     //std::get<2>(t)->SetName("Matias");
279   }
280 #endif
281   return 0;
282 }
283