aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite/performance/23_containers/producer_consumer/sequence.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/testsuite/performance/23_containers/producer_consumer/sequence.cc')
-rw-r--r--libstdc++-v3/testsuite/performance/23_containers/producer_consumer/sequence.cc257
1 files changed, 257 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/performance/23_containers/producer_consumer/sequence.cc b/libstdc++-v3/testsuite/performance/23_containers/producer_consumer/sequence.cc
new file mode 100644
index 00000000000..93284f89d39
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/23_containers/producer_consumer/sequence.cc
@@ -0,0 +1,257 @@
+// Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#include <testsuite_common_types.h>
+
+typedef int test_type;
+
+// The number of iterations to be performed.
+int iterations = 1000;
+
+// TODO - restore Stefan's comment? i don't understand it. -- fwy
+int insert_values = 128;
+
+class Lock
+{
+public:
+ Lock() {pthread_mutex_init(&mutex, 0);}
+ ~Lock() {pthread_mutex_destroy(&mutex);}
+
+public:
+ inline pthread_mutex_t* operator&() {return &mutex;}
+
+public:
+ inline void lock() {pthread_mutex_lock(&mutex);}
+ inline void unlock() {pthread_mutex_unlock(&mutex);}
+
+private:
+ Lock(const Lock&);
+ Lock& operator=(Lock&);
+
+private:
+ pthread_mutex_t mutex;
+};
+
+class AutoLock
+{
+public:
+ AutoLock(Lock& _lock)
+ : lock(_lock)
+ {lock.lock();}
+
+ ~AutoLock() {lock.unlock();}
+
+private:
+ AutoLock(AutoLock&);
+ AutoLock& operator=(AutoLock&);
+
+private:
+ Lock& lock;
+};
+
+template<typename Container>
+ class Queue
+ {
+ public:
+ Queue() {pthread_cond_init(&condition, 0);}
+ ~Queue() {pthread_cond_destroy(&condition);}
+
+ public:
+ void push_back(const typename Container::value_type& x);
+ void swap(Container& container);
+
+ private:
+ pthread_cond_t condition;
+ Lock lock;
+ Container queue;
+ };
+
+template<typename Container>
+ void
+ Queue<Container>::push_back(const typename Container::value_type& value)
+ {
+ AutoLock auto_lock(lock);
+ const bool signal = queue.empty();
+ queue.insert(queue.end(), value);
+ if (signal) pthread_cond_signal(&condition);
+ }
+
+template<typename Container>
+ void
+ Queue<Container>::swap(Container& container)
+ {
+ AutoLock auto_lock(lock);
+ while (queue.empty()) pthread_cond_wait(&condition, &lock);
+ queue.swap(container);
+ }
+
+class Thread
+{
+ // NB: Make this the last data member of an object defining operator()().
+public:
+ class Attributes
+ {
+ public:
+ Attributes(int state = PTHREAD_CREATE_JOINABLE);
+ ~Attributes() {pthread_attr_destroy(&attributes);}
+
+ public:
+ inline pthread_attr_t* operator&() {return &attributes;}
+
+ private:
+ pthread_attr_t attributes;
+ };
+
+public:
+ Thread() {thread = pthread_self();}
+ ~Thread();
+
+public:
+ template <typename ThreadOwner>
+ void create(ThreadOwner* owner);
+
+private:
+ pthread_t thread;
+};
+
+Thread::Attributes::Attributes(int state)
+{
+ pthread_attr_init(&attributes);
+ pthread_attr_setdetachstate(&attributes, state);
+}
+
+Thread::~Thread()
+{
+ if (!pthread_equal(thread, pthread_self()))
+ pthread_join(thread, 0);
+}
+
+template<typename ThreadOwner>
+ void*
+ create_thread(void* _this)
+ {
+ ThreadOwner* owner = static_cast<ThreadOwner*>(_this);
+ (*owner)();
+ return 0;
+ }
+
+template<typename ThreadOwner>
+ void
+ Thread::create(ThreadOwner* owner)
+ {
+ Thread::Attributes attributes;
+ pthread_create(&thread, &attributes, create_thread<ThreadOwner>, owner);
+ }
+
+template<typename Container>
+ class Consumer
+ {
+ public:
+ Consumer(Queue<Container>& _queue)
+ : queue(_queue)
+ {thread.create(this);}
+
+ public:
+ void operator()();
+
+ private:
+ Queue<Container>& queue;
+ Thread thread;
+ };
+
+template<typename Container>
+ void
+ Consumer<Container>::operator()()
+ {
+ for (int j = insert_values * iterations; j > 0;)
+ {
+ Container container;
+ queue.swap(container);
+ j -= container.size();
+ }
+ }
+
+template<typename TestType>
+ struct Value : public std::pair<TestType, TestType>
+ {
+ Value()
+ : std::pair<TestType, TestType>(0, 0)
+ { }
+
+ inline Value operator++() {return ++this->first, *this;}
+ inline operator TestType() const {return this->first;}
+ };
+
+template<typename Container>
+ class ProducerConsumer : private Queue<Container>
+ {
+ public:
+ ProducerConsumer() {thread.create(this);}
+
+ public:
+ void operator()();
+
+ private:
+ Thread thread;
+ };
+
+template<typename Container>
+ void
+ ProducerConsumer<Container>::operator()()
+ {
+ Consumer<Container> consumer(*this);
+ Value<test_type> test_value;
+ for (int j = insert_values * iterations; j-- > 0;)
+ this->push_back(++test_value);
+ }
+
+template<typename Container, int Iter>
+ void
+ do_loop()
+ {
+ ProducerConsumer<Container> pc1;
+ ProducerConsumer<Container> pc2;
+ }
+
+int
+main()
+{
+#ifdef TEST_T1
+#define thread_type true
+#endif
+
+ using __gnu_test::sequence_containers;
+ typedef sequence_containers<test_type, thread_type>::type container_types;
+
+ typedef test_sequence<thread_type> test_type;
+ test_type test("producer_consumer_sequence");
+ __gnu_cxx::apply<test_type, container_types> applier;
+ applier(test);
+
+ return 0;
+}
+