83 lines
2.7 KiB
C++
83 lines
2.7 KiB
C++
// 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_
|