%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/tasks/ |
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/tasks/operations-barrier.h |
// Copyright 2020 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_TASKS_OPERATIONS_BARRIER_H_ #define V8_TASKS_OPERATIONS_BARRIER_H_ #include <cstdint> #include "src/base/macros.h" #include "src/base/platform/condition-variable.h" #include "src/base/platform/mutex.h" namespace v8 { namespace internal { // A thread-safe barrier to manage lifetime of muti-threaded operations. // // The barrier is used to determine if operations are allowed, and to keep track // of how many are currently active. Users will call TryLock() before starting // such operations. If the call succeeds the user can run the operation and the // barrier will keep track of it until the user signals that the operation is // completed. No operations are allowed after CancelAndWait() is called. // // There is no explicit way of telling the barrier when an operation is // completed, instead for convenience TryLock() will return a RAII // like object that will do so on destruction. // // For example: // // OperationsBarrier barrier_; // // void TearDown() { // barrier_.CancelAndWait(); // } // // void MaybeRunOperation() { // if (token = barrier_.TryLock()) Process(); // } // class V8_EXPORT_PRIVATE OperationsBarrier { public: // The owner of a Token which evaluates to true can safely perform an // operation while being certain it happens-before CancelAndWait(). Releasing // this Token relinquishes this right. // // This class is thread-safe. class Token { public: Token() = default; ~Token() { if (outer_) outer_->Release(); } Token(const Token&) = delete; Token(Token&& other) V8_NOEXCEPT : outer_(other.outer_) { other.outer_ = nullptr; } Token& operator=(const Token&) = delete; Token& operator=(Token&& other) V8_NOEXCEPT { DCHECK_NE(this, &other); if (outer_) outer_->Release(); outer_ = other.outer_; other.outer_ = nullptr; return *this; } operator bool() const { return !!outer_; } private: friend class OperationsBarrier; explicit Token(OperationsBarrier* outer) : outer_(outer) { DCHECK_NOT_NULL(outer_); } OperationsBarrier* outer_ = nullptr; }; OperationsBarrier() = default; // Users must call CancelAndWait() before destroying an instance of this // class. ~OperationsBarrier() { DCHECK(cancelled_); } OperationsBarrier(const OperationsBarrier&) = delete; OperationsBarrier& operator=(const OperationsBarrier&) = delete; // Returns a RAII like object that implicitly converts to true if operations // are allowed i.e. if this call happens-before CancelAndWait(), otherwise the // object will convert to false. On successful return, this OperationsBarrier // will keep track of the operation until the returned object goes out of // scope. Token TryLock(); // Prevents further calls to TryLock() from succeeding and waits for // all the ongoing operations to complete. // // Attention: Can only be called once. void CancelAndWait(); bool cancelled() const { return cancelled_; } private: void Release(); // Mutex and condition variable enabling concurrent register and removing, as // well as waiting for background tasks on {CancelAndWait}. base::Mutex mutex_; base::ConditionVariable release_condition_; bool cancelled_ = false; size_t operations_count_{0}; }; } // namespace internal } // namespace v8 #endif // V8_TASKS_OPERATIONS_BARRIER_H_