Ticket #9587: Test.cpp

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