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()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(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