From 54a951b6c67922b108488465bc062eda42877fd7 Mon Sep 17 00:00:00 2001 From: Joel Low Date: Sat, 5 Nov 2016 22:11:55 +0800 Subject: Implement barriers for Threaded Fork This commit introduces a concept of a barrier, where all threads must synchronise before continuing. Threaded Fork uses this to ensure that all input is consumed by each sink exactly once. Fixes #695. --- src/lib/utils/barrier.cpp | 35 +++++++++++++++++++++++++++++++++++ src/lib/utils/barrier.h | 41 +++++++++++++++++++++++++++++++++++++++++ src/lib/utils/info.txt | 1 + 3 files changed, 77 insertions(+) create mode 100644 src/lib/utils/barrier.cpp create mode 100644 src/lib/utils/barrier.h (limited to 'src/lib/utils') diff --git a/src/lib/utils/barrier.cpp b/src/lib/utils/barrier.cpp new file mode 100644 index 000000000..eb2ab978c --- /dev/null +++ b/src/lib/utils/barrier.cpp @@ -0,0 +1,35 @@ +/* +* Barrier +* (C) 2016 Joel Low +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include + +#if defined(BOTAN_TARGET_OS_HAS_THREADS) + +namespace Botan { + +void Barrier::wait(unsigned delta) + { + lock_guard_type lock(m_mutex); + m_value += delta; + } + +void Barrier::sync() + { + std::unique_lock lock(m_mutex); + --m_value; + if(m_value > 0) + m_cond.wait(lock, [this] { return m_value <= 0; }); + else + { + m_value = 0; + m_cond.notify_all(); + } + } + +} + +#endif diff --git a/src/lib/utils/barrier.h b/src/lib/utils/barrier.h new file mode 100644 index 000000000..96b9c0c7b --- /dev/null +++ b/src/lib/utils/barrier.h @@ -0,0 +1,41 @@ +/* +* Barrier +* (C) 2016 Joel Low +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_UTIL_BARRIER_H__ +#define BOTAN_UTIL_BARRIER_H__ + +#include + +#if defined(BOTAN_TARGET_OS_HAS_THREADS) +#include +#endif + +namespace Botan { + +#if defined(BOTAN_TARGET_OS_HAS_THREADS) +// Barrier implements a barrier synchronization primitive. wait() will indicate +// how many threads to synchronize; each thread needing synchronization should +// call sync(). When sync() returns, the barrier is reset to zero. +class Barrier + { + public: + explicit Barrier(int value = 0) : m_value(value) {} + + void wait(unsigned delta); + + void sync(); + + private: + int m_value; + mutex_type m_mutex; + std::condition_variable m_cond; + }; +#endif + +} + +#endif diff --git a/src/lib/utils/info.txt b/src/lib/utils/info.txt index 189b2da1f..75a428a83 100644 --- a/src/lib/utils/info.txt +++ b/src/lib/utils/info.txt @@ -22,6 +22,7 @@ version.h +barrier.h bit_ops.h ct_utils.h donna128.h -- cgit v1.2.3