1 // Copyright (C) 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
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 3, or (at your option)
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.
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
19 #include <testsuite_performance.h>
21 typedef int test_type;
23 // The number of iterations to be performed.
24 int iterations = 1000;
26 // TODO - restore Stefan's comment? i don't understand it. -- fwy
27 int insert_values = 128;
32 Lock() {pthread_mutex_init(&mutex, 0);}
33 ~Lock() {pthread_mutex_destroy(&mutex);}
36 inline pthread_mutex_t* operator&() {return &mutex;}
39 inline void lock() {pthread_mutex_lock(&mutex);}
40 inline void unlock() {pthread_mutex_unlock(&mutex);}
44 Lock& operator=(Lock&);
47 pthread_mutex_t mutex;
57 ~AutoLock() {lock.unlock();}
61 AutoLock& operator=(AutoLock&);
67 template<typename Container>
71 Queue() {pthread_cond_init(&condition, 0);}
72 ~Queue() {pthread_cond_destroy(&condition);}
75 void push_back(const typename Container::value_type& x);
76 void swap(Container& container);
79 pthread_cond_t condition;
84 template<typename Container>
86 Queue<Container>::push_back(const typename Container::value_type& value)
88 AutoLock auto_lock(lock);
89 const bool signal = queue.empty();
90 queue.insert(queue.end(), value);
91 if (signal) pthread_cond_signal(&condition);
94 template<typename Container>
96 Queue<Container>::swap(Container& container)
98 AutoLock auto_lock(lock);
99 while (queue.empty()) pthread_cond_wait(&condition, &lock);
100 queue.swap(container);
105 // NB: Make this the last data member of an object defining operator()().
110 Attributes(int state = PTHREAD_CREATE_JOINABLE);
111 ~Attributes() {pthread_attr_destroy(&attributes);}
114 inline pthread_attr_t* operator&() {return &attributes;}
117 pthread_attr_t attributes;
121 Thread() {thread = pthread_self();}
125 template <typename ThreadOwner>
126 void create(ThreadOwner* owner);
132 Thread::Attributes::Attributes(int state)
134 pthread_attr_init(&attributes);
135 pthread_attr_setdetachstate(&attributes, state);
140 if (!pthread_equal(thread, pthread_self()))
141 pthread_join(thread, 0);
144 template<typename ThreadOwner>
146 create_thread(void* _this)
148 ThreadOwner* owner = static_cast<ThreadOwner*>(_this);
153 template<typename ThreadOwner>
155 Thread::create(ThreadOwner* owner)
157 Thread::Attributes attributes;
158 pthread_create(&thread, &attributes, create_thread<ThreadOwner>, owner);
161 template<typename Container>
165 Consumer(Queue<Container>& _queue)
167 {thread.create(this);}
173 Queue<Container>& queue;
177 template<typename Container>
179 Consumer<Container>::operator()()
181 for (int j = insert_values * iterations; j > 0;)
184 queue.swap(container);
185 j -= container.size();
189 template<typename TestType>
190 struct Value : public std::pair<TestType, TestType>
193 : std::pair<TestType, TestType>(0, 0)
196 inline Value operator++() {return ++this->first, *this;}
197 inline operator TestType() const {return this->first;}
200 template<typename Container>
201 class ProducerConsumer : private Queue<Container>
204 ProducerConsumer() {thread.create(this);}
213 template<typename Container>
215 ProducerConsumer<Container>::operator()()
217 Consumer<Container> consumer(*this);
218 Value<test_type> test_value;
219 for (int j = insert_values * iterations; j-- > 0;)
220 this->push_back(++test_value);
223 template<typename Container, int Iter>
227 ProducerConsumer<Container> pc1;
228 ProducerConsumer<Container> pc2;
235 #define thread_type true
238 typedef __gnu_test::maps<test_type, thread_type>::type map_typelist;
239 typedef __gnu_test::sets<test_type, thread_type>::type set_typelist;
240 typedef __gnu_cxx::typelist::append<map_typelist, set_typelist>::type container_types;
242 typedef test_sequence<thread_type> test_type;
243 test_type test("producer_consumer_associative");
244 __gnu_cxx::typelist::apply(test, container_types());