diff options
author | Casey Rodarmor <casey@rodarmor.com> | 2015-09-03 12:53:00 -0400 |
---|---|---|
committer | Casey Rodarmor <casey@rodarmor.com> | 2015-09-03 15:13:40 -0400 |
commit | 86270c816411680c33a60adfa768c7a647fce08f (patch) | |
tree | 8e8e3f427d23ec88dab51cb99ab5314590997f75 | |
parent | da9beb288d2ee35b9c70513dd18f220b2dc32f16 (diff) |
Replace boost::reverse_lock with our own.
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/Makefile.test.include | 1 | ||||
-rw-r--r-- | src/reverselock.h | 31 | ||||
-rw-r--r-- | src/scheduler.cpp | 5 | ||||
-rw-r--r-- | src/test/reverselock_tests.cpp | 64 |
5 files changed, 100 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index cc8dded413..456dfc32ce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -119,6 +119,7 @@ BITCOIN_CORE_H = \ protocol.h \ pubkey.h \ random.h \ + reverselock.h \ rpcclient.h \ rpcprotocol.h \ rpcserver.h \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index fc4e047c35..cc60cd92bb 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -62,6 +62,7 @@ BITCOIN_TESTS =\ test/pmt_tests.cpp \ test/policyestimator_tests.cpp \ test/pow_tests.cpp \ + test/reverselock_tests.cpp \ test/rpc_tests.cpp \ test/sanity_tests.cpp \ test/scheduler_tests.cpp \ diff --git a/src/reverselock.h b/src/reverselock.h new file mode 100644 index 0000000000..567636e16a --- /dev/null +++ b/src/reverselock.h @@ -0,0 +1,31 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_REVERSELOCK_H +#define BITCOIN_REVERSELOCK_H + +/** + * An RAII-style reverse lock. Unlocks on construction and locks on destruction. + */ +template<typename Lock> +class reverse_lock +{ +public: + + explicit reverse_lock(Lock& lock) : lock(lock) { + lock.unlock(); + } + + ~reverse_lock() { + lock.lock(); + } + +private: + reverse_lock(reverse_lock const&); + reverse_lock& operator=(reverse_lock const&); + + Lock& lock; +}; + +#endif // BITCOIN_REVERSELOCK_H diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 06115f5619..184ddc28ab 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -4,9 +4,10 @@ #include "scheduler.h" +#include "reverselock.h" + #include <assert.h> #include <boost/bind.hpp> -#include <boost/thread/reverse_lock.hpp> #include <utility> CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false) @@ -69,7 +70,7 @@ void CScheduler::serviceQueue() { // Unlock before calling f, so it can reschedule itself or another task // without deadlocking: - boost::reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock); + reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock); f(); } } catch (...) { diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp new file mode 100644 index 0000000000..e7e627ae0f --- /dev/null +++ b/src/test/reverselock_tests.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "reverselock.h" +#include "test/test_bitcoin.h" + +#include <boost/test/unit_test.hpp> + +BOOST_FIXTURE_TEST_SUITE(reverselock_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(reverselock_basics) +{ + boost::mutex mutex; + boost::unique_lock<boost::mutex> lock(mutex); + + BOOST_CHECK(lock.owns_lock()); + { + reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock); + BOOST_CHECK(!lock.owns_lock()); + } + BOOST_CHECK(lock.owns_lock()); +} + +BOOST_AUTO_TEST_CASE(reverselock_errors) +{ + boost::mutex mutex; + boost::unique_lock<boost::mutex> lock(mutex); + + // Make sure trying to reverse lock an unlocked lock fails + lock.unlock(); + + BOOST_CHECK(!lock.owns_lock()); + + bool failed = false; + try { + reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock); + } catch(...) { + failed = true; + } + + BOOST_CHECK(failed); + BOOST_CHECK(!lock.owns_lock()); + + // Make sure trying to lock a lock after it has been reverse locked fails + failed = false; + bool locked = false; + + lock.lock(); + BOOST_CHECK(lock.owns_lock()); + + try { + reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock); + lock.lock(); + locked = true; + } catch(...) { + failed = true; + } + + BOOST_CHECK(locked && failed); + BOOST_CHECK(lock.owns_lock()); +} + +BOOST_AUTO_TEST_SUITE_END() |