diff options
Diffstat (limited to 'dbtests/threadedtests.cpp')
-rw-r--r-- | dbtests/threadedtests.cpp | 154 |
1 files changed, 118 insertions, 36 deletions
diff --git a/dbtests/threadedtests.cpp b/dbtests/threadedtests.cpp index af413cc..805b2d5 100644 --- a/dbtests/threadedtests.cpp +++ b/dbtests/threadedtests.cpp @@ -21,6 +21,7 @@ #include "../bson/util/atomic_int.h" #include "../util/concurrency/mvar.h" #include "../util/concurrency/thread_pool.h" +#include "../util/timer.h" #include <boost/thread.hpp> #include <boost/bind.hpp> @@ -29,34 +30,108 @@ namespace ThreadedTests { template <int nthreads_param=10> - class ThreadedTest{ - public: - virtual void setup() {} //optional - virtual void subthread() = 0; - virtual void validate() = 0; + class ThreadedTest { + public: + virtual void setup() {} //optional + virtual void subthread() = 0; + virtual void validate() = 0; - static const int nthreads = nthreads_param; + static const int nthreads = nthreads_param; - void run(){ - setup(); + void run() { + setup(); + launch_subthreads(nthreads); + validate(); + } - launch_subthreads(nthreads); + virtual ~ThreadedTest() {}; // not necessary, but makes compilers happy - validate(); - } + private: + void launch_subthreads(int remaining) { + if (!remaining) return; - virtual ~ThreadedTest() {}; // not necessary, but makes compilers happy + boost::thread athread(boost::bind(&ThreadedTest::subthread, this)); - private: - void launch_subthreads(int remaining){ - if (!remaining) return; + launch_subthreads(remaining - 1); - boost::thread athread(boost::bind(&ThreadedTest::subthread, this)); - - launch_subthreads(remaining - 1); + athread.join(); + } + }; - athread.join(); + class MongoMutexTest : public ThreadedTest<135> { +#if defined(_DEBUG) + enum { N = 5000 }; +#else + enum { N = 40000 }; +#endif + MongoMutex *mm; + public: + void run() { + Timer t; + cout << "MongoMutexTest N:" << N << endl; + ThreadedTest<135>::run(); + cout << "MongoMutexTest " << t.millis() << "ms" << endl; + } + private: + virtual void setup() { + mm = new MongoMutex("MongoMutexTest"); + } + virtual void subthread() { + Client::initThread("mongomutextest"); + sleepmillis(0); + for( int i = 0; i < N; i++ ) { + if( i % 7 == 0 ) { + mm->lock_shared(); + mm->lock_shared(); + mm->unlock_shared(); + mm->unlock_shared(); + } + else if( i % 7 == 1 ) { + mm->lock_shared(); + ASSERT( mm->atLeastReadLocked() ); + mm->unlock_shared(); + } + else if( i % 7 == 2 ) { + mm->lock(); + ASSERT( mm->isWriteLocked() ); + mm->unlock(); + } + else if( i % 7 == 3 ) { + mm->lock(); + mm->lock_shared(); + ASSERT( mm->isWriteLocked() ); + mm->unlock_shared(); + mm->unlock(); + } + else if( i % 7 == 4 ) { + mm->lock(); + mm->releaseEarly(); + mm->unlock(); + } + else if( i % 7 == 5 ) { + if( mm->lock_try(1) ) { + mm->unlock(); + } + } + else if( i % 7 == 6 ) { + if( mm->lock_shared_try(0) ) { + mm->unlock_shared(); + } + } + else { + mm->lock_shared(); + mm->unlock_shared(); + } } + cc().shutdown(); + } + virtual void validate() { + ASSERT( !mm->atLeastReadLocked() ); + mm->lock(); + mm->unlock(); + mm->lock_shared(); + mm->unlock_shared(); + } }; // Tested with up to 30k threads @@ -64,13 +139,13 @@ namespace ThreadedTests { static const int iterations = 1000000; AtomicUInt target; - void subthread(){ - for(int i=0; i < iterations; i++){ + void subthread() { + for(int i=0; i < iterations; i++) { //target.x++; // verified to fail with this version target++; } } - void validate(){ + void validate() { ASSERT_EQUALS(target.x , unsigned(nthreads * iterations)); AtomicUInt u; @@ -80,6 +155,12 @@ namespace ThreadedTests { ASSERT_EQUALS(2u, u--); ASSERT_EQUALS(0u, --u); ASSERT_EQUALS(0u, u); + + u++; + ASSERT( u > 0 ); + + u--; + ASSERT( ! ( u > 0 ) ); } }; @@ -87,10 +168,10 @@ namespace ThreadedTests { static const int iterations = 10000; MVar<int> target; - public: + public: MVarTest() : target(0) {} - void subthread(){ - for(int i=0; i < iterations; i++){ + void subthread() { + for(int i=0; i < iterations; i++) { int val = target.take(); #if BOOST_VERSION >= 103500 //increase chances of catching failure @@ -99,30 +180,30 @@ namespace ThreadedTests { target.put(val+1); } } - void validate(){ + void validate() { ASSERT_EQUALS(target.take() , nthreads * iterations); } }; - class ThreadPoolTest{ + class ThreadPoolTest { static const int iterations = 10000; static const int nThreads = 8; AtomicUInt counter; - void increment(int n){ - for (int i=0; i<n; i++){ + void increment(int n) { + for (int i=0; i<n; i++) { counter++; } } - public: - void run(){ + public: + void run() { ThreadPool tp(nThreads); - for (int i=0; i < iterations; i++){ + for (int i=0; i < iterations; i++) { tp.schedule(&ThreadPoolTest::increment, this, 2); } - + tp.join(); ASSERT(counter == (unsigned)(iterations * 2)); @@ -131,7 +212,7 @@ namespace ThreadedTests { class LockTest { public: - void run(){ + void run() { // quick atomicint wrap test // MSGID likely assumes this semantic AtomicUInt counter = 0xffffffff; @@ -145,14 +226,15 @@ namespace ThreadedTests { class All : public Suite { public: - All() : Suite( "threading" ){ + All() : Suite( "threading" ) { } - void setupTests(){ + void setupTests() { add< IsAtomicUIntAtomic >(); add< MVarTest >(); add< ThreadPoolTest >(); add< LockTest >(); + add< MongoMutexTest >(); } } myall; } |