blob: 680d94b24ef517d2a0e4bd886ebbced9893b68c5 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the llvm::sys::Mutex class.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_MUTEX_H
15#define LLVM_SUPPORT_MUTEX_H
16
Andrew Scullcdfcccc2018-10-05 20:58:37 +010017#include "llvm/Config/llvm-config.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010018#include "llvm/Support/Compiler.h"
19#include "llvm/Support/Threading.h"
20#include <cassert>
21
22namespace llvm
23{
24 namespace sys
25 {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010026 /// Platform agnostic Mutex class.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010027 class MutexImpl
28 {
29 /// @name Constructors
30 /// @{
31 public:
32
33 /// Initializes the lock but doesn't acquire it. if \p recursive is set
34 /// to false, the lock will not be recursive which makes it cheaper but
35 /// also more likely to deadlock (same thread can't acquire more than
36 /// once).
Andrew Scullcdfcccc2018-10-05 20:58:37 +010037 /// Default Constructor.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010038 explicit MutexImpl(bool recursive = true);
39
40 /// Releases and removes the lock
Andrew Scullcdfcccc2018-10-05 20:58:37 +010041 /// Destructor
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010042 ~MutexImpl();
43
44 /// @}
45 /// @name Methods
46 /// @{
47 public:
48
49 /// Attempts to unconditionally acquire the lock. If the lock is held by
50 /// another thread, this method will wait until it can acquire the lock.
51 /// @returns false if any kind of error occurs, true otherwise.
Andrew Scullcdfcccc2018-10-05 20:58:37 +010052 /// Unconditionally acquire the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010053 bool acquire();
54
55 /// Attempts to release the lock. If the lock is held by the current
56 /// thread, the lock is released allowing other threads to acquire the
57 /// lock.
58 /// @returns false if any kind of error occurs, true otherwise.
Andrew Scullcdfcccc2018-10-05 20:58:37 +010059 /// Unconditionally release the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010060 bool release();
61
62 /// Attempts to acquire the lock without blocking. If the lock is not
63 /// available, this function returns false quickly (without blocking). If
64 /// the lock is available, it is acquired.
65 /// @returns false if any kind of error occurs or the lock is not
66 /// available, true otherwise.
Andrew Scullcdfcccc2018-10-05 20:58:37 +010067 /// Try to acquire the lock.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010068 bool tryacquire();
69
70 //@}
71 /// @name Platform Dependent Data
72 /// @{
73 private:
74#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
75 void* data_; ///< We don't know what the data will be
76#endif
77
78 /// @}
79 /// @name Do Not Implement
80 /// @{
81 private:
82 MutexImpl(const MutexImpl &) = delete;
83 void operator=(const MutexImpl &) = delete;
84 /// @}
85 };
86
87
88 /// SmartMutex - A mutex with a compile time constant parameter that
89 /// indicates whether this mutex should become a no-op when we're not
90 /// running in multithreaded mode.
91 template<bool mt_only>
92 class SmartMutex {
93 MutexImpl impl;
94 unsigned acquired;
95 bool recursive;
96 public:
97 explicit SmartMutex(bool rec = true) :
98 impl(rec), acquired(0), recursive(rec) { }
99
100 bool lock() {
101 if (!mt_only || llvm_is_multithreaded()) {
102 return impl.acquire();
103 } else {
104 // Single-threaded debugging code. This would be racy in
105 // multithreaded mode, but provides not sanity checks in single
106 // threaded mode.
107 assert((recursive || acquired == 0) && "Lock already acquired!!");
108 ++acquired;
109 return true;
110 }
111 }
112
113 bool unlock() {
114 if (!mt_only || llvm_is_multithreaded()) {
115 return impl.release();
116 } else {
117 // Single-threaded debugging code. This would be racy in
118 // multithreaded mode, but provides not sanity checks in single
119 // threaded mode.
120 assert(((recursive && acquired) || (acquired == 1)) &&
121 "Lock not acquired before release!");
122 --acquired;
123 return true;
124 }
125 }
126
127 bool try_lock() {
128 if (!mt_only || llvm_is_multithreaded())
129 return impl.tryacquire();
130 else return true;
131 }
132
133 private:
134 SmartMutex(const SmartMutex<mt_only> & original);
135 void operator=(const SmartMutex<mt_only> &);
136 };
137
138 /// Mutex - A standard, always enforced mutex.
139 typedef SmartMutex<false> Mutex;
140
141 template<bool mt_only>
142 class SmartScopedLock {
143 SmartMutex<mt_only>& mtx;
144
145 public:
146 SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
147 mtx.lock();
148 }
149
150 ~SmartScopedLock() {
151 mtx.unlock();
152 }
153 };
154
155 typedef SmartScopedLock<false> ScopedLock;
156 }
157}
158
159#endif