ip_allocator.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* Boost.MultiIndex example of use of Boost.Interprocess allocators.
  2. *
  3. * Copyright 2003-2008 Joaquin M Lopez Munoz.
  4. * Distributed under the Boost Software License, Version 1.0.
  5. * (See accompanying file LICENSE_1_0.txt or copy at
  6. * http://www.boost.org/LICENSE_1_0.txt)
  7. *
  8. * See http://www.boost.org/libs/multi_index for library home page.
  9. */
  10. #if !defined(NDEBUG)
  11. #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
  12. #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
  13. #endif
  14. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  15. #include <algorithm>
  16. #include <boost/interprocess/allocators/allocator.hpp>
  17. #include <boost/interprocess/containers/string.hpp>
  18. #include <boost/interprocess/managed_mapped_file.hpp>
  19. #include <boost/interprocess/sync/named_mutex.hpp>
  20. #include <boost/interprocess/sync/scoped_lock.hpp>
  21. #include <boost/multi_index_container.hpp>
  22. #include <boost/multi_index/ordered_index.hpp>
  23. #include <boost/multi_index/member.hpp>
  24. #include <iostream>
  25. #include <iterator>
  26. #include <sstream>
  27. #include <string>
  28. using boost::multi_index_container;
  29. using namespace boost::multi_index;
  30. namespace bip=boost::interprocess;
  31. /* shared_string is a string type placeable in shared memory,
  32. * courtesy of Boost.Interprocess.
  33. */
  34. typedef bip::basic_string<
  35. char,std::char_traits<char>,
  36. bip::allocator<char,bip::managed_mapped_file::segment_manager>
  37. > shared_string;
  38. /* Book record. All its members can be placed in shared memory,
  39. * hence the structure itself can too.
  40. */
  41. struct book
  42. {
  43. shared_string name;
  44. shared_string author;
  45. unsigned pages;
  46. unsigned prize;
  47. book(const shared_string::allocator_type& al):
  48. name(al),author(al),pages(0),prize(0)
  49. {}
  50. friend std::ostream& operator<<(std::ostream& os,const book& b)
  51. {
  52. os<<b.author<<": \""<<b.name<<"\", $"<<b.prize<<", "<<b.pages<<" pages\n";
  53. return os;
  54. }
  55. };
  56. /* partial_str_less allows for partial searches taking into account
  57. * only the first n chars of the strings compared against. See
  58. * Tutorial: Basics: Special lookup operations for more info on this
  59. * type of comparison functors.
  60. */
  61. /* partial_string is a mere string holder used to differentiate from
  62. * a plain string.
  63. */
  64. struct partial_string
  65. {
  66. partial_string(const shared_string& str):str(str){}
  67. shared_string str;
  68. };
  69. struct partial_str_less
  70. {
  71. bool operator()(const shared_string& x,const shared_string& y)const
  72. {
  73. return x<y;
  74. }
  75. bool operator()(const shared_string& x,const partial_string& y)const
  76. {
  77. return x.substr(0,y.str.size())<y.str;
  78. }
  79. bool operator()(const partial_string& x,const shared_string& y)const
  80. {
  81. return x.str<y.substr(0,x.str.size());
  82. }
  83. };
  84. /* Define a multi_index_container of book records with indices on
  85. * author, name and prize. The index on names allows for partial
  86. * searches. This container can be placed in shared memory because:
  87. * * book can be placed in shared memory.
  88. * * We are using a Boost.Interprocess specific allocator.
  89. */
  90. /* see Compiler specifics: Use of member_offset for info on
  91. * BOOST_MULTI_INDEX_MEMBER
  92. */
  93. typedef multi_index_container<
  94. book,
  95. indexed_by<
  96. ordered_non_unique<
  97. BOOST_MULTI_INDEX_MEMBER(book,shared_string,author)
  98. >,
  99. ordered_non_unique<
  100. BOOST_MULTI_INDEX_MEMBER(book,shared_string,name),
  101. partial_str_less
  102. >,
  103. ordered_non_unique<
  104. BOOST_MULTI_INDEX_MEMBER(book,unsigned,prize)
  105. >
  106. >,
  107. bip::allocator<book,bip::managed_mapped_file::segment_manager>
  108. > book_container;
  109. /* A small utility to get data entered via std::cin */
  110. template<typename T>
  111. void enter(const char* msg,T& t)
  112. {
  113. std::cout<<msg;
  114. std::string str;
  115. std::getline(std::cin,str);
  116. std::istringstream iss(str);
  117. iss>>t;
  118. }
  119. void enter(const char* msg,std::string& str)
  120. {
  121. std::cout<<msg;
  122. std::getline(std::cin,str);
  123. }
  124. void enter(const char* msg,shared_string& str)
  125. {
  126. std::cout<<msg;
  127. std::string stdstr;
  128. std::getline(std::cin,stdstr);
  129. str=stdstr.c_str();
  130. }
  131. int main()
  132. {
  133. /* Create (or open) the memory mapped file where the book container
  134. * is stored, along with a mutex for synchronized access.
  135. */
  136. bip::managed_mapped_file seg(
  137. bip::open_or_create,"./book_container.db",
  138. 65536);
  139. bip::named_mutex mutex(
  140. bip::open_or_create,"7FD6D7E8-320B-11DC-82CF-F0B655D89593");
  141. /* create or open the book container in shared memory */
  142. book_container* pbc=seg.find_or_construct<book_container>("book container")(
  143. book_container::ctor_args_list(),
  144. book_container::allocator_type(seg.get_segment_manager()));
  145. std::string command_info=
  146. "1. list books by author\n"
  147. "2. list all books by prize\n"
  148. "3. insert a book\n"
  149. "4. delete a book\n"
  150. "0. exit\n";
  151. std::cout<<command_info;
  152. /* main loop */
  153. for(bool exit=false;!exit;){
  154. int command=-1;
  155. enter("command: ",command);
  156. switch(command){
  157. case 0:{ /* exit */
  158. exit=true;
  159. break;
  160. }
  161. case 1:{ /* list books by author */
  162. std::string author;
  163. enter("author (empty=all authors): ",author);
  164. /* operations with the container must be mutex protected */
  165. bip::scoped_lock<bip::named_mutex> lock(mutex);
  166. std::pair<book_container::iterator,book_container::iterator> rng;
  167. if(author.empty()){
  168. rng=std::make_pair(pbc->begin(),pbc->end());
  169. }
  170. else{
  171. rng=pbc->equal_range(
  172. shared_string(
  173. author.c_str(),
  174. shared_string::allocator_type(seg.get_segment_manager())));
  175. }
  176. if(rng.first==rng.second){
  177. std::cout<<"no entries\n";
  178. }
  179. else{
  180. std::copy(
  181. rng.first,rng.second,std::ostream_iterator<book>(std::cout));
  182. }
  183. break;
  184. }
  185. case 2:{ /* list all books by prize */
  186. bip::scoped_lock<bip::named_mutex> lock(mutex);
  187. std::copy(
  188. get<2>(*pbc).begin(),get<2>(*pbc).end(),
  189. std::ostream_iterator<book>(std::cout));
  190. break;
  191. }
  192. case 3:{ /* insert a book */
  193. book b(shared_string::allocator_type(seg.get_segment_manager()));
  194. enter("author: ",b.author);
  195. enter("name: " ,b.name);
  196. enter("prize: " ,b.prize);
  197. enter("pages: " ,b.pages);
  198. std::cout<<"insert the following?\n"<<b<<"(y/n): ";
  199. char yn='n';
  200. enter("",yn);
  201. if(yn=='y'||yn=='Y'){
  202. bip::scoped_lock<bip::named_mutex> lock(mutex);
  203. pbc->insert(b);
  204. }
  205. break;
  206. }
  207. case 4:{ /* delete a book */
  208. shared_string name(
  209. shared_string::allocator_type(seg.get_segment_manager()));
  210. enter(
  211. "name of the book (you can enter\nonly the first few characters): ",
  212. name);
  213. typedef nth_index<book_container,1>::type index_by_name;
  214. index_by_name& idx=get<1>(*pbc);
  215. index_by_name::iterator it;
  216. book b(shared_string::allocator_type(seg.get_segment_manager()));
  217. {
  218. /* Look for a book whose title begins with name. Note that we
  219. * are unlocking after doing the search so as to not leave the
  220. * container blocked during user prompting. That is also why a
  221. * local copy of the book is done.
  222. */
  223. bip::scoped_lock<bip::named_mutex> lock(mutex);
  224. it=idx.find(partial_string(name));
  225. if(it==idx.end()){
  226. std::cout<<"no such book found\n";
  227. break;
  228. }
  229. b=*it;
  230. }
  231. std::cout<<"delete the following?\n"<<b<<"(y/n): ";
  232. char yn='n';
  233. enter("",yn);
  234. if(yn=='y'||yn=='Y'){
  235. bip::scoped_lock<bip::named_mutex> lock(mutex);
  236. idx.erase(it);
  237. }
  238. break;
  239. }
  240. default:{
  241. std::cout<<"select one option:\n"<<command_info;
  242. break;
  243. }
  244. }
  245. }
  246. return 0;
  247. }