58604b012aa386bbeca2ce7341751fa932c402a9
[WebKit-https.git] / Source / WTF / wtf / SpinLock.h
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef SpinLock_h
27 #define SpinLock_h
28
29 #include <thread>
30 #include <wtf/Atomics.h>
31 #include <wtf/Locker.h>
32
33 namespace WTF {
34
35 // SpinLock is a very simple lock implementation that has extremely fast lock/unlock for very small
36 // uncontended critical sections. However, it will exhibit bad performance degradation when the lock
37 // becomes contended: the thread trying to acquire the lock will simply waste CPU cycles.
38 //
39 // For most (all?) locking use cases, it's better to use Lock (see wtf/Lock.h). That uses only a bit
40 // more memory (8 bytes instead of 4 on 64-bit), and is only a bit slower in the uncontended case
41 // (Lock needs CAS to unlock, while SpinLock doesn't), but will burn a lot less CPU time - for 10
42 // threads acquiring a 50 microsecond critical section, Lock will use up to 100x less kernel CPU time
43 // than SpinLock.
44
45 // SpinLockBase is a struct without an explicitly defined constructors so that
46 // it can be initialized at compile time. See StaticSpinLock below.
47 struct SpinLockBase {
48
49     void lock()
50     {
51         while (!m_lock.compareExchangeWeak(0, 1, std::memory_order_acquire))
52             std::this_thread::yield();
53     }
54
55     void unlock()
56     {
57         m_lock.store(0, std::memory_order_release);
58     }
59
60     bool isLocked() const
61     {
62         return m_lock.load(std::memory_order_acquire);
63     }
64     
65     Atomic<unsigned> m_lock;
66 };
67
68 // SpinLock is for use as instance variables in structs and classes, not as
69 // statics and globals.
70 struct SpinLock : public SpinLockBase {
71     SpinLock()
72     {
73         m_lock.store(0, std::memory_order_relaxed);
74     }
75 };
76
77 // StaticSpinLock is for use as statics and globals, not as instance variables.
78 typedef SpinLockBase StaticSpinLock;
79 typedef Locker<SpinLockBase> SpinLockHolder;
80
81 } // namespace WTF
82
83 using WTF::StaticSpinLock;
84 using WTF::SpinLock;
85 using WTF::SpinLockHolder;
86
87 #endif // SpinLock_h