Commit 913b8233 authored by Marian Triebe's avatar Marian Triebe Committed by Dominik Charousset

Add workaround for a bug in `compare_exchange_weak`

Instead of `compare_exchange_weak` we use `comare_exchange_strong`
on older compilers to prevent race conditions.
This bug is present in GCC <= 4.8.2 and Clang <= 3.4.0.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60272
https://llvm.org/bugs/show_bug.cgi?id=18899
parent 4781c75f
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_CAS_WEAK_HPP
#define CAF_DETAIL_CAS_WEAK_HPP
#include <atomic>
#include "caf/config.hpp"
namespace caf {
namespace detail {
template<class T>
bool cas_weak(std::atomic<T>* obj, T* expected, T desired) {
# if (defined(CAF_CLANG) && CAF_COMPILER_VERSION < 30401) \
|| (defined(CAF_GCC) && CAF_COMPILER_VERSION < 40803)
return std::atomic_compare_exchange_strong(obj, expected, desired);
# else
return std::atomic_compare_exchange_weak(obj, expected, desired);
# endif
}
} // namespace detail
} // namespace caf
#endif // CAF_DETAIL_CAS_WEAK_HPP
......@@ -26,6 +26,8 @@
#include "caf/fwd.hpp"
#include "caf/detail/cas_weak.hpp"
namespace caf {
namespace detail {
......@@ -117,7 +119,7 @@ class singletons {
if (p == nullptr) {
return;
}
if (ptr.compare_exchange_weak(p, nullptr)) {
if (cas_weak<T*>(&ptr, &p, nullptr)) {
p->dispose();
return;
}
......
......@@ -21,8 +21,11 @@
#include <limits>
#include <thread>
#include "caf/detail/shared_spinlock.hpp"
#include "caf/detail/cas_weak.hpp"
namespace {
inline long min_long() {
......@@ -42,9 +45,8 @@ void shared_spinlock::lock() {
long v = m_flag.load();
for (;;) {
if (v != 0) {
// std::this_thread::yield();
v = m_flag.load();
} else if (m_flag.compare_exchange_weak(v, min_long())) {
} else if (cas_weak(&m_flag, &v, min_long())) {
return;
}
// else: next iteration
......@@ -75,7 +77,7 @@ void shared_spinlock::unlock() {
bool shared_spinlock::try_lock() {
long v = m_flag.load();
return (v == 0) ? m_flag.compare_exchange_weak(v, min_long()) : false;
return (v == 0) ? cas_weak(&m_flag, &v, min_long()) : false;
}
void shared_spinlock::lock_shared() {
......@@ -84,7 +86,7 @@ void shared_spinlock::lock_shared() {
if (v < 0) {
// std::this_thread::yield();
v = m_flag.load();
} else if (m_flag.compare_exchange_weak(v, v + 1)) {
} else if (cas_weak(&m_flag, &v, v + 1)) {
return;
}
// else: next iteration
......@@ -97,7 +99,7 @@ void shared_spinlock::unlock_shared() {
bool shared_spinlock::try_lock_shared() {
long v = m_flag.load();
return (v >= 0) ? m_flag.compare_exchange_weak(v, v + 1) : false;
return (v >= 0) ? cas_weak(&m_flag, &v, v + 1) : false;
}
} // namespace detail
......
......@@ -21,7 +21,7 @@ void inc_actor_instances() {
long v1 = ++s_actor_instances;
long v2 = s_max_actor_instances.load();
while (v1 > v2) {
s_max_actor_instances.compare_exchange_weak(v2, v1);
s_max_actor_instances.compare_exchange_strong(v2, v1);
}
}
......
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