| // Copyright 2019 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef BASE_TASK_COMMON_SCOPED_DEFER_TASK_POSTING_H_ | 
 | #define BASE_TASK_COMMON_SCOPED_DEFER_TASK_POSTING_H_ | 
 |  | 
 | #include <vector> | 
 |  | 
 | #include "base/base_export.h" | 
 | #include "base/location.h" | 
 | #include "base/task/sequenced_task_runner.h" | 
 | #include "base/time/time.h" | 
 |  | 
 | namespace base { | 
 |  | 
 | // Tracing wants to post tasks from within a trace event within PostTask, but | 
 | // this can lead to a deadlock. Create a scope to ensure that we are posting | 
 | // the tasks in question outside of the scope of the lock. | 
 | // NOTE: This scope affects only the thread it is created on. All other threads | 
 | // still can post tasks. | 
 | // | 
 | // TODO(altimin): It should be possible to get rid of this scope, but this | 
 | // requires refactoring TimeDomain to ensure that TimeDomain never changes and | 
 | // we can read current time without grabbing a lock. | 
 | class BASE_EXPORT [[maybe_unused, nodiscard]] ScopedDeferTaskPosting { | 
 |  public: | 
 |   static void PostOrDefer(scoped_refptr<SequencedTaskRunner> task_runner, | 
 |                           const Location& from_here, | 
 |                           OnceClosure task, | 
 |                           base::TimeDelta delay); | 
 |  | 
 |   static bool IsPresent(); | 
 |  | 
 |   ScopedDeferTaskPosting(); | 
 |  | 
 |   ScopedDeferTaskPosting(const ScopedDeferTaskPosting&) = delete; | 
 |   ScopedDeferTaskPosting& operator=(const ScopedDeferTaskPosting&) = delete; | 
 |  | 
 |   ~ScopedDeferTaskPosting(); | 
 |  | 
 |  private: | 
 |   static ScopedDeferTaskPosting* Get(); | 
 |   // Returns whether the |scope| was set as active, which happens only | 
 |   // when the scope wasn't set before. | 
 |   static bool Set(ScopedDeferTaskPosting* scope); | 
 |  | 
 |   void DeferTaskPosting(scoped_refptr<SequencedTaskRunner> task_runner, | 
 |                         const Location& from_here, | 
 |                         OnceClosure task, | 
 |                         base::TimeDelta delay); | 
 |  | 
 |   struct DeferredTask { | 
 |     DeferredTask(scoped_refptr<SequencedTaskRunner> task_runner, | 
 |                  Location from_here, | 
 |                  OnceClosure task, | 
 |                  base::TimeDelta delay); | 
 |  | 
 |     DeferredTask(const DeferredTask&) = delete; | 
 |     DeferredTask& operator=(const DeferredTask&) = delete; | 
 |  | 
 |     DeferredTask(DeferredTask&& task); | 
 |  | 
 |     ~DeferredTask(); | 
 |  | 
 |     scoped_refptr<SequencedTaskRunner> task_runner; | 
 |     Location from_here; | 
 |     OnceClosure task; | 
 |     base::TimeDelta delay; | 
 |   }; | 
 |  | 
 |   std::vector<DeferredTask> deferred_tasks_; | 
 |  | 
 |   // Scopes can be nested (e.g. ScheduleWork inside PostTasks can post a task | 
 |   // to another task runner), so we want to know whether the scope is top-level | 
 |   // or not. | 
 |   bool top_level_scope_ = false; | 
 | }; | 
 |  | 
 | }  // namespace base | 
 |  | 
 | #endif  // BASE_TASK_COMMON_SCOPED_DEFER_TASK_POSTING_H_ |