1 // Copyright 2019 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TASK_COMMON_SCOPED_DEFER_TASK_POSTING_H_ 6 #define BASE_TASK_COMMON_SCOPED_DEFER_TASK_POSTING_H_ 7 8 #include <vector> 9 10 #include "base/base_export.h" 11 #include "base/location.h" 12 #include "base/task/sequenced_task_runner.h" 13 #include "base/time/time.h" 14 15 namespace base { 16 17 // Tracing wants to post tasks from within a trace event within PostTask, but 18 // this can lead to a deadlock. Create a scope to ensure that we are posting 19 // the tasks in question outside of the scope of the lock. 20 // NOTE: This scope affects only the thread it is created on. All other threads 21 // still can post tasks. 22 // 23 // TODO(altimin): It should be possible to get rid of this scope, but this 24 // requires refactoring TimeDomain to ensure that TimeDomain never changes and 25 // we can read current time without grabbing a lock. 26 class BASE_EXPORT [[maybe_unused, nodiscard]] ScopedDeferTaskPosting { 27 public: 28 static void PostOrDefer(scoped_refptr<SequencedTaskRunner> task_runner, 29 const Location& from_here, 30 OnceClosure task, 31 base::TimeDelta delay); 32 33 static bool IsPresent(); 34 35 ScopedDeferTaskPosting(); 36 37 ScopedDeferTaskPosting(const ScopedDeferTaskPosting&) = delete; 38 ScopedDeferTaskPosting& operator=(const ScopedDeferTaskPosting&) = delete; 39 40 ~ScopedDeferTaskPosting(); 41 42 private: 43 static ScopedDeferTaskPosting* Get(); 44 // Returns whether the |scope| was set as active, which happens only 45 // when the scope wasn't set before. 46 static bool Set(ScopedDeferTaskPosting* scope); 47 48 void DeferTaskPosting(scoped_refptr<SequencedTaskRunner> task_runner, 49 const Location& from_here, 50 OnceClosure task, 51 base::TimeDelta delay); 52 53 struct DeferredTask { 54 DeferredTask(scoped_refptr<SequencedTaskRunner> task_runner, 55 Location from_here, 56 OnceClosure task, 57 base::TimeDelta delay); 58 59 DeferredTask(const DeferredTask&) = delete; 60 DeferredTask& operator=(const DeferredTask&) = delete; 61 62 DeferredTask(DeferredTask&& task); 63 64 ~DeferredTask(); 65 66 scoped_refptr<SequencedTaskRunner> task_runner; 67 Location from_here; 68 OnceClosure task; 69 base::TimeDelta delay; 70 }; 71 72 std::vector<DeferredTask> deferred_tasks_; 73 74 // Scopes can be nested (e.g. ScheduleWork inside PostTasks can post a task 75 // to another task runner), so we want to know whether the scope is top-level 76 // or not. 77 bool top_level_scope_ = false; 78 }; 79 80 } // namespace base 81 82 #endif // BASE_TASK_COMMON_SCOPED_DEFER_TASK_POSTING_H_ 83