blob: b64a6caf99cd503b090949d83d69125bb10ace6f [file] [log] [blame]
/**
* Copyright 2011-2015 Quickstep Technologies LLC.
* Copyright 2015 Pivotal Software, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
#ifndef QUICKSTEP_THREADING_SPIN_MUTEX_HPP_
#define QUICKSTEP_THREADING_SPIN_MUTEX_HPP_
#include <atomic>
#include "threading/Mutex.hpp"
#include "utility/Macros.hpp"
namespace quickstep {
/** \addtogroup Threading
* @{
*/
/**
* @brief Mutex implementation as a pure user-space spinlock. May be more
* efficient than an ordinary Mutex if locks are usually held briefly.
*
* @note Unlike a regular Mutex, SpinMutex can not create condition variables.
* @note In some cases, SpinMutex will perform better if it is aligned on its
* own cache line to avoid false sharing.
**/
class SpinMutex {
public:
SpinMutex() : locked_(false) {
}
/**
* @note This call does NOT yield when contended. SpinMutex is intended
* mainly for cases where locks are held briefly and it is better to
* simply spin for a short time rather than involving the kernel's
* scheduler. Otherwise, a regular Mutex (using the futex mechanism on
* Linux) is a more appropriate choice.
**/
inline void lock() {
bool previous_locked = false;
while (!locked_.compare_exchange_weak(previous_locked,
true,
std::memory_order_acquire,
std::memory_order_relaxed)) {
previous_locked = false;
}
}
inline void unlock() {
locked_.store(false, std::memory_order_release);
}
private:
std::atomic<bool> locked_;
DISALLOW_COPY_AND_ASSIGN(SpinMutex);
};
typedef MutexLockImpl<SpinMutex, true> SpinMutexLock;
template <bool actually_lock> using StaticConditionalSpinMutexLock
= MutexLockImpl<SpinMutex, actually_lock>;
typedef DynamicConditionalMutexLockImpl<SpinMutex> DynamicConditionalSpinMutexLock;
/** @} */
} // namespace quickstep
#endif // QUICKSTEP_THREADING_SPIN_MUTEX_HPP_