Added support for 'synchronized_wait'. Review: https://reviews.apache.org/r/36629
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/b062eb05 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/b062eb05 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/b062eb05 Branch: refs/heads/master Commit: b062eb05cf55f88a217bf8d9a5654df316931a47 Parents: ab68f9d Author: Michael Park <[email protected]> Authored: Fri Jul 24 14:34:31 2015 -0700 Committer: Benjamin Hindman <[email protected]> Committed: Fri Jul 24 15:29:04 2015 -0700 ---------------------------------------------------------------------- .../stout/include/stout/synchronized.hpp | 80 ++++++++++++++++++++ 1 file changed, 80 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/b062eb05/3rdparty/libprocess/3rdparty/stout/include/stout/synchronized.hpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/synchronized.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/synchronized.hpp index e40ec55..855ba1d 100644 --- a/3rdparty/libprocess/3rdparty/stout/include/stout/synchronized.hpp +++ b/3rdparty/libprocess/3rdparty/stout/include/stout/synchronized.hpp @@ -16,6 +16,7 @@ #define __STOUT_SYNCHRONIZED_HPP__ #include <atomic> +#include <condition_variable> #include <mutex> #include <type_traits> @@ -158,4 +159,83 @@ T* synchronized_get_pointer(T* t) goto SYNCHRONIZED_LABEL; \ } else SYNCHRONIZED_LABEL: + +/** + * Waits on the condition variable associated with 'lock' which has + * already been synchronized. Currently, the only supported + * implementation is for 'std::condition_variable' associated with a + * 'std::mutex'. + * + * @param cv The condition variable. + * @param lock The lock associated with the condition variable. + * + * @pre 'lock' is already owned by the calling thread. + * @post 'lock' is still owned by the calling thread. + * + * @return Nothing. + */ +template <typename CV, typename Lock> +void synchronized_wait(CV* cv, Lock* lock); + + +/** + * Waits on the 'std::condition_variable' associated with 'std::mutex' + * which has already been synchronized. We provide this specialization + * since 'std::condition_variable::wait' only works with + * 'std::unique_lock<std::mutex>'. + * + * @example + * std::condition_variable cv; + * std::mutex m; + * synchronized (m) { // lock 'm'. + * // ... + * synchronized_wait(cv, m); // unlock/lock 'm'. + * // ... + * } // unlock 'm'. + * + * @param cv The 'std::condition_variable'. + * @param mutex The 'std::mutex' associated with the + * 'std::condition_variable'. + * + * @pre 'mutex' is already owned by the calling thread. + * @post 'mutex' is still owned by the calling thread. + * + * @return Nothing. + */ +template <> +inline void synchronized_wait(std::condition_variable* cv, std::mutex* mutex) +{ + CHECK_NOTNULL(cv); + CHECK_NOTNULL(mutex); + + // Since the pre-condition is that 'mutex' is already owned by the + // calling thread, we use 'std::adopt_lock' to adopt the mutex + // rather than trying to lock it ourselves. + std::unique_lock<std::mutex> lock(*mutex, std::adopt_lock); + + // On entrance, 'std::condition_variable::wait' releases 'mutex'. + // On exit, 'std::condition_variable::wait' re-acquires 'mutex'. + cv->wait(lock); + + // At this point, the 'mutex' has been acquired. Since the + // post-condition is that 'mutex' is still owned by the calling + // thread, we use 'release' in order to prevent 'std::unique_lock' + // from unlocking the 'mutex'. + lock.release(); +} + + +/** + * There is a known bug around 'std::condition_variable_any' in + * 'libstdc++' distributed 'devtoolset-2', and also general issues + * around the use of 'std::condition_variable_any' with + * 'std::recursive_mutex'. Hence, this function is currently deleted + * until both issues are resolved. + * + * @see https://rhn.redhat.com/errata/RHBA-2014-1035.html + * @see http://stackoverflow.com/questions/11752155/behavior-of-condition-variable-any-when-used-with-a-recursive-mutex + */ +template <typename Lock> +void synchronized_wait(std::condition_variable_any* cv, Lock* lock) = delete; + #endif // __STOUT_SYNCHRONIZED_HPP__
