1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #include <algorithm>
12 #include <vector>
13 #include <list>
14 #include <iostream>
15 #include <functional>
16 #include <boost/interprocess/managed_external_buffer.hpp>
17 #include <boost/interprocess/managed_heap_memory.hpp>
18 #include <boost/interprocess/containers/list.hpp>
19 #include <boost/interprocess/detail/type_traits.hpp>
20 #include <boost/move/detail/type_traits.hpp>
21 #include <boost/interprocess/allocators/node_allocator.hpp>
22 #include "print_container.hpp"
23
24 /******************************************************************************/
25 /* */
26 /* This example constructs repeats the same operations with std::list, */
27 /* shmem_list in user provided buffer, and shmem_list in heap memory */
28 /* */
29 /******************************************************************************/
30
31 using namespace boost::interprocess;
32
33 //We will work with wide characters for user memory objects
34 //Alias <integer> node allocator type
35 typedef node_allocator
36 <int, wmanaged_external_buffer::segment_manager> user_node_allocator_t;
37 typedef node_allocator
38 <int, wmanaged_heap_memory::segment_manager> heap_node_allocator_t;
39
40 //Alias list types
41 typedef list<int, user_node_allocator_t> MyUserList;
42 typedef list<int, heap_node_allocator_t> MyHeapList;
43 typedef std::list<int> MyStdList;
44
45 //Function to check if both lists are equal
CheckEqual(MyUserList * userlist,MyStdList * stdlist,MyHeapList * heaplist)46 bool CheckEqual(MyUserList *userlist, MyStdList *stdlist, MyHeapList *heaplist)
47 {
48 return std::equal(userlist->begin(), userlist->end(), stdlist->begin()) &&
49 std::equal(heaplist->begin(), heaplist->end(), stdlist->begin());
50 }
51
main()52 int main ()
53 {
54 //Create the user memory who will store all objects
55 const int size_aligner = sizeof(::boost::container::dtl::max_align_t);
56 const int memsize = 65536/size_aligner*size_aligner;
57 static ::boost::container::dtl::max_align_t static_buffer[memsize/size_aligner];
58
59 {
60 //Now test move semantics
61 managed_heap_memory original(memsize);
62 managed_heap_memory move_ctor(boost::move(original));
63 managed_heap_memory move_assign;
64 move_assign = boost::move(move_ctor);
65 original.swap(move_assign);
66 }
67 {
68 //Now test move semantics
69 managed_external_buffer original(create_only, static_buffer, memsize);
70 managed_external_buffer move_ctor(boost::move(original));
71 managed_external_buffer move_assign;
72 move_assign = boost::move(move_ctor);
73 original.swap(move_assign);
74 }
75
76 //Named new capable user mem allocator
77 wmanaged_external_buffer user_buffer(create_only, static_buffer, memsize);
78
79 //Named new capable heap mem allocator
80 wmanaged_heap_memory heap_buffer(memsize);
81
82 //Test move semantics
83 {
84 wmanaged_external_buffer user_default;
85 wmanaged_external_buffer temp_external(boost::move(user_buffer));
86 user_default = boost::move(temp_external);
87 user_buffer = boost::move(user_default);
88 wmanaged_heap_memory heap_default;
89 wmanaged_heap_memory temp_heap(boost::move(heap_buffer));
90 heap_default = boost::move(temp_heap);
91 heap_buffer = boost::move(heap_default);
92 }
93
94 //Initialize memory
95 user_buffer.reserve_named_objects(100);
96 heap_buffer.reserve_named_objects(100);
97
98 //User memory allocator must be always be initialized
99 //since it has no default constructor
100 MyUserList *userlist = user_buffer.construct<MyUserList>(L"MyUserList")
101 (user_buffer.get_segment_manager());
102
103 MyHeapList *heaplist = heap_buffer.construct<MyHeapList>(L"MyHeapList")
104 (heap_buffer.get_segment_manager());
105
106 //Alias heap list
107 MyStdList *stdlist = new MyStdList;
108
109 int i;
110 const int max = 100;
111 for(i = 0; i < max; ++i){
112 userlist->push_back(i);
113 heaplist->push_back(i);
114 stdlist->push_back(i);
115 }
116 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
117
118 userlist->erase(userlist->begin()++);
119 heaplist->erase(heaplist->begin()++);
120 stdlist->erase(stdlist->begin()++);
121 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
122
123 userlist->pop_back();
124 heaplist->pop_back();
125 stdlist->pop_back();
126 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
127
128 userlist->pop_front();
129 heaplist->pop_front();
130 stdlist->pop_front();
131 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
132
133 std::vector<int> aux_vect;
134 #if !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
135 aux_vect.assign(50, -1);
136 userlist->assign(aux_vect.begin(), aux_vect.end());
137 heaplist->assign(aux_vect.begin(), aux_vect.end());
138 stdlist->assign(aux_vect.begin(), aux_vect.end());
139 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
140 #endif
141
142 userlist->sort();
143 heaplist->sort();
144 stdlist->sort();
145 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
146
147 #if !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
148 aux_vect.assign(50, 0);
149 #endif
150 userlist->insert(userlist->begin(), aux_vect.begin(), aux_vect.end());
151 heaplist->insert(heaplist->begin(), aux_vect.begin(), aux_vect.end());
152 stdlist->insert(stdlist->begin(), aux_vect.begin(), aux_vect.end());
153
154 userlist->unique();
155 heaplist->unique();
156 stdlist->unique();
157 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
158
159 userlist->sort(std::greater<int>());
160 heaplist->sort(std::greater<int>());
161 stdlist->sort(std::greater<int>());
162 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
163
164 userlist->resize(userlist->size()/2);
165 heaplist->resize(heaplist->size()/2);
166 stdlist->resize(stdlist->size()/2);
167 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
168
169 userlist->remove(*userlist->begin());
170 heaplist->remove(*heaplist->begin());
171 stdlist->remove(*stdlist->begin());
172 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
173
174 for(i = 0; i < max; ++i){
175 userlist->push_back(i);
176 heaplist->push_back(i);
177 stdlist->push_back(i);
178 }
179
180 MyUserList otheruserlist(*userlist);
181 MyHeapList otherheaplist(*heaplist);
182 MyStdList otherstdlist(*stdlist);
183 userlist->splice(userlist->begin(), otheruserlist);
184 heaplist->splice(heaplist->begin(), otherheaplist);
185 stdlist->splice(stdlist->begin(), otherstdlist);
186 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
187
188 otheruserlist = *userlist;
189 otherheaplist = *heaplist;
190 otherstdlist = *stdlist;
191
192 userlist->sort(std::greater<int>());
193 heaplist->sort(std::greater<int>());
194 stdlist->sort(std::greater<int>());
195 otheruserlist.sort(std::greater<int>());
196 otherheaplist.sort(std::greater<int>());
197 otherstdlist.sort(std::greater<int>());
198 userlist->merge(otheruserlist, std::greater<int>());
199 heaplist->merge(otherheaplist, std::greater<int>());
200 stdlist->merge(otherstdlist, std::greater<int>());
201 if(!CheckEqual(userlist, stdlist, heaplist)) return 1;
202
203 user_buffer.destroy<MyUserList>(L"MyUserList");
204 delete stdlist;
205
206 //Fill heap buffer until is full
207 try{
208 while(1){
209 heaplist->insert(heaplist->end(), 0);
210 }
211 }
212 catch(boost::interprocess::bad_alloc &){}
213
214 MyHeapList::size_type heap_list_size = heaplist->size();
215
216 //Copy heap buffer to another
217 const char *insert_beg = static_cast<char*>(heap_buffer.get_address());
218 const char *insert_end = insert_beg + heap_buffer.get_size();
219 std::vector<char> grow_copy (insert_beg, insert_end);
220
221 //Destroy old list
222 heap_buffer.destroy<MyHeapList>(L"MyHeapList");
223
224 //Resize copy buffer
225 grow_copy.resize(memsize*2);
226
227 //Open Interprocess machinery in the new managed external buffer
228 wmanaged_external_buffer user_buffer2(open_only, &grow_copy[0], memsize);
229
230 //Expand old Interprocess machinery to the new size
231 user_buffer2.grow(memsize);
232
233 //Get a pointer to the full list
234 userlist = user_buffer2.find<MyUserList>(L"MyHeapList").first;
235 if(!userlist){
236 return 1;
237 }
238
239 //Fill user buffer until is full
240 try{
241 while(1){
242 userlist->insert(userlist->end(), 0);
243 }
244 }
245 catch(boost::interprocess::bad_alloc &){}
246
247 MyUserList::size_type user_list_size = userlist->size();
248
249 if(user_list_size <= heap_list_size){
250 return 1;
251 }
252
253 user_buffer2.destroy_ptr(userlist);
254
255 return 0;
256 }
257