You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2011/05/23 02:26:27 UTC

svn commit: r1126283 - in /activemq/activemq-cpp/trunk/activemq-cpp/src: main/decaf/util/concurrent/locks/ test/ test/decaf/util/concurrent/locks/

Author: tabish
Date: Mon May 23 00:26:26 2011
New Revision: 1126283

URL: http://svn.apache.org/viewvc?rev=1126283&view=rev
Log:
Adds test suite for ReentrantLock and fixes a small bug in AQS

Added:
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.cpp   (with props)
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.h   (with props)
Modified:
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/locks/AbstractQueuedSynchronizer.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/Makefile.am
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/locks/AbstractQueuedSynchronizer.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/locks/AbstractQueuedSynchronizer.cpp?rev=1126283&r1=1126282&r2=1126283&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/locks/AbstractQueuedSynchronizer.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/concurrent/locks/AbstractQueuedSynchronizer.cpp Mon May 23 00:26:26 2011
@@ -426,7 +426,9 @@ namespace locks {
                 // Attempt to set next on tail, this can fail if another thread can in
                 // and replaced the old tail but that's ok since that means next is up
                 // to date in that case.
-                tail.compareAndSet(node, NULL);
+                PlatformThread::writerLockMutex(this->rwLock);
+                if(tail.get()->next == node) tail.get()->next = NULL;
+                PlatformThread::unlockRWMutex(this->rwLock);
                 delete node;
             } else {
                 // If successor needs signal, try to set pred's next-link
@@ -437,7 +439,7 @@ namespace locks {
 
                 // Did we become the tail.
                 if (node == tail.get() && compareAndSetTail(node, node->prev)) {
-                    tail.compareAndSet(node, NULL);
+                    tail.get()->next = NULL;
                 } else {
                     node->prev->next = node->next;
                     node->next->prev = node->prev;

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/Makefile.am
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/Makefile.am?rev=1126283&r1=1126282&r2=1126283&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/Makefile.am (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/Makefile.am Mon May 23 00:26:26 2011
@@ -219,6 +219,7 @@ cc_sources = \
     decaf/util/concurrent/atomic/AtomicReferenceTest.cpp \
     decaf/util/concurrent/locks/AbstractQueuedSynchronizerTest.cpp \
     decaf/util/concurrent/locks/LockSupportTest.cpp \
+    decaf/util/concurrent/locks/ReentrantLockTest.cpp \
     decaf/util/zip/Adler32Test.cpp \
     decaf/util/zip/CRC32Test.cpp \
     decaf/util/zip/CheckedInputStreamTest.cpp \
@@ -444,6 +445,7 @@ h_sources = \
     decaf/util/concurrent/atomic/AtomicReferenceTest.h \
     decaf/util/concurrent/locks/AbstractQueuedSynchronizerTest.h \
     decaf/util/concurrent/locks/LockSupportTest.h \
+    decaf/util/concurrent/locks/ReentrantLockTest.h \
     decaf/util/zip/Adler32Test.h \
     decaf/util/zip/CRC32Test.h \
     decaf/util/zip/CheckedInputStreamTest.h \

Added: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.cpp?rev=1126283&view=auto
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.cpp (added)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.cpp Mon May 23 00:26:26 2011
@@ -0,0 +1,1388 @@
+/*
+ * 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.
+ */
+
+#include "ReentrantLockTest.h"
+
+#include <decaf/lang/System.h>
+#include <decaf/lang/Thread.h>
+#include <decaf/lang/Runnable.h>
+#include <decaf/util/Date.h>
+#include <decaf/util/concurrent/TimeUnit.h>
+#include <decaf/util/concurrent/locks/LockSupport.h>
+#include <decaf/util/concurrent/locks/ReentrantLock.h>
+
+using namespace std;
+using namespace decaf;
+using namespace decaf::lang;
+using namespace decaf::lang::exceptions;
+using namespace decaf::util;
+using namespace decaf::util::concurrent;
+using namespace decaf::util::concurrent::locks;
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class InterruptibleLockRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        ReentrantLockTest* parent;
+
+    public:
+
+        InterruptibleLockRunnable(ReentrantLock* lock, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), parent(parent) {}
+        virtual ~InterruptibleLockRunnable() {}
+
+        virtual void run() {
+            try {
+                lock->lockInterruptibly();
+            } catch(InterruptedException& success){}
+        }
+    };
+
+    class InterruptedLockRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        ReentrantLockTest* parent;
+
+    public:
+
+        InterruptedLockRunnable(ReentrantLock* lock, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), parent(parent) {}
+        virtual ~InterruptedLockRunnable() {}
+
+        virtual void run() {
+            try {
+                lock->lockInterruptibly();
+                parent->threadShouldThrow();
+            } catch(InterruptedException& success) {}
+        }
+    };
+
+    class PublicReentrantLock : public ReentrantLock {
+    public:
+
+        PublicReentrantLock() : ReentrantLock() {}
+
+        Collection<Thread*>* getQueuedThreads() const {
+            return ReentrantLock::getQueuedThreads();
+        }
+
+        Collection<Thread*>* getWaitingThreads(Condition* condition) {
+            return ReentrantLock::getWaitingThreads(condition);
+        }
+    };
+
+    class UninterruptableThread : public Thread {
+    private:
+
+        ReentrantLock* lock;
+        Condition* c;
+        Mutex monitor;
+
+    public:
+
+        volatile bool canAwake;
+        volatile bool interrupted;
+        volatile bool lockStarted;
+
+        UninterruptableThread(ReentrantLock* lock, Condition* c) :
+            Thread(), lock(lock), c(c), canAwake(false), interrupted(false), lockStarted(false) {
+        }
+        virtual ~UninterruptableThread() {}
+
+        virtual void run() {
+
+            synchronized(&monitor) {
+                lock->lock();
+                lockStarted = true;
+
+                while (!canAwake) {
+                    c->awaitUninterruptibly();
+                }
+
+                interrupted = isInterrupted();
+                lock->unlock();
+            }
+        }
+    };
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+ReentrantLockTest::ReentrantLockTest() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+ReentrantLockTest::~ReentrantLockTest() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testConstructor() {
+    ReentrantLock rl;
+    CPPUNIT_ASSERT(!rl.isFair());
+    ReentrantLock r2(true);
+    CPPUNIT_ASSERT(r2.isFair());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testLock() {
+    ReentrantLock rl;
+    rl.lock();
+    CPPUNIT_ASSERT(rl.isLocked());
+    rl.unlock();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testFairLock() {
+    ReentrantLock rl(true);
+    rl.lock();
+    CPPUNIT_ASSERT(rl.isLocked());
+    rl.unlock();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testUnlockIllegalMonitorStateException() {
+    ReentrantLock rl;
+    try {
+        rl.unlock();
+        shouldThrow();
+    } catch(IllegalMonitorStateException& success) {
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testTryLock() {
+    ReentrantLock rl;
+    CPPUNIT_ASSERT(rl.tryLock());
+    CPPUNIT_ASSERT(rl.isLocked());
+    rl.unlock();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testhasQueuedThreads() {
+
+    ReentrantLock lock;
+
+    InterruptedLockRunnable interrupted(&lock, this);
+    InterruptibleLockRunnable interruptable(&lock, this);
+
+    Thread t1(&interrupted);
+    Thread t2(&interruptable);
+
+    try {
+        CPPUNIT_ASSERT(!lock.hasQueuedThreads());
+        lock.lock();
+        t1.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(lock.hasQueuedThreads());
+        t2.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(lock.hasQueuedThreads());
+        t1.interrupt();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(lock.hasQueuedThreads());
+        lock.unlock();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!lock.hasQueuedThreads());
+        t1.join();
+        t2.join();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetQueueLength() {
+
+    ReentrantLock lock;
+
+    InterruptedLockRunnable interrupted(&lock, this);
+    InterruptibleLockRunnable interruptable(&lock, this);
+
+    Thread t1(&interrupted);
+    Thread t2(&interruptable);
+
+    try {
+        CPPUNIT_ASSERT_EQUAL(0, lock.getQueueLength());
+        lock.lock();
+        t1.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT_EQUAL(1, lock.getQueueLength());
+        t2.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT_EQUAL(2, lock.getQueueLength());
+        t1.interrupt();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT_EQUAL(1, lock.getQueueLength());
+        lock.unlock();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT_EQUAL(0, lock.getQueueLength());
+        t1.join();
+        t2.join();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetQueueLengthFair() {
+
+    ReentrantLock lock(true);
+
+    InterruptedLockRunnable interrupted(&lock, this);
+    InterruptibleLockRunnable interruptable(&lock, this);
+
+    Thread t1(&interrupted);
+    Thread t2(&interruptable);
+
+    try {
+        CPPUNIT_ASSERT_EQUAL(0, lock.getQueueLength());
+        lock.lock();
+        t1.start();
+        Thread::sleep( SHORT_DELAY_MS);
+        CPPUNIT_ASSERT_EQUAL(1, lock.getQueueLength());
+        t2.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT_EQUAL(2, lock.getQueueLength());
+        t1.interrupt();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT_EQUAL(1, lock.getQueueLength());
+        lock.unlock();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT_EQUAL(0, lock.getQueueLength());
+        t1.join();
+        t2.join();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testHasQueuedThreadNPE() {
+
+    ReentrantLock sync;
+    try {
+        sync.hasQueuedThread(NULL);
+        shouldThrow();
+    } catch(NullPointerException& success) {
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testHasQueuedThread() {
+
+    ReentrantLock sync;
+
+    InterruptedLockRunnable interrupted(&sync, this);
+    InterruptibleLockRunnable interruptable(&sync, this);
+
+    Thread t1(&interrupted);
+    Thread t2(&interruptable);
+
+    try {
+        CPPUNIT_ASSERT(!sync.hasQueuedThread(&t1));
+        CPPUNIT_ASSERT(!sync.hasQueuedThread(&t2));
+        sync.lock();
+        t1.start();
+        Thread::sleep( SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(sync.hasQueuedThread(&t1));
+        t2.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(sync.hasQueuedThread(&t1));
+        CPPUNIT_ASSERT(sync.hasQueuedThread(&t2));
+        t1.interrupt();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!sync.hasQueuedThread(&t1));
+        CPPUNIT_ASSERT(sync.hasQueuedThread(&t2));
+        sync.unlock();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!sync.hasQueuedThread(&t1));
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!sync.hasQueuedThread(&t2));
+        t1.join();
+        t2.join();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetQueuedThreads() {
+
+    PublicReentrantLock lock;
+
+    InterruptedLockRunnable interrupted(&lock, this);
+    InterruptibleLockRunnable interruptable(&lock, this);
+
+    Thread t1(&interrupted);
+    Thread t2(&interruptable);
+
+    try {
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getQueuedThreads())->isEmpty());
+        lock.lock();
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getQueuedThreads())->isEmpty());
+        t1.start();
+        Thread::sleep( SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getQueuedThreads())->contains(&t1));
+        t2.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getQueuedThreads())->contains(&t1));
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getQueuedThreads())->contains(&t2));
+        t1.interrupt();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!std::auto_ptr<Collection<Thread*> >(lock.getQueuedThreads())->contains(&t1));
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getQueuedThreads())->contains(&t2));
+        lock.unlock();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getQueuedThreads())->isEmpty());
+        t1.join();
+        t2.join();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestInterruptedException2Runnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestInterruptedException2Runnable(ReentrantLock* lock, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), parent(parent) {}
+        virtual ~TestInterruptedException2Runnable() {}
+
+        virtual void run() {
+            try {
+                lock->tryLock(ReentrantLockTest::MEDIUM_DELAY_MS, TimeUnit::MILLISECONDS);
+                parent->threadShouldThrow();
+            } catch(InterruptedException& success){}
+        }
+    };
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testInterruptedException2() {
+
+    ReentrantLock lock;
+    lock.lock();
+
+    TestInterruptedException2Runnable runnable(&lock, this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        t.interrupt();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestTryLockWhenLockedRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestTryLockWhenLockedRunnable(ReentrantLock* lock, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), parent(parent) {}
+        virtual ~TestTryLockWhenLockedRunnable() {}
+
+        virtual void run() {
+            parent->threadAssertFalse(lock->tryLock());
+        }
+    };
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testTryLockWhenLocked() {
+
+    ReentrantLock lock;
+    TestTryLockWhenLockedRunnable runnable(&lock, this);
+    lock.lock();
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        t.join();
+        lock.unlock();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestTryLockTimeoutRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestTryLockTimeoutRunnable(ReentrantLock* lock, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), parent(parent) {}
+        virtual ~TestTryLockTimeoutRunnable() {}
+
+        virtual void run() {
+            try {
+                parent->threadAssertFalse(lock->tryLock(1, TimeUnit::MILLISECONDS));
+            } catch (Exception& ex) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testTryLockTimeout() {
+    ReentrantLock lock;
+    lock.lock();
+    TestTryLockTimeoutRunnable runnable(&lock, this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        t.join();
+        lock.unlock();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetHoldCount() {
+    ReentrantLock lock;
+    const int SIZE = 50;
+
+    for(int i = 1; i <= SIZE; i++) {
+        lock.lock();
+        CPPUNIT_ASSERT_EQUAL(i,lock.getHoldCount());
+    }
+    for(int i = SIZE; i > 0; i--) {
+        lock.unlock();
+        CPPUNIT_ASSERT_EQUAL(i-1,lock.getHoldCount());
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestIsLockedRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestIsLockedRunnable(ReentrantLock* lock, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), parent(parent) {}
+        virtual ~TestIsLockedRunnable() {}
+
+        virtual void run() {
+            lock->lock();
+            try {
+                Thread::sleep(ReentrantLockTest::SMALL_DELAY_MS);
+            } catch(Exception& e) {
+                parent->threadUnexpectedException();
+            }
+            lock->unlock();
+        }
+    };
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testIsLocked() {
+
+    ReentrantLock lock;
+    lock.lock();
+    CPPUNIT_ASSERT(lock.isLocked());
+    lock.unlock();
+    CPPUNIT_ASSERT(!lock.isLocked());
+    TestIsLockedRunnable runnable(&lock, this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(lock.isLocked());
+        t.join();
+        CPPUNIT_ASSERT(!lock.isLocked());
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testLockInterruptibly1() {
+    ReentrantLock lock;
+    lock.lock();
+    InterruptedLockRunnable runnable(&lock, this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        t.interrupt();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.unlock();
+        t.join();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testLockInterruptibly2() {
+    ReentrantLock lock;
+    try {
+        lock.lockInterruptibly();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+
+    InterruptedLockRunnable runnable(&lock, this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        t.interrupt();
+        CPPUNIT_ASSERT(lock.isLocked());
+        CPPUNIT_ASSERT(lock.isHeldByCurrentThread());
+        t.join();
+    } catch(Exception& e) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitIllegalMonitor() {
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    try {
+        c->await();
+        shouldThrow();
+    } catch(IllegalMonitorStateException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testSignalIllegalMonitor() {
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    try {
+        c->signal();
+        shouldThrow();
+    } catch(IllegalMonitorStateException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitNanosTimeout() {
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    try {
+        lock.lock();
+        long long t = c->awaitNanos(100);
+        CPPUNIT_ASSERT(t <= 0);
+        lock.unlock();
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitTimeout() {
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    try {
+        lock.lock();
+        c->await(SHORT_DELAY_MS, TimeUnit::MILLISECONDS);
+        lock.unlock();
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitUntilTimeout() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    try {
+        lock.lock();
+        Date d;
+        c->awaitUntil(Date(d.getTime() + 10));
+        lock.unlock();
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestAwaitRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestAwaitRunnable(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestAwaitRunnable() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                condition->await();
+                lock->unlock();
+            } catch(Exception& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwait() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestAwaitRunnable runnable(&lock, c.get(), this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.lock();
+        c->signal();
+        lock.unlock();
+        t.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t.isAlive());
+    } catch (Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testHasWaitersNPE() {
+    ReentrantLock lock;
+    try {
+        lock.hasWaiters(NULL);
+        shouldThrow();
+    } catch(NullPointerException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetWaitQueueLengthNPE() {
+    ReentrantLock lock;
+    try {
+        lock.getWaitQueueLength(NULL);
+        shouldThrow();
+    } catch(NullPointerException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetWaitingThreadsNPE() {
+    PublicReentrantLock lock;
+    try {
+        lock.getWaitingThreads(NULL);
+        shouldThrow();
+    } catch(NullPointerException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testHasWaitersIAE() {
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    ReentrantLock lock2;
+    try {
+        lock2.hasWaiters(c.get());
+        shouldThrow();
+    } catch(IllegalArgumentException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testHasWaitersIMSE() {
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    try {
+        lock.hasWaiters(c.get());
+        shouldThrow();
+    } catch(IllegalMonitorStateException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetWaitQueueLengthIAE() {
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    ReentrantLock lock2;
+    try {
+        lock2.getWaitQueueLength(c.get());
+        shouldThrow();
+    } catch(IllegalArgumentException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetWaitQueueLengthIMSE() {
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    try {
+        lock.getWaitQueueLength(c.get());
+        shouldThrow();
+    } catch(IllegalMonitorStateException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetWaitingThreadsIAE() {
+
+    PublicReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    PublicReentrantLock lock2;
+    try {
+        lock2.getWaitingThreads(c.get());
+        shouldThrow();
+    } catch(IllegalArgumentException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetWaitingThreadsIMSE() {
+
+    PublicReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    try {
+        lock.getWaitingThreads(c.get());
+        shouldThrow();
+    } catch(IllegalMonitorStateException& success) {
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestHasWaitersRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestHasWaitersRunnable(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestHasWaitersRunnable() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                parent->threadAssertFalse(lock->hasWaiters(condition));
+                parent->threadAssertEquals(0, lock->getWaitQueueLength(condition));
+                condition->await();
+                lock->unlock();
+            } catch(Exception& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testHasWaiters() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestHasWaitersRunnable runnable(&lock, c.get(), this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.lock();
+        CPPUNIT_ASSERT(lock.hasWaiters(c.get()));
+        CPPUNIT_ASSERT_EQUAL(1, lock.getWaitQueueLength(c.get()));
+        c->signal();
+        lock.unlock();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.lock();
+        CPPUNIT_ASSERT(!lock.hasWaiters(c.get()));
+        CPPUNIT_ASSERT_EQUAL(0, lock.getWaitQueueLength(c.get()));
+        lock.unlock();
+        t.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestGetWaitQueueLengthRunnable1 : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestGetWaitQueueLengthRunnable1(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestGetWaitQueueLengthRunnable1() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                parent->threadAssertFalse(lock->hasWaiters(condition));
+                parent->threadAssertEquals(0, lock->getWaitQueueLength(condition));
+                condition->await();
+                lock->unlock();
+            } catch(Exception& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+
+    class TestGetWaitQueueLengthRunnable2 : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestGetWaitQueueLengthRunnable2(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestGetWaitQueueLengthRunnable2() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                parent->threadAssertTrue(lock->hasWaiters(condition));
+                parent->threadAssertEquals(1, lock->getWaitQueueLength(condition));
+                condition->await();
+                lock->unlock();
+            } catch(Exception& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetWaitQueueLength() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestGetWaitQueueLengthRunnable1 runnable1(&lock, c.get(), this);
+    Thread t1(&runnable1);
+    TestGetWaitQueueLengthRunnable2 runnable2(&lock, c.get(), this);
+    Thread t2(&runnable2);
+
+    try {
+        t1.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        t2.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.lock();
+        CPPUNIT_ASSERT(lock.hasWaiters(c.get()));
+        CPPUNIT_ASSERT_EQUAL(2, lock.getWaitQueueLength(c.get()));
+        c->signalAll();
+        lock.unlock();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.lock();
+        CPPUNIT_ASSERT(!lock.hasWaiters(c.get()));
+        CPPUNIT_ASSERT_EQUAL(0, lock.getWaitQueueLength(c.get()));
+        lock.unlock();
+        t1.join(SHORT_DELAY_MS);
+        t2.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t1.isAlive());
+        CPPUNIT_ASSERT(!t2.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestGetWaitingThreadsRunnable1 : public Runnable {
+    private:
+
+        PublicReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestGetWaitingThreadsRunnable1(PublicReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestGetWaitingThreadsRunnable1() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                parent->threadAssertTrue(std::auto_ptr<Collection<Thread*> >(lock->getWaitingThreads(condition))->isEmpty());
+                condition->await();
+                lock->unlock();
+            } catch(Exception& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+
+    class TestGetWaitingThreadsRunnable2 : public Runnable {
+    private:
+
+        PublicReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestGetWaitingThreadsRunnable2(PublicReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestGetWaitingThreadsRunnable2() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                parent->threadAssertFalse(std::auto_ptr<Collection<Thread*> >(lock->getWaitingThreads(condition))->isEmpty());
+                condition->await();
+                lock->unlock();
+            } catch(Exception& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testGetWaitingThreads() {
+
+    PublicReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestGetWaitingThreadsRunnable1 runnable1(&lock, c.get(), this);
+    Thread t1(&runnable1);
+    TestGetWaitingThreadsRunnable2 runnable2(&lock, c.get(), this);
+    Thread t2(&runnable2);
+
+    try {
+        lock.lock();
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getWaitingThreads(c.get()))->isEmpty());
+        lock.unlock();
+        t1.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        t2.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.lock();
+        CPPUNIT_ASSERT(lock.hasWaiters(c.get()));
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getWaitingThreads(c.get()))->contains(&t1));
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getWaitingThreads(c.get()))->contains(&t2));
+        c->signalAll();
+        lock.unlock();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.lock();
+        CPPUNIT_ASSERT(!lock.hasWaiters(c.get()));
+        CPPUNIT_ASSERT(std::auto_ptr<Collection<Thread*> >(lock.getWaitingThreads(c.get()))->isEmpty());
+        lock.unlock();
+        t1.join(SHORT_DELAY_MS);
+        t2.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t1.isAlive());
+        CPPUNIT_ASSERT(!t2.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitUninterruptibly() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    UninterruptableThread thread(&lock, c.get());
+
+    try {
+        thread.start();
+
+        while(!thread.lockStarted) {
+            Thread::sleep(100);
+        }
+
+        lock.lock();
+        try {
+            thread.interrupt();
+            thread.canAwake = true;
+            c->signal();
+        } catch(...) {
+        }
+        lock.unlock();
+
+        thread.join();
+        CPPUNIT_ASSERT(thread.interrupted);
+        CPPUNIT_ASSERT(!thread.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestAwaitInterruptRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestAwaitInterruptRunnable(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestAwaitInterruptRunnable() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                condition->await();
+                lock->unlock();
+                parent->threadShouldThrow();
+            } catch(InterruptedException& e) {
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitInterrupt() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestAwaitInterruptRunnable runnable(&lock, c.get(), this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        t.interrupt();
+        t.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestAwaitNanosInterruptRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestAwaitNanosInterruptRunnable(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestAwaitNanosInterruptRunnable() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                condition->awaitNanos(1000 * 1000 * 1000); // 1 sec
+                lock->unlock();
+                parent->threadShouldThrow();
+            } catch(InterruptedException& e) {
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitNanosInterrupt() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestAwaitNanosInterruptRunnable runnable(&lock, c.get(), this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        t.interrupt();
+        t.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestAwaitUntilInterruptRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestAwaitUntilInterruptRunnable(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestAwaitUntilInterruptRunnable() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                Date d;
+                condition->awaitUntil(Date(d.getTime() + 10000));
+                lock->unlock();
+                parent->threadShouldThrow();
+            } catch(InterruptedException& e) {
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitUntilInterrupt() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestAwaitNanosInterruptRunnable runnable(&lock, c.get(), this);
+    Thread t(&runnable);
+
+    try {
+        t.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        t.interrupt();
+        t.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestSignalAllRunnable : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestSignalAllRunnable(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestSignalAllRunnable() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                condition->await();
+                lock->unlock();
+            } catch(InterruptedException& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testSignalAll() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestSignalAllRunnable runnable1(&lock, c.get(), this);
+    Thread t1(&runnable1);
+    TestSignalAllRunnable runnable2(&lock, c.get(), this);
+    Thread t2(&runnable2);
+
+    try {
+        t1.start();
+        t2.start();
+        Thread::sleep(SHORT_DELAY_MS);
+        lock.lock();
+        c->signalAll();
+        lock.unlock();
+        t1.join(SHORT_DELAY_MS);
+        t2.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t1.isAlive());
+        CPPUNIT_ASSERT(!t2.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class TestAwaitLockCountRunnable1 : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestAwaitLockCountRunnable1(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestAwaitLockCountRunnable1() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                parent->threadAssertEquals(1, lock->getHoldCount());
+                condition->await();
+                parent->threadAssertEquals(1, lock->getHoldCount());
+                lock->unlock();
+            } catch(InterruptedException& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+
+    class TestAwaitLockCountRunnable2 : public Runnable {
+    private:
+
+        ReentrantLock* lock;
+        Condition* condition;
+        ReentrantLockTest* parent;
+
+    public:
+
+        TestAwaitLockCountRunnable2(ReentrantLock* lock, Condition* condition, ReentrantLockTest* parent) :
+            Runnable(), lock(lock), condition(condition), parent(parent) {}
+        virtual ~TestAwaitLockCountRunnable2() {}
+
+        virtual void run() {
+            try {
+                lock->lock();
+                lock->lock();
+                parent->threadAssertEquals(2, lock->getHoldCount());
+                condition->await();
+                parent->threadAssertEquals(2, lock->getHoldCount());
+                lock->unlock();
+                lock->unlock();
+            } catch(InterruptedException& e) {
+                parent->threadUnexpectedException();
+            }
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testAwaitLockCount() {
+
+    ReentrantLock lock;
+    std::auto_ptr<Condition> c(lock.newCondition());
+    TestAwaitLockCountRunnable1 runnable1(&lock, c.get(), this);
+    Thread t1(&runnable1);
+    TestAwaitLockCountRunnable2 runnable2(&lock, c.get(), this);
+    Thread t2(&runnable2);
+
+    try {
+        t1.start();
+        t2.start();
+        Thread::sleep( SHORT_DELAY_MS);
+        lock.lock();
+        c->signalAll();
+        lock.unlock();
+        t1.join(SHORT_DELAY_MS);
+        t2.join(SHORT_DELAY_MS);
+        CPPUNIT_ASSERT(!t1.isAlive());
+        CPPUNIT_ASSERT(!t2.isAlive());
+    } catch(Exception& ex) {
+        unexpectedException();
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void ReentrantLockTest::testToString() {
+
+    ReentrantLock lock;
+    std::string us = lock.toString();
+    CPPUNIT_ASSERT((int)us.find_first_of("Unlocked") >= 0);
+    lock.lock();
+    std::string ls = lock.toString();
+    CPPUNIT_ASSERT((int)ls.find_first_of("Locked") >= 0);
+}

Propchange: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.h?rev=1126283&view=auto
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.h (added)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.h Mon May 23 00:26:26 2011
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+#ifndef _DECAF_UTIL_CONCURRENT_LOCKS_REENTRANTLOCKTEST_H_
+#define _DECAF_UTIL_CONCURRENT_LOCKS_REENTRANTLOCKTEST_H_
+
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <decaf/util/concurrent/ExecutorsTestSupport.h>
+
+namespace decaf {
+namespace util {
+namespace concurrent {
+namespace locks {
+
+    class ReentrantLockTest : public ExecutorsTestSupport {
+
+        CPPUNIT_TEST_SUITE( ReentrantLockTest );
+        CPPUNIT_TEST( testConstructor );
+        CPPUNIT_TEST( testLock );
+        CPPUNIT_TEST( testFairLock );
+        CPPUNIT_TEST( testUnlockIllegalMonitorStateException );
+        CPPUNIT_TEST( testTryLock );
+        CPPUNIT_TEST( testhasQueuedThreads );
+        CPPUNIT_TEST( testGetQueueLength );
+        CPPUNIT_TEST( testGetQueueLengthFair );
+        CPPUNIT_TEST( testHasQueuedThreadNPE );
+        CPPUNIT_TEST( testHasQueuedThread );
+        CPPUNIT_TEST( testGetQueuedThreads );
+        CPPUNIT_TEST( testInterruptedException2 );
+        CPPUNIT_TEST( testTryLockWhenLocked );
+        CPPUNIT_TEST( testTryLockTimeout );
+        CPPUNIT_TEST( testGetHoldCount );
+        CPPUNIT_TEST( testIsLocked );
+        CPPUNIT_TEST( testLockInterruptibly1 );
+        CPPUNIT_TEST( testLockInterruptibly2 );
+        CPPUNIT_TEST( testAwaitIllegalMonitor );
+        CPPUNIT_TEST( testSignalIllegalMonitor );
+        CPPUNIT_TEST( testAwaitNanosTimeout );
+        CPPUNIT_TEST( testAwaitTimeout );
+        CPPUNIT_TEST( testAwaitUntilTimeout );
+        CPPUNIT_TEST( testAwait );
+        CPPUNIT_TEST( testHasWaitersNPE );
+        CPPUNIT_TEST( testGetWaitQueueLengthNPE );
+        CPPUNIT_TEST( testGetWaitingThreadsNPE );
+        CPPUNIT_TEST( testHasWaitersIAE );
+        CPPUNIT_TEST( testHasWaitersIMSE );
+        CPPUNIT_TEST( testGetWaitQueueLengthIAE );
+        CPPUNIT_TEST( testGetWaitQueueLengthIMSE );
+        CPPUNIT_TEST( testGetWaitingThreadsIAE );
+        CPPUNIT_TEST( testGetWaitingThreadsIMSE );
+        CPPUNIT_TEST( testHasWaiters );
+        CPPUNIT_TEST( testGetWaitQueueLength );
+        CPPUNIT_TEST( testGetWaitingThreads );
+        CPPUNIT_TEST( testAwaitUninterruptibly );
+        CPPUNIT_TEST( testAwaitInterrupt );
+        CPPUNIT_TEST( testAwaitNanosInterrupt );
+        CPPUNIT_TEST( testAwaitUntilInterrupt );
+        CPPUNIT_TEST( testSignalAll );
+        CPPUNIT_TEST( testAwaitLockCount );
+        CPPUNIT_TEST( testToString );
+        CPPUNIT_TEST_SUITE_END();
+
+    public:
+
+        ReentrantLockTest();
+        virtual ~ReentrantLockTest();
+
+        void testConstructor();
+        void testLock();
+        void testFairLock();
+        void testUnlockIllegalMonitorStateException();
+        void testTryLock();
+        void testhasQueuedThreads();
+        void testGetQueueLength();
+        void testGetQueueLengthFair();
+        void testHasQueuedThreadNPE();
+        void testHasQueuedThread();
+        void testGetQueuedThreads();
+        void testInterruptedException2();
+        void testTryLockWhenLocked();
+        void testTryLockTimeout();
+        void testGetHoldCount();
+        void testIsLocked();
+        void testLockInterruptibly1();
+        void testLockInterruptibly2();
+        void testAwaitIllegalMonitor();
+        void testSignalIllegalMonitor();
+        void testAwaitNanosTimeout();
+        void testAwaitTimeout();
+        void testAwaitUntilTimeout();
+        void testAwait();
+        void testHasWaitersNPE();
+        void testGetWaitQueueLengthNPE();
+        void testGetWaitingThreadsNPE();
+        void testHasWaitersIAE();
+        void testHasWaitersIMSE();
+        void testGetWaitQueueLengthIAE();
+        void testGetWaitQueueLengthIMSE();
+        void testGetWaitingThreadsIAE();
+        void testGetWaitingThreadsIMSE();
+        void testHasWaiters();
+        void testGetWaitQueueLength();
+        void testGetWaitingThreads();
+        void testAwaitUninterruptibly();
+        void testAwaitInterrupt();
+        void testAwaitNanosInterrupt();
+        void testAwaitUntilInterrupt();
+        void testSignalAll();
+        void testAwaitLockCount();
+        void testToString();
+
+    };
+
+}}}}
+
+#endif /* _DECAF_UTIL_CONCURRENT_LOCKS_REENTRANTLOCKTEST_H_ */

Propchange: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/concurrent/locks/ReentrantLockTest.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp?rev=1126283&r1=1126282&r2=1126283&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/testRegistry.cpp Mon May 23 00:26:26 2011
@@ -291,6 +291,10 @@ CPPUNIT_TEST_SUITE_REGISTRATION( decaf::
 
 #include <decaf/util/concurrent/locks/LockSupportTest.h>
 CPPUNIT_TEST_SUITE_REGISTRATION( decaf::util::concurrent::locks::LockSupportTest );
+#include <decaf/util/concurrent/locks/AbstractQueuedSynchronizerTest.h>
+CPPUNIT_TEST_SUITE_REGISTRATION( decaf::util::concurrent::locks::AbstractQueuedSynchronizerTest );
+#include <decaf/util/concurrent/locks/ReentrantLockTest.h>
+CPPUNIT_TEST_SUITE_REGISTRATION( decaf::util::concurrent::locks::ReentrantLockTest );
 
 #include <decaf/util/AbstractCollectionTest.h>
 CPPUNIT_TEST_SUITE_REGISTRATION( decaf::util::AbstractCollectionTest );