Commit 7df75988 authored by Jason Rhinelander's avatar Jason Rhinelander

Use a C++14 std::shared_timed_mutex for locking

This significantly simplifies the member locking implementation since we
no longer have to worry about tracking the number of active locks;
instead read locks are shared locks and write locks are exclusive locks;
the stl implementation can worry about the details beyond that.

This also disallows recursive member locks; instead calling code has to
manage itself to avoid double-locking a member.  Note also that
switching a write lock to a read lock is no longer guaranteed to be
non-blocking as there is no way to downgrade an exclusive lock to a
shared lock.  boost::upgrade_mutex could allow this, but this importance
of this is minor and it seems nicer to get rid of the boost dependency.

It also changes the main Simulation run lock to be the same stl
implementation; previously it was using the boost implementation.

With that, the boost thread, date_time, and atomic library components
are no longer required.
parent 9d4ca568
......@@ -118,7 +118,7 @@ else()
endif()
include_directories(${EIGEN3_INCLUDE_DIR})
find_package(Boost REQUIRED COMPONENTS filesystem thread system chrono date_time atomic)
find_package(Boost REQUIRED COMPONENTS filesystem system)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
......
This diff is collapsed.
This diff is collapsed.
......@@ -427,16 +427,16 @@ void Simulation::thr_thread_pool() {
}
}
boost::shared_lock<boost::shared_mutex> Simulation::runLock() {
return boost::shared_lock<boost::shared_mutex>(run_mutex_);
std::shared_lock<std::shared_timed_mutex> Simulation::runLock() {
return std::shared_lock<std::shared_timed_mutex>(run_mutex_);
}
boost::shared_lock<boost::shared_mutex> Simulation::runLockTry() {
return boost::shared_lock<boost::shared_mutex>(run_mutex_, boost::try_to_lock);
std::shared_lock<std::shared_timed_mutex> Simulation::runLockTry() {
return std::shared_lock<std::shared_timed_mutex>(run_mutex_, std::try_to_lock);
}
void Simulation::run() {
boost::unique_lock<boost::shared_mutex> lock(run_mutex_);
std::unique_lock<std::shared_timed_mutex> lock(run_mutex_);
stage_mutex_.lock();
stage_ = RunStage::idle;
......
......@@ -19,9 +19,7 @@
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/lock_types.hpp>
#include <shared_mutex>
/// Base namespace containing all eris classes.
namespace eris {
......@@ -422,13 +420,13 @@ class Simulation : public std::enable_shared_from_this<Simulation>, private nonc
* ensuring that it does not run simultaneously with an active run call. This lock is held
* (exclusively!) during run().
*/
boost::shared_lock<boost::shared_mutex> runLock();
std::shared_lock<std::shared_timed_mutex> runLock();
/** Tries to obtain a lock that, when held, guarantees that a simulation stage is not in
* progress. If the lock cannot be obtained (i.e. because something else already holds it),
* this returns an unheld lock object.
*/
boost::shared_lock<boost::shared_mutex> runLockTry();
std::shared_lock<std::shared_timed_mutex> runLockTry();
/** Contains the number of rounds of the intra-period optimizers in the previous run() call.
* A round is defined by a intraReset() call, a set of intraOptimize() calls, and a set of
......@@ -540,7 +538,7 @@ class Simulation : public std::enable_shared_from_this<Simulation>, private nonc
// Mutex held exclusively during a run which is available for outside threads to ensure
// operation not during an active stage. See runLock() and runLockTry()
boost::shared_mutex run_mutex_;
std::shared_timed_mutex run_mutex_;
// Pool of threads we can use
std::vector<std::thread> thr_pool_;
......
......@@ -21,7 +21,7 @@ std::vector<int> order;
std::mutex orderlock;
// Different sleep timings are multiples of 1 to 20 times this value (in milliseconds)
constexpr int SLEEP_SCALE = 10;
constexpr int SLEEP_SCALE = 100;
void sleep_ms(int x) {
std::this_thread::sleep_for(std::chrono::milliseconds(x));
......@@ -110,7 +110,6 @@ void thr_code8() {
record_finished(8);
}
int main() {
......@@ -136,12 +135,13 @@ int main() {
for (auto &t : threads) t.join();
if (order == std::vector<int>({ 8, 7, 5, 1, 2, 3, 6, 4 })) {
std::cout << "Lock test passed (8-7-5-1-2-3-6-4)\n";
// FIXME: broken since switch to boost::upgrade_mutex
if (order == std::vector<int>({ 7, 5, 8, 1, 2, 3, 6, 4 })) {
std::cout << "Lock test passed (7-5-8-1-2-3-6-4)\n";
seq1++;
}
else if (order == std::vector<int>({ 8, 7, 6, 5, 1, 2, 3, 4 })) {
std::cout << "Lock test passed (8-7-6-5-1-2-3-4)\n";
else if (order == std::vector<int>({ 7, 5, 8, 6, 1, 2, 3, 4 })) {
std::cout << "Lock test passed (7-5-8-6-1-2-3-4)\n";
seq2++;
}
else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment