]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/performance/20_util/allocator/producer_consumer.cc
remove 2004 entries, which have been moved to ChangeLog.2004
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / performance / 20_util / allocator / producer_consumer.cc
1 // Copyright (C) 2004 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 2, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING. If not, write to the Free
16 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 // USA.
18
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction. Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License. This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27
28 /*
29 * The goal with this application is to compare the performance of
30 * different allocators in a simple producer-consumer scenario.
31 */
32
33 // 2004-02-04 Felix Yen <fwy@alumni.brown.edu>
34
35 #include <vector>
36 #include <list>
37 #include <map>
38 #include <typeinfo>
39 #include <sstream>
40 #include <pthread.h>
41 #include <ext/mt_allocator.h>
42 #include <ext/new_allocator.h>
43 #include <ext/malloc_allocator.h>
44 #include <ext/bitmap_allocator.h>
45 #include <ext/pool_allocator.h>
46 #include <cxxabi.h>
47 #include <testsuite_performance.h>
48
49
50 using namespace std;
51 using __gnu_cxx::__mt_alloc;
52 using __gnu_cxx::new_allocator;
53 using __gnu_cxx::malloc_allocator;
54 using __gnu_cxx::bitmap_allocator;
55 using __gnu_cxx::__pool_alloc;
56 using abi::__cxa_demangle;
57
58 typedef int test_type;
59 typedef less<test_type> compare_type;
60 typedef malloc_allocator<test_type> malloc_alloc_type;
61 typedef new_allocator<test_type> new_alloc_type;
62 typedef __mt_alloc<test_type> so_alloc_type;
63 typedef bitmap_allocator<test_type> bit_alloc_type;
64 typedef __pool_alloc<test_type> po_alloc_type;
65
66 typedef pair<const test_type, test_type> pair_type;
67 typedef malloc_allocator<pair_type> malloc_pair_alloc_type;
68 typedef new_allocator<pair_type> new_pair_alloc_type;
69 typedef __mt_alloc<pair_type> so_pair_alloc_type;
70 typedef bitmap_allocator<pair_type> bit_pair_alloc_type;
71 typedef __pool_alloc<pair_type> po_pair_alloc_type;
72
73 // The number of iterations to be performed.
74 int iterations = 10000;
75
76 // TODO - restore Stefan's comment? i don't understand it. -- fwy
77 int insert_values = 128;
78
79 class Lock
80 {
81 public:
82 Lock() {pthread_mutex_init(&mutex, 0);}
83 ~Lock() {pthread_mutex_destroy(&mutex);}
84
85 public:
86 inline pthread_mutex_t* operator&() {return &mutex;}
87
88 public:
89 inline void lock() {pthread_mutex_lock(&mutex);}
90 inline void unlock() {pthread_mutex_unlock(&mutex);}
91
92 private:
93 Lock(const Lock&);
94 Lock& operator=(Lock&);
95
96 private:
97 pthread_mutex_t mutex;
98 };
99
100 class AutoLock
101 {
102 public:
103 AutoLock(Lock& _lock)
104 : lock(_lock)
105 {lock.lock();}
106
107 ~AutoLock() {lock.unlock();}
108
109 private:
110 AutoLock(AutoLock&);
111 AutoLock& operator=(AutoLock&);
112
113 private:
114 Lock& lock;
115 };
116
117 template<typename Container>
118 class Queue
119 {
120 public:
121 Queue() {pthread_cond_init(&condition, 0);}
122 ~Queue() {pthread_cond_destroy(&condition);}
123
124 public:
125 void push_back(const typename Container::value_type& x);
126 void swap(Container& container);
127
128 private:
129 pthread_cond_t condition;
130 Lock lock;
131 Container queue;
132 };
133
134 template<typename Container>
135 void
136 Queue<Container>::push_back(const typename Container::value_type& value)
137 {
138 AutoLock auto_lock(lock);
139 const bool signal = queue.empty();
140 queue.insert(queue.end(), value);
141 if (signal) pthread_cond_signal(&condition);
142 }
143
144 template<typename Container>
145 void
146 Queue<Container>::swap(Container& container)
147 {
148 AutoLock auto_lock(lock);
149 while (queue.empty()) pthread_cond_wait(&condition, &lock);
150 queue.swap(container);
151 }
152
153 class Thread
154 {
155 // NB: Make this the last data member of an object defining operator()().
156 public:
157 class Attributes
158 {
159 public:
160 Attributes(int state = PTHREAD_CREATE_JOINABLE);
161 ~Attributes() {pthread_attr_destroy(&attributes);}
162
163 public:
164 inline pthread_attr_t* operator&() {return &attributes;}
165
166 private:
167 pthread_attr_t attributes;
168 };
169
170 public:
171 Thread() {thread = pthread_self();}
172 ~Thread();
173
174 public:
175 template <typename ThreadOwner>
176 void create(ThreadOwner* owner);
177
178 private:
179 pthread_t thread;
180 };
181
182 Thread::Attributes::Attributes(int state)
183 {
184 pthread_attr_init(&attributes);
185 pthread_attr_setdetachstate(&attributes, state);
186 }
187
188 Thread::~Thread()
189 {
190 if (!pthread_equal(thread, pthread_self()))
191 pthread_join(thread, 0);
192 }
193
194 template<typename ThreadOwner>
195 void*
196 create_thread(void* _this)
197 {
198 ThreadOwner* owner = static_cast<ThreadOwner*>(_this);
199 (*owner)();
200 return 0;
201 }
202
203 template<typename ThreadOwner>
204 void
205 Thread::create(ThreadOwner* owner)
206 {
207 Thread::Attributes attributes;
208 pthread_create(&thread, &attributes, create_thread<ThreadOwner>, owner);
209 }
210
211 template<typename Container>
212 class Consumer
213 {
214 public:
215 Consumer(Queue<Container>& _queue)
216 : queue(_queue)
217 {thread.create(this);}
218
219 public:
220 void operator()();
221
222 private:
223 Queue<Container>& queue;
224 Thread thread;
225 };
226
227 template<typename Container>
228 void
229 Consumer<Container>::operator()()
230 {
231 for (int j = insert_values * iterations; j > 0;)
232 {
233 Container container;
234 queue.swap(container);
235 j -= container.size();
236 }
237 }
238
239 template<typename TestType>
240 struct Value : public pair<TestType, TestType>
241 {
242 Value()
243 : pair<TestType, TestType>(0, 0)
244 { }
245
246 inline Value operator++() {return ++this->first, *this;}
247 inline operator TestType() const {return this->first;}
248 };
249
250 template<typename Container>
251 class ProducerConsumer : private Queue<Container>
252 {
253 public:
254 ProducerConsumer() {thread.create(this);}
255
256 public:
257 void operator()();
258
259 private:
260 Thread thread;
261 };
262
263 template<typename Container>
264 void
265 ProducerConsumer<Container>::operator()()
266 {
267 Consumer<Container> consumer(*this);
268 Value<test_type> test_value;
269 for (int j = insert_values * iterations; j-- > 0;)
270 this->push_back(++test_value);
271 }
272
273 template<typename Container>
274 void
275 test_container(Container obj)
276 {
277 using namespace __gnu_test;
278 int status;
279
280 time_counter time;
281 resource_counter resource;
282
283 clear_counters(time, resource);
284 start_counters(time, resource);
285 {
286 ProducerConsumer<Container> pc1;
287 ProducerConsumer<Container> pc2;
288 }
289 stop_counters(time, resource);
290
291 std::ostringstream comment;
292 comment << "iterations: " << iterations << '\t';
293 comment << "type: " << __cxa_demangle(typeid(obj).name(), 0, 0, &status);
294 report_header(__FILE__, comment.str());
295 report_performance(__FILE__, string(), time, resource);
296 }
297
298 int main(void)
299 {
300 #ifdef TEST_T0
301 test_container(vector<test_type, malloc_alloc_type>());
302 #endif
303 #ifdef TEST_T1
304 test_container(vector<test_type, new_alloc_type>());
305 #endif
306 #ifdef TEST_T2
307 test_container(vector<test_type, so_alloc_type>());
308 #endif
309 #ifdef TEST_T3
310 test_container(vector<test_type, bit_alloc_type>());
311 #endif
312 #ifdef TEST_T4
313 test_container(vector<test_type, po_alloc_type>());
314 #endif
315
316 #ifdef TEST_T5
317 test_container(list<test_type, malloc_alloc_type>());
318 #endif
319 #ifdef TEST_T6
320 test_container(list<test_type, new_alloc_type>());
321 #endif
322 #ifdef TEST_T7
323 test_container(list<test_type, so_alloc_type>());
324 #endif
325 #ifdef TEST_T8
326 test_container(list<test_type, bit_alloc_type>());
327 #endif
328 #ifdef TEST_T9
329 test_container(list<test_type, po_alloc_type>());
330 #endif
331
332 #ifdef TEST_T10
333 test_container(map<test_type, test_type, compare_type,
334 malloc_pair_alloc_type>());
335 #endif
336 #ifdef TEST_T11
337 test_container(map<test_type, test_type, compare_type,
338 new_pair_alloc_type>());
339 #endif
340 #ifdef TEST_T12
341 test_container(map<test_type, test_type, compare_type,
342 so_pair_alloc_type>());
343 #endif
344 #ifdef TEST_T13
345 test_container(map<test_type, test_type, compare_type,
346 bit_pair_alloc_type>());
347 #endif
348 #ifdef TEST_T14
349 test_container(map<test_type, test_type, compare_type,
350 po_pair_alloc_type>());
351 #endif
352
353 return 0;
354 }
355