diff options
Diffstat (limited to 'cpp/src/tests/ConcurrentQueue.cpp')
-rw-r--r-- | cpp/src/tests/ConcurrentQueue.cpp | 208 |
1 files changed, 0 insertions, 208 deletions
diff --git a/cpp/src/tests/ConcurrentQueue.cpp b/cpp/src/tests/ConcurrentQueue.cpp deleted file mode 100644 index c6ca40e897..0000000000 --- a/cpp/src/tests/ConcurrentQueue.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/**@file - * Compare alternative implementations for BlockingQueue. - */ - -#include "qpid/sys/BlockingQueue.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Time.h" - -#include <boost/test/test_tools.hpp> -#include <boost/bind.hpp> - -#include <deque> -#include <vector> -#include <iostream> - -#include "time.h" - -using namespace qpid::sys; -using namespace std; - -template <class T> class DualVectorDualLockQueue { - public: - /** Optionally specify initial capacity of the queue to minimize - * re-allocation. - */ - DualVectorDualLockQueue(size_t capacity=16) { - pushVec.reserve(capacity); - popVec.reserve(capacity); - popIter = popVec.end(); - } - - /** Push a data item onto the back of the queue */ - void push(const T& data) { - Mutex::ScopedLock l(pushLock); - pushVec.push_back(data); - } - - /** If the queue is non-empty, pop the front item into data and - * return true. If the queue is empty, return false - */ - bool tryPop(T& data) { - Mutex::ScopedLock l(popLock); - if (popIter == popVec.end()) { - popVec.clear(); - Mutex::ScopedLock l(pushLock); - pushVec.swap(popVec); - popIter = popVec.begin(); - } - if (popIter == popVec.end()) - return false; - else { - data = *popIter++; - return true; - } - } - - private: - Mutex pushLock, popLock; - std::vector<T> pushVec, popVec; - typename std::vector<T>::iterator popIter; -}; - -template <class T> struct LockedDequeQueue : public BlockingQueue<T> { - /** size_t ignored, can't pre-allocate space in a dequeue */ - LockedDequeQueue(size_t=0) {}; -}; - -// ================ Test code. - -/** Pause by sleeping */ -void nsleep(const Duration& delay) { - static Monitor m; - AbsTime stop(now(), delay); - while (now() < stop) - m.wait(stop); -} - -/** Pause by spinning */ -void nspin(const Duration& delay) { - AbsTime stop(now(), delay); - while (now() < stop) - ; -} - -/** Unlocked fake queue for comparison */ -struct NullQueue { - NullQueue(int items=0) : npush(items), npop(items) {} - void push(int) { --npush; } - bool tryPop(int& n) { - if (npop == 0) - return false; - else { - n=npop--; - return true; - } - } - volatile int npush, npop; -}; - - -// Global test parameters. -int items; -Duration delay(0); -boost::function<void()> npause; - -template <class Q> -struct Pusher : public Runnable { - Pusher(Q& q) : queue(q) {} - void run() { - for (int i=items; i > 0; i--) { - queue.push(i); - npause(); - } - } - Q& queue; -}; - -template <class Q> -struct Popper : public Runnable { - Popper(Q& q) : queue(q) {} - void run() { - for (int i=items; i > 0; i--) { - int n; - if (queue.tryPop(n)) - BOOST_REQUIRE_EQUAL(i,n); - npause(); - } - } - Q& queue; -}; - -ostream& operator<<(ostream& out, const Duration& d) { - return out << double(d)/TIME_MSEC << " msecs"; -} - -void report(const char* s, const Duration &d) { - cout << s << ": " << d - << " (" << (double(items)*TIME_SEC)/d << " push-pops/sec" << ")" - << endl; -} - -template <class Q, class PusherT=Pusher<Q>, class PopperT=Popper<Q> > -struct Timer { - static Duration time() { - cout << endl << "==" << typeid(Q).name() << endl; - - Q queue(items); - PusherT pusher(queue); - PopperT popper(queue); - - // Serial - AbsTime start=now(); - pusher.run(); - popper.run(); - Duration serial(start,now()); - report ("Serial", serial); - - // Concurrent - start=now(); - Thread pushThread(pusher); - Thread popThread(popper); - pushThread.join(); - popThread.join(); - Duration concurrent(start,now()); - report ("Concurrent", concurrent); - - cout << "Serial/concurrent: " << double(serial)/concurrent << endl; - return concurrent; - } -}; - -int test_main(int argc, char** argv) { - items = (argc > 1) ? atoi(argv[1]) : 250*1000; - delay = (argc > 2) ? atoi(argv[2]) : 4*1000; - npause=boost::bind(nspin, delay); - - cout << "Push/pop " << items << " items, delay=" << delay << endl; - Timer<NullQueue>::time(); - Duration dv = Timer<DualVectorDualLockQueue<int> >::time(); - Duration d = Timer<LockedDequeQueue<int> >::time(); - cout << endl; - cout << "Ratio deque/dual vector=" << double(d)/dv << endl; - return 0; -} -// namespace |