]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/performance/23_containers/producer_consumer/sequence.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / performance / 23_containers / producer_consumer / sequence.cc
1 // Copyright (C) 2003-2020 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 3, 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 COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
17
18
19 #include <testsuite_performance.h>
20
21 typedef int test_type;
22
23 // The number of iterations to be performed.
24 int iterations = 1000;
25
26 // TODO - restore Stefan's comment? i don't understand it. -- fwy
27 int insert_values = 128;
28
29 class Lock
30 {
31 public:
32 Lock() {pthread_mutex_init(&mutex, 0);}
33 ~Lock() {pthread_mutex_destroy(&mutex);}
34
35 public:
36 inline pthread_mutex_t* operator&() {return &mutex;}
37
38 public:
39 inline void lock() {pthread_mutex_lock(&mutex);}
40 inline void unlock() {pthread_mutex_unlock(&mutex);}
41
42 private:
43 Lock(const Lock&);
44 Lock& operator=(Lock&);
45
46 private:
47 pthread_mutex_t mutex;
48 };
49
50 class AutoLock
51 {
52 public:
53 AutoLock(Lock& _lock)
54 : lock(_lock)
55 {lock.lock();}
56
57 ~AutoLock() {lock.unlock();}
58
59 private:
60 AutoLock(AutoLock&);
61 AutoLock& operator=(AutoLock&);
62
63 private:
64 Lock& lock;
65 };
66
67 template<typename Container>
68 class Queue
69 {
70 public:
71 Queue() {pthread_cond_init(&condition, 0);}
72 ~Queue() {pthread_cond_destroy(&condition);}
73
74 public:
75 void push_back(const typename Container::value_type& x);
76 void swap(Container& container);
77
78 private:
79 pthread_cond_t condition;
80 Lock lock;
81 Container queue;
82 };
83
84 template<typename Container>
85 void
86 Queue<Container>::push_back(const typename Container::value_type& value)
87 {
88 AutoLock auto_lock(lock);
89 const bool signal = queue.empty();
90 queue.insert(queue.end(), value);
91 if (signal) pthread_cond_signal(&condition);
92 }
93
94 template<typename Container>
95 void
96 Queue<Container>::swap(Container& container)
97 {
98 AutoLock auto_lock(lock);
99 while (queue.empty()) pthread_cond_wait(&condition, &lock);
100 queue.swap(container);
101 }
102
103 class Thread
104 {
105 // NB: Make this the last data member of an object defining operator()().
106 public:
107 class Attributes
108 {
109 public:
110 Attributes(int state = PTHREAD_CREATE_JOINABLE);
111 ~Attributes() {pthread_attr_destroy(&attributes);}
112
113 public:
114 inline pthread_attr_t* operator&() {return &attributes;}
115
116 private:
117 pthread_attr_t attributes;
118 };
119
120 public:
121 Thread() {thread = pthread_self();}
122 ~Thread();
123
124 public:
125 template <typename ThreadOwner>
126 void create(ThreadOwner* owner);
127
128 private:
129 pthread_t thread;
130 };
131
132 Thread::Attributes::Attributes(int state)
133 {
134 pthread_attr_init(&attributes);
135 pthread_attr_setdetachstate(&attributes, state);
136 }
137
138 Thread::~Thread()
139 {
140 if (!pthread_equal(thread, pthread_self()))
141 pthread_join(thread, 0);
142 }
143
144 template<typename ThreadOwner>
145 void*
146 create_thread(void* _this)
147 {
148 ThreadOwner* owner = static_cast<ThreadOwner*>(_this);
149 (*owner)();
150 return 0;
151 }
152
153 template<typename ThreadOwner>
154 void
155 Thread::create(ThreadOwner* owner)
156 {
157 Thread::Attributes attributes;
158 pthread_create(&thread, &attributes, create_thread<ThreadOwner>, owner);
159 }
160
161 template<typename Container>
162 class Consumer
163 {
164 public:
165 Consumer(Queue<Container>& _queue)
166 : queue(_queue)
167 {thread.create(this);}
168
169 public:
170 void operator()();
171
172 private:
173 Queue<Container>& queue;
174 Thread thread;
175 };
176
177 template<typename Container>
178 void
179 Consumer<Container>::operator()()
180 {
181 for (int j = insert_values * iterations; j > 0;)
182 {
183 Container container;
184 queue.swap(container);
185 j -= container.size();
186 }
187 }
188
189 template<typename TestType>
190 struct Value : public std::pair<TestType, TestType>
191 {
192 Value()
193 : std::pair<TestType, TestType>(0, 0)
194 { }
195
196 inline Value operator++() {return ++this->first, *this;}
197 inline operator TestType() const {return this->first;}
198 };
199
200 template<typename Container>
201 class ProducerConsumer : private Queue<Container>
202 {
203 public:
204 ProducerConsumer() {thread.create(this);}
205
206 public:
207 void operator()();
208
209 private:
210 Thread thread;
211 };
212
213 template<typename Container>
214 void
215 ProducerConsumer<Container>::operator()()
216 {
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);
221 }
222
223 template<typename Container, int Iter>
224 void
225 do_loop()
226 {
227 ProducerConsumer<Container> pc1;
228 ProducerConsumer<Container> pc2;
229 }
230
231 int
232 main()
233 {
234 #ifdef TEST_T1
235 #define thread_type true
236 #endif
237
238 using __gnu_test::sequence_containers;
239 typedef sequence_containers<test_type, thread_type>::type container_types;
240
241 typedef test_sequence<thread_type> test_type;
242 test_type test("producer_consumer_sequence");
243 __gnu_cxx::typelist::apply(test, container_types());
244
245 return 0;
246 }
247