synchronized_person.cpp 6.1 KB

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