refactor lockstep_scheduler: fix class member naming convention

This commit is contained in:
Beat Küng 2019-01-09 13:30:40 +01:00 committed by Julian Oes
parent 828e31d3a9
commit 2a47715385
3 changed files with 58 additions and 57 deletions

View File

@ -13,13 +13,11 @@ public:
~LockstepScheduler();
void set_absolute_time(uint64_t time_us);
inline uint64_t get_absolute_time() const { return time_us_; }
inline uint64_t get_absolute_time() const { return _time_us; }
int cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *lock, uint64_t time_us);
int usleep_until(uint64_t timed_us);
private:
std::atomic<uint64_t> time_us_{0};
struct TimedWait {
~TimedWait()
{
@ -42,7 +40,10 @@ private:
TimedWait *next{nullptr}; ///< linked list
};
TimedWait *timed_waits_{nullptr}; ///< head of linked list
std::mutex timed_waits_mutex_;
std::atomic<bool> setting_time_{false}; ///< true if set_absolute_time() is currently being executed
std::atomic<uint64_t> _time_us{0};
TimedWait *_timed_waits{nullptr}; ///< head of linked list
std::mutex _timed_waits_mutex;
std::atomic<bool> _setting_time{false}; ///< true if set_absolute_time() is currently being executed
};

View File

@ -3,24 +3,24 @@
LockstepScheduler::~LockstepScheduler()
{
// cleanup the linked list
std::unique_lock<std::mutex> lock_timed_waits(timed_waits_mutex_);
std::unique_lock<std::mutex> lock_timed_waits(_timed_waits_mutex);
while (timed_waits_) {
TimedWait *tmp = timed_waits_;
timed_waits_ = timed_waits_->next;
while (_timed_waits) {
TimedWait *tmp = _timed_waits;
_timed_waits = _timed_waits->next;
tmp->removed = true;
}
}
void LockstepScheduler::set_absolute_time(uint64_t time_us)
{
time_us_ = time_us;
_time_us = time_us;
{
std::unique_lock<std::mutex> lock_timed_waits(timed_waits_mutex_);
setting_time_ = true;
std::unique_lock<std::mutex> lock_timed_waits(_timed_waits_mutex);
_setting_time = true;
TimedWait *timed_wait = timed_waits_;
TimedWait *timed_wait = _timed_waits;
TimedWait *timed_wait_prev = nullptr;
while (timed_wait) {
@ -31,7 +31,7 @@ void LockstepScheduler::set_absolute_time(uint64_t time_us)
timed_wait_prev->next = timed_wait->next;
} else {
timed_waits_ = timed_wait->next;
_timed_waits = timed_wait->next;
}
TimedWait *tmp = timed_wait;
@ -54,7 +54,7 @@ void LockstepScheduler::set_absolute_time(uint64_t time_us)
timed_wait = timed_wait->next;
}
setting_time_ = false;
_setting_time = false;
}
}
@ -64,10 +64,10 @@ int LockstepScheduler::cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *loc
// longer. And using thread_local is more efficient than malloc.
static thread_local TimedWait timed_wait;
{
std::lock_guard<std::mutex> lock_timed_waits(timed_waits_mutex_);
std::lock_guard<std::mutex> lock_timed_waits(_timed_waits_mutex);
// The time has already passed.
if (time_us <= time_us_) {
if (time_us <= _time_us) {
return ETIMEDOUT;
}
@ -80,8 +80,8 @@ int LockstepScheduler::cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *loc
// Add to linked list if not removed yet (otherwise just re-use the object)
if (timed_wait.removed) {
timed_wait.removed = false;
timed_wait.next = timed_waits_;
timed_waits_ = &timed_wait;
timed_wait.next = _timed_waits;
_timed_waits = &timed_wait;
}
}
@ -95,7 +95,7 @@ int LockstepScheduler::cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *loc
timed_wait.done = true;
if (!timeout && setting_time_) {
if (!timeout && _setting_time) {
// This is where it gets tricky: the timeout has not been triggered yet,
// and another thread is in set_absolute_time().
// If it already passed the 'done' check, it will access the mutex and
@ -106,8 +106,8 @@ int LockstepScheduler::cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *loc
// Note that this case does not happen too frequently, and thus can be
// a bit more expensive.
pthread_mutex_unlock(lock);
timed_waits_mutex_.lock();
timed_waits_mutex_.unlock();
_timed_waits_mutex.lock();
_timed_waits_mutex.unlock();
pthread_mutex_lock(lock);
}

View File

@ -125,69 +125,69 @@ class TestCase
{
public:
TestCase(unsigned timeout, unsigned unlocked_after, LockstepScheduler &ls) :
timeout_(timeout + some_time_us),
unlocked_after_(unlocked_after + some_time_us),
ls_(ls)
_timeout(timeout + some_time_us),
_unlocked_after(unlocked_after + some_time_us),
_ls(ls)
{
pthread_mutex_init(&lock_, NULL);
pthread_cond_init(&cond_, NULL);
pthread_mutex_init(&_lock, NULL);
pthread_cond_init(&_cond, NULL);
}
~TestCase()
{
assert(is_done_);
pthread_mutex_destroy(&lock_);
pthread_cond_destroy(&cond_);
assert(_is_done);
pthread_mutex_destroy(&_lock);
pthread_cond_destroy(&_cond);
}
void run()
{
pthread_mutex_lock(&lock_);
thread_ = std::make_shared<TestThread>([this]() {
result_ = ls_.cond_timedwait(&cond_, &lock_, timeout_);
pthread_mutex_unlock(&lock_);
pthread_mutex_lock(&_lock);
_thread = std::make_shared<TestThread>([this]() {
_result = _ls.cond_timedwait(&_cond, &_lock, _timeout);
pthread_mutex_unlock(&_lock);
});
}
void check()
{
if (is_done_) {
if (_is_done) {
return;
}
uint64_t time_us = ls_.get_absolute_time();
uint64_t time_us = _ls.get_absolute_time();
const bool unlock_reached = (time_us >= unlocked_after_);
const bool unlock_is_before_timeout = (unlocked_after_ <= timeout_);
const bool timeout_reached = (time_us >= timeout_);
const bool unlock_reached = (time_us >= _unlocked_after);
const bool unlock_is_before_timeout = (_unlocked_after <= _timeout);
const bool timeout_reached = (time_us >= _timeout);
if (unlock_reached && unlock_is_before_timeout && !(timeout_reached)) {
pthread_mutex_lock(&lock_);
pthread_cond_broadcast(&cond_);
pthread_mutex_unlock(&lock_);
is_done_ = true;
pthread_mutex_lock(&_lock);
pthread_cond_broadcast(&_cond);
pthread_mutex_unlock(&_lock);
_is_done = true;
// We can be sure that this triggers.
thread_->join(ls_);
assert(result_ == 0);
_thread->join(_ls);
assert(_result == 0);
}
else if (timeout_reached) {
is_done_ = true;
thread_->join(ls_);
assert(result_ == ETIMEDOUT);
_is_done = true;
_thread->join(_ls);
assert(_result == ETIMEDOUT);
}
}
private:
static constexpr int INITIAL_RESULT = 42;
unsigned timeout_;
unsigned unlocked_after_;
pthread_cond_t cond_;
pthread_mutex_t lock_;
LockstepScheduler &ls_;
std::atomic<bool> is_done_{false};
std::atomic<int> result_ {INITIAL_RESULT};
std::shared_ptr<TestThread> thread_{};
unsigned _timeout;
unsigned _unlocked_after;
pthread_cond_t _cond;
pthread_mutex_t _lock;
LockstepScheduler &_ls;
std::atomic<bool> _is_done{false};
std::atomic<int> _result {INITIAL_RESULT};
std::shared_ptr<TestThread> _thread{};
};
int random_number(int min, int max)