a8c5ee6b02a672a3e7b448d7ef2a9a4a4ff1fc31
[WebKit-https.git] / Source / bmalloc / bmalloc / Mutex.h
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #pragma once
28
29 #include "BAssert.h"
30 #include <atomic>
31 #include <mutex>
32 #include <thread>
33
34 // A fast replacement for std::mutex.
35
36 namespace bmalloc {
37
38 class Mutex {
39 public:
40     Mutex() = default;
41
42     void lock();
43     bool try_lock();
44     void unlock();
45
46 private:
47     BEXPORT void lockSlowCase();
48
49     std::atomic<bool> m_flag { false };
50     std::atomic<bool> m_isSpinning { false };
51 };
52
53 static inline void sleep(
54     std::unique_lock<Mutex>& lock, std::chrono::milliseconds duration)
55 {
56     if (duration == std::chrono::milliseconds(0))
57         return;
58     
59     lock.unlock();
60     std::this_thread::sleep_for(duration);
61     lock.lock();
62 }
63
64 static inline void waitUntilFalse(
65     std::unique_lock<Mutex>& lock, std::chrono::milliseconds sleepDuration,
66     bool& condition)
67 {
68     while (condition) {
69         condition = false;
70         sleep(lock, sleepDuration);
71     }
72 }
73
74 inline bool Mutex::try_lock()
75 {
76     return !m_flag.exchange(true, std::memory_order_acquire);
77 }
78
79 inline void Mutex::lock()
80 {
81     if (!try_lock())
82         lockSlowCase();
83 }
84
85 inline void Mutex::unlock()
86 {
87     m_flag.store(false, std::memory_order_release);
88 }
89
90 } // namespace bmalloc