summaryrefslogtreecommitdiff
path: root/dbtests/threadedtests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dbtests/threadedtests.cpp')
-rw-r--r--dbtests/threadedtests.cpp154
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;
}