1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_SPIN_LOCK_H 6#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_SPIN_LOCK_H 7 8#include <atomic> 9#include <memory> 10#include <mutex> 11 12#include "third_party/base/base_export.h" 13#include "third_party/base/compiler_specific.h" 14 15// Spinlock is a simple spinlock class based on the standard CPU primitive of 16// atomic increment and decrement of an int at a given memory address. These are 17// intended only for very short duration locks and assume a system with multiple 18// cores. For any potentially longer wait you should use a real lock, such as 19// |base::Lock|. 20// 21// |SpinLock|s MUST be globals. Using them as (e.g.) struct/class members will 22// result in an uninitialized lock, which is dangerously incorrect. 23 24namespace pdfium { 25namespace base { 26namespace subtle { 27 28class SpinLock { 29 public: 30 using Guard = std::lock_guard<SpinLock>; 31 32 ALWAYS_INLINE void lock() { 33 static_assert(sizeof(lock_) == sizeof(int), 34 "int and lock_ are different sizes"); 35 if (LIKELY(!lock_.exchange(true, std::memory_order_acquire))) 36 return; 37 LockSlow(); 38 } 39 40 ALWAYS_INLINE void unlock() { lock_.store(false, std::memory_order_release); } 41 42 private: 43 // This is called if the initial attempt to acquire the lock fails. It's 44 // slower, but has a much better scheduling and power consumption behavior. 45 BASE_EXPORT void LockSlow(); 46 47 std::atomic_int lock_; 48}; 49 50} // namespace subtle 51} // namespace base 52} // namespace pdfium 53 54#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SPIN_LOCK_H 55