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 24 namespace pdfium { 25 namespace base { 26 namespace subtle { 27 28 class SpinLock { 29 public: 30 using Guard = std::lock_guard<SpinLock>; 31 lock()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 unlock()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