-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathsynchronization.h
135 lines (101 loc) · 3.31 KB
/
synchronization.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_PLATFORM_SYNCHRONIZATION_H_
#define RUNTIME_PLATFORM_SYNCHRONIZATION_H_
#include "platform/allocation.h"
#include "platform/threads.h"
#if defined(DART_USE_ABSL)
#include "third_party/absl/synchronization/mutex.h"
#endif
namespace dart {
#if defined(DART_USE_ABSL)
using MutexImpl = absl::Mutex;
using ConditionVariableImpl = absl::CondVar;
#elif defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \
defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID)
using MutexImpl = pthread_mutex_t;
using ConditionVariableImpl = pthread_cond_t;
#elif defined(DART_HOST_OS_WINDOWS)
using MutexImpl = SRWLOCK;
using ConditionVariableImpl = CONDITION_VARIABLE;
#else
#error Unknown target os.
#endif
// Mark when we are running in a signal handler (Linux, Android) or with a
// suspended thread (Windows, Mac, Fuchia). During this time, we cannot take
// locks.
class DisallowMutexLockingScope : public ValueObject {
#if defined(DEBUG)
public:
DisallowMutexLockingScope() {
ASSERT(!is_active_);
is_active_ = true;
}
~DisallowMutexLockingScope() { is_active_ = false; }
static bool is_active() { return is_active_; }
private:
static inline thread_local bool is_active_ = false;
#endif // DEBUG
};
class Mutex {
public:
Mutex();
~Mutex();
bool IsOwnedByCurrentThread() const {
return owner_.IsOwnedByCurrentThread();
}
void Lock();
bool TryLock(); // Returns false if lock is busy and locking failed.
void Unlock();
private:
MutexImpl mutex_;
platform::ThreadBoundResource owner_;
friend class ConditionVariable;
DISALLOW_COPY_AND_ASSIGN(Mutex);
};
class ConditionVariable {
public:
enum WaitResult { kNotified, kTimedOut };
static constexpr int64_t kNoTimeout = 0;
ConditionVariable();
~ConditionVariable();
WaitResult Wait(Mutex* mutex, int64_t timeout_millis = kNoTimeout);
WaitResult WaitMicros(Mutex* mutex, int64_t timeout_micros = kNoTimeout);
void Notify();
void NotifyAll();
private:
ConditionVariableImpl cv_;
DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
};
class Monitor {
public:
using WaitResult = ConditionVariable::WaitResult;
static constexpr WaitResult kNotified = ConditionVariable::kNotified;
static constexpr WaitResult kTimedOut = ConditionVariable::kTimedOut;
static constexpr int64_t kNoTimeout = ConditionVariable::kNoTimeout;
Monitor() {}
~Monitor() {}
bool IsOwnedByCurrentThread() const {
return mutex_.IsOwnedByCurrentThread();
}
bool TryEnter() { return mutex_.TryLock(); }
void Enter() { return mutex_.Lock(); }
void Exit() { return mutex_.Unlock(); }
// Wait for notification or timeout.
WaitResult Wait(int64_t timeout_millis) {
return cv_.Wait(&mutex_, timeout_millis);
}
WaitResult WaitMicros(int64_t timeout_micros) {
return cv_.WaitMicros(&mutex_, timeout_micros);
}
// Notify waiting threads.
void Notify() { cv_.Notify(); }
void NotifyAll() { cv_.NotifyAll(); }
private:
Mutex mutex_; // OS-specific data.
ConditionVariable cv_;
DISALLOW_COPY_AND_ASSIGN(Monitor);
};
} // namespace dart
#endif // RUNTIME_PLATFORM_SYNCHRONIZATION_H_