summaryrefslogtreecommitdiff
path: root/chromium/base/task/sequence_manager/tasks.h
blob: b043ceec40bb37da5eb7ca0364e55cd71bd922a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2018 The Chromium 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 BASE_TASK_SEQUENCE_MANAGER_TASKS_H_
#define BASE_TASK_SEQUENCE_MANAGER_TASKS_H_

#include "base/pending_task.h"
#include "base/sequenced_task_runner.h"
#include "base/task/sequence_manager/enqueue_order.h"

namespace base {
namespace sequence_manager {

using TaskType = uint8_t;
constexpr TaskType kTaskTypeNone = 0;

namespace internal {

enum class WakeUpResolution { kLow, kHigh };

// Wrapper around PostTask method arguments and the assigned task type.
// Eventually it becomes a PendingTask once accepted by a TaskQueueImpl.
struct BASE_EXPORT PostedTask {
  explicit PostedTask(scoped_refptr<SequencedTaskRunner> task_runner,
                      OnceClosure callback = OnceClosure(),
                      Location location = Location(),
                      TimeDelta delay = TimeDelta(),
                      Nestable nestable = Nestable::kNestable,
                      TaskType task_type = kTaskTypeNone);
  PostedTask(PostedTask&& move_from) noexcept;
  PostedTask(const PostedTask&) = delete;
  PostedTask& operator=(const PostedTask&) = delete;
  ~PostedTask();

  OnceClosure callback;
  Location location;
  TimeDelta delay;
  Nestable nestable;
  TaskType task_type;
  // The task runner this task is running on. Can be used by task runners that
  // support posting back to the "current sequence".
  scoped_refptr<SequencedTaskRunner> task_runner;
  // The time at which the task was queued.
  TimeTicks queue_time;
};

// Represents a time at which a task wants to run. Tasks scheduled for the
// same point in time will be ordered by their sequence numbers.
struct DelayedWakeUp {
  TimeTicks time;
  int sequence_num;
  WakeUpResolution resolution;

  bool operator!=(const DelayedWakeUp& other) const {
    return time != other.time || other.sequence_num != sequence_num ||
           resolution != other.resolution;
  }

  bool operator==(const DelayedWakeUp& other) const {
    return !(*this != other);
  }

  bool operator<=(const DelayedWakeUp& other) const {
    if (time == other.time) {
      if (sequence_num == other.sequence_num) {
        if (resolution == other.resolution) {
          // Debug gcc builds can compare an element against itself.
          DCHECK_EQ(this, &other);
          return true;
        }

        return resolution < other.resolution;
      }

      // |sequence_num| is int and might wrap around to a negative number when
      // casted from EnqueueOrder. This way of comparison handles that properly.
      return (sequence_num - other.sequence_num) < 0;
    }
    return time < other.time;
  }
};

}  // namespace internal

// PendingTask with extra metadata for SequenceManager.
struct BASE_EXPORT Task : public PendingTask {
  Task(internal::PostedTask posted_task,
       TimeTicks delayed_run_time,
       EnqueueOrder sequence_order,
       EnqueueOrder enqueue_order = EnqueueOrder(),
       internal::WakeUpResolution wake_up_resolution =
           internal::WakeUpResolution::kLow);
  Task(Task&& move_from);
  ~Task();
  Task& operator=(Task&& other);

  // SequenceManager is particularly sensitive to enqueue order,
  // so we have accessors for safety.
  EnqueueOrder enqueue_order() const {
    DCHECK(enqueue_order_);
    return enqueue_order_;
  }

  void set_enqueue_order(EnqueueOrder enqueue_order) {
    DCHECK(!enqueue_order_);
    enqueue_order_ = enqueue_order;
  }

  bool enqueue_order_set() const { return enqueue_order_; }

  TaskType task_type;

  // The task runner this task is running on. Can be used by task runners that
  // support posting back to the "current sequence".
  scoped_refptr<SequencedTaskRunner> task_runner;

#if DCHECK_IS_ON()
  bool cross_thread_;
#endif

 private:
  // Similar to |sequence_num|, but ultimately the |enqueue_order| is what
  // the scheduler uses for task ordering. For immediate tasks |enqueue_order|
  // is set when posted, but for delayed tasks it's not defined until they are
  // enqueued. This is because otherwise delayed tasks could run before
  // an immediate task posted after the delayed task.
  EnqueueOrder enqueue_order_;
};

}  // namespace sequence_manager
}  // namespace base

#endif  // BASE_TASK_SEQUENCE_MANAGER_TASKS_H_