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

base / task / sequence_manager / thread_controller_impl.h [blame]

// Copyright 2017 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_SEQUENCE_MANAGER_THREAD_CONTROLLER_IMPL_H_
#define BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_IMPL_H_

#include <memory>

#include "base/base_export.h"
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
#include "base/dcheck_is_on.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/sequence_checker.h"
#include "base/task/common/task_annotator.h"
#include "base/task/sequence_manager/thread_controller.h"
#include "base/task/sequence_manager/work_deduplicator.h"
#include "base/task/single_thread_task_runner.h"
#include "build/build_config.h"

namespace base {
namespace sequence_manager {
namespace internal {
class SequenceManagerImpl;

// This is the interface between a SequenceManager which sits on top of an
// underlying SequenceManagerImpl or SingleThreadTaskRunner. Currently it's only
// used for workers in blink although we'd intend to migrate those to
// ThreadControllerWithMessagePumpImpl (https://crbug.com/948051). Long term we
// intend to use this for sequence funneling.
class BASE_EXPORT ThreadControllerImpl : public ThreadController,
                                         public RunLoop::NestingObserver {
 public:
  ThreadControllerImpl(const ThreadControllerImpl&) = delete;
  ThreadControllerImpl& operator=(const ThreadControllerImpl&) = delete;
  ~ThreadControllerImpl() override;

  // TODO(crbug.com/40620995): replace |funneled_sequence_manager| with
  // |funneled_task_runner| when we sort out the workers
  static std::unique_ptr<ThreadControllerImpl> Create(
      SequenceManagerImpl* funneled_sequence_manager,
      const TickClock* time_source);

  // ThreadController:
  void SetWorkBatchSize(int work_batch_size) override;
  void WillQueueTask(PendingTask* pending_task) override;
  void ScheduleWork() override;
  void BindToCurrentThread(std::unique_ptr<MessagePump> message_pump) override;
  void SetNextDelayedDoWork(LazyNow* lazy_now,
                            std::optional<WakeUp> wake_up) override;
  void SetSequencedTaskSource(SequencedTaskSource* sequence) override;
  bool RunsTasksInCurrentSequence() override;
  void SetDefaultTaskRunner(scoped_refptr<SingleThreadTaskRunner>) override;
  scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override;
  void RestoreDefaultTaskRunner() override;
  void AddNestingObserver(RunLoop::NestingObserver* observer) override;
  void RemoveNestingObserver(RunLoop::NestingObserver* observer) override;
  void SetTaskExecutionAllowedInNativeNestedLoop(bool allowed) override;
  bool IsTaskExecutionAllowed() const override;
  MessagePump* GetBoundMessagePump() const override;
#if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID)
  void AttachToMessagePump() override;
#endif
#if BUILDFLAG(IS_IOS)
  void DetachFromMessagePump() override;
#endif
  void PrioritizeYieldingToNative(base::TimeTicks prioritize_until) override;
  bool ShouldQuitRunLoopWhenIdle() override;

  // RunLoop::NestingObserver:
  void OnBeginNestedRunLoop() override;
  void OnExitNestedRunLoop() override;

 protected:
  ThreadControllerImpl(SequenceManagerImpl* sequence_manager,
                       scoped_refptr<SingleThreadTaskRunner> task_runner,
                       const TickClock* time_source);

  const raw_ptr<SequenceManagerImpl> funneled_sequence_manager_;
  const scoped_refptr<SingleThreadTaskRunner> task_runner_;

  raw_ptr<RunLoop::NestingObserver> nesting_observer_ = nullptr;

 private:
  enum class WorkType { kImmediate, kDelayed };

  void DoWork(WorkType work_type);

  // TODO(scheduler-dev): Maybe fold this into the main class and use
  // thread annotations.
  struct MainSequenceOnly {
    MainSequenceOnly();
    ~MainSequenceOnly();

    int work_batch_size_ = 1;

    TimeTicks next_delayed_do_work = TimeTicks::Max();
  };

  MainSequenceOnly main_sequence_only_;
  MainSequenceOnly& main_sequence_only() LIFETIME_BOUND {
    DCHECK_CALLED_ON_VALID_SEQUENCE(associated_thread_->sequence_checker);
    return main_sequence_only_;
  }
  const MainSequenceOnly& main_sequence_only() const LIFETIME_BOUND {
    DCHECK_CALLED_ON_VALID_SEQUENCE(associated_thread_->sequence_checker);
    return main_sequence_only_;
  }

  scoped_refptr<SingleThreadTaskRunner> message_loop_task_runner_;
  RepeatingClosure immediate_do_work_closure_;
  RepeatingClosure delayed_do_work_closure_;
  CancelableRepeatingClosure cancelable_delayed_do_work_closure_;
  raw_ptr<SequencedTaskSource> sequence_ = nullptr;  // Not owned.
  TaskAnnotator task_annotator_;
  WorkDeduplicator work_deduplicator_;

#if DCHECK_IS_ON()
  bool default_task_runner_set_ = false;
#endif

  WeakPtrFactory<ThreadControllerImpl> weak_factory_{this};
};

}  // namespace internal
}  // namespace sequence_manager
}  // namespace base

#endif  // BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_IMPL_H_