Bug 1921551 - React to sync sign in flow correctly r=android-reviewers,matt-tighe
[gecko.git] / js / src / builtin / AtomicsObject.h
blob0f2e6c4af9ffa8dd83397a1a7e3b5524eaa0f594
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef builtin_AtomicsObject_h
8 #define builtin_AtomicsObject_h
10 #include "mozilla/Maybe.h"
11 #include "mozilla/TimeStamp.h"
13 #include "threading/ConditionVariable.h"
14 #include "threading/ProtectedData.h" // js::ThreadData
15 #include "vm/NativeObject.h"
17 namespace js {
19 class SharedArrayRawBuffer;
21 class AtomicsObject : public NativeObject {
22 public:
23 static const JSClass class_;
26 class FutexThread {
27 friend class AutoLockFutexAPI;
29 public:
30 [[nodiscard]] static bool initialize();
31 static void destroy();
33 static void lock();
34 static void unlock();
36 FutexThread();
37 [[nodiscard]] bool initInstance();
38 void destroyInstance();
40 // Parameters to notify().
41 enum NotifyReason {
42 NotifyExplicit, // Being asked to wake up by another thread
43 NotifyForJSInterrupt // Interrupt requested
46 // Result codes from wait() and atomics_wait_impl().
47 enum class WaitResult {
48 Error, // Error has been reported, just propagate error signal
49 NotEqual, // Did not wait because the values differed
50 OK, // Waited and was woken
51 TimedOut // Waited and timed out
54 // Block the calling thread and wait.
56 // The futex lock must be held around this call.
58 // The timeout is the number of milliseconds, with fractional
59 // times allowed; specify mozilla::Nothing() for an indefinite
60 // wait.
62 // wait() will not wake up spuriously.
63 [[nodiscard]] WaitResult wait(
64 JSContext* cx, js::UniqueLock<js::Mutex>& locked,
65 const mozilla::Maybe<mozilla::TimeDuration>& timeout);
67 // Notify the thread this is associated with.
69 // The futex lock must be held around this call. (The sleeping
70 // thread will not wake up until the caller of Atomics.notify()
71 // releases the lock.)
73 // If the thread is not waiting then this method does nothing.
75 // If the thread is waiting in a call to wait() and the
76 // reason is NotifyExplicit then the wait() call will return
77 // with Woken.
79 // If the thread is waiting in a call to wait() and the
80 // reason is NotifyForJSInterrupt then the wait() will return
81 // with WaitingNotifiedForInterrupt; in the latter case the caller
82 // of wait() must handle the interrupt.
83 void notify(NotifyReason reason);
85 bool isWaiting();
87 // If canWait() returns false (the default) then wait() is disabled
88 // on the thread to which the FutexThread belongs.
89 bool canWait() { return canWait_; }
91 void setCanWait(bool flag) { canWait_ = flag; }
93 private:
94 enum FutexState {
95 Idle, // We are not waiting or woken
96 Waiting, // We are waiting, nothing has happened yet
97 WaitingNotifiedForInterrupt, // We are waiting, but have been interrupted,
98 // and have not yet started running the
99 // interrupt handler
100 WaitingInterrupted, // We are waiting, but have been interrupted
101 // and are running the interrupt handler
102 Woken // Woken by a script call to Atomics.notify
105 // Condition variable that this runtime will wait on.
106 js::ConditionVariable* cond_;
108 // Current futex state for this runtime. When not in a wait this
109 // is Idle; when in a wait it is Waiting or the reason the futex
110 // is about to wake up.
111 FutexState state_;
113 // Shared futex lock for all runtimes. We can perhaps do better,
114 // but any lock will need to be per-domain (consider SharedWorker)
115 // or coarser.
116 static mozilla::Atomic<js::Mutex*, mozilla::SequentiallyConsistent> lock_;
118 // A flag that controls whether waiting is allowed.
119 ThreadData<bool> canWait_;
122 // Go to sleep if the int32_t value at the given address equals `value`.
123 [[nodiscard]] FutexThread::WaitResult atomics_wait_impl(
124 JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int32_t value,
125 const mozilla::Maybe<mozilla::TimeDuration>& timeout);
127 // Go to sleep if the int64_t value at the given address equals `value`.
128 [[nodiscard]] FutexThread::WaitResult atomics_wait_impl(
129 JSContext* cx, SharedArrayRawBuffer* sarb, size_t byteOffset, int64_t value,
130 const mozilla::Maybe<mozilla::TimeDuration>& timeout);
132 // Notify some waiters on the given address. If `count` is negative then notify
133 // all. The return value is nonnegative and is the number of waiters woken. If
134 // the number of waiters woken exceeds INT64_MAX then this never returns. If
135 // `count` is nonnegative then the return value is never greater than `count`.
136 [[nodiscard]] int64_t atomics_notify_impl(SharedArrayRawBuffer* sarb,
137 size_t byteOffset, int64_t count);
139 } /* namespace js */
141 #endif /* builtin_AtomicsObject_h */