blob: 679dfb91bdf776a59c8e639c8eaa2776a815f0d7 [file] [log] [blame]
toyoshimccb8ff92017-06-13 05:31:46 -07001// Copyright 2017 The Chromium Authors. All rights reserved.
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 MEDIA_MIDI_TASK_SERVICE_H_
6#define MEDIA_MIDI_TASK_SERVICE_H_
7
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +00008#include <memory>
9#include <vector>
10
toyoshimccb8ff92017-06-13 05:31:46 -070011#include "base/callback_forward.h"
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000012#include "base/compiler_specific.h"
toyoshimccb8ff92017-06-13 05:31:46 -070013#include "base/macros.h"
14#include "base/memory/ref_counted.h"
Robert Liaoa4512b62017-08-29 16:38:28 +000015#include "base/sequence_checker.h"
Robert Liaof66a9cf2017-08-26 01:40:35 +000016#include "base/synchronization/condition_variable.h"
toyoshimccb8ff92017-06-13 05:31:46 -070017#include "base/synchronization/lock.h"
Patrick Monette3f9156f2021-10-15 19:13:42 +000018#include "base/task/single_thread_task_runner.h"
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000019#include "base/thread_annotations.h"
toyoshimccb8ff92017-06-13 05:31:46 -070020#include "base/threading/thread.h"
21#include "base/time/time.h"
22#include "media/midi/midi_export.h"
23
24namespace midi {
25
26// TaskService manages TaskRunners that can be used in midi and provides
27// functionalities to ensure thread safety.
28class MIDI_EXPORT TaskService final {
29 public:
30 using RunnerId = size_t;
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000031 using InstanceId = int64_t;
toyoshimccb8ff92017-06-13 05:31:46 -070032
33 static constexpr RunnerId kDefaultRunnerId = 0;
34
35 TaskService();
Peter Boström53634032021-09-22 20:24:34 +000036
37 TaskService(const TaskService&) = delete;
38 TaskService& operator=(const TaskService&) = delete;
39
toyoshimccb8ff92017-06-13 05:31:46 -070040 ~TaskService();
41
42 // Issues an InstanceId internally to post tasks via PostBoundTask() and
43 // PostDelayedBoundTask() with the InstanceId. Once UnbindInstance() is
44 // called, tasks posted via these methods with unbind InstanceId won't be
45 // invoked any more.
46 // Returns true if call is bound or unbound correctly. Otherwise returns
47 // false, that happens when the BindInstance() is called twice without
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000048 // unbinding the previous instance, or the UnbindInstance() is called without
49 // any successful BindInstance() call.
50 bool BindInstance() WARN_UNUSED_RESULT;
51 bool UnbindInstance() WARN_UNUSED_RESULT;
toyoshimccb8ff92017-06-13 05:31:46 -070052
Takashi Toyoshima143f0fd2017-08-01 16:15:33 +000053 // Checks if the current thread belongs to the specified runner.
54 bool IsOnTaskRunner(RunnerId runner_id);
55
Takashi Toyoshima3f0ea8f2018-01-17 09:19:59 +000056 // Posts a task to run on a specified TaskRunner. |runner_id| should be a
57 // positive number that represents a dedicated thread on that |task| will run.
58 // |task| will run even without a bound instance.
toyoshimccb8ff92017-06-13 05:31:46 -070059 void PostStaticTask(RunnerId runner_id, base::OnceClosure task);
60
61 // Posts a task to run on a specified TaskRunner, and ensures that the bound
62 // instance should not quit UnbindInstance() while a bound task is running.
Takashi Toyoshima3f0ea8f2018-01-17 09:19:59 +000063 // |runner_id| should be |kDefaultRunnerId| or a positive number. If
64 // |kDefaultRunnerId| is specified, the task runs on the thread on which
65 // BindInstance() was called.
toyoshimccb8ff92017-06-13 05:31:46 -070066 void PostBoundTask(RunnerId runner, base::OnceClosure task);
67 void PostBoundDelayedTask(RunnerId runner_id,
68 base::OnceClosure task,
69 base::TimeDelta delay);
70
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000071 void OverflowInstanceIdForTesting();
72
toyoshimccb8ff92017-06-13 05:31:46 -070073 private:
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000074 static constexpr TaskService::InstanceId kInvalidInstanceId = -1;
75
toyoshimccb8ff92017-06-13 05:31:46 -070076 // Returns a SingleThreadTaskRunner reference. Each TaskRunner will be
77 // constructed on demand.
78 scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(RunnerId runner_id);
79
80 // Helps to run a posted bound task on TaskRunner safely.
81 void RunTask(InstanceId instance_id,
82 RunnerId runner_id,
83 base::OnceClosure task);
84
Robert Liaof66a9cf2017-08-26 01:40:35 +000085 // Returns true if |instance_id| is equal to |bound_instance_id_|.
86 bool IsInstanceIdStillBound(InstanceId instance_id);
87
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000088 // Holds InstanceId for the next bound instance, accessed on the BindInstance
89 // call thread without any protection.
90 InstanceId next_instance_id_ = kInvalidInstanceId;
91
toyoshimccb8ff92017-06-13 05:31:46 -070092 // Keeps a TaskRunner for the thread that calls BindInstance() as a default
93 // task runner to run posted tasks.
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000094 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_
95 GUARDED_BY(lock_);
toyoshimccb8ff92017-06-13 05:31:46 -070096
97 // Holds threads to host SingleThreadTaskRunners.
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +000098 std::vector<std::unique_ptr<base::Thread>> threads_ GUARDED_BY(lock_);
toyoshimccb8ff92017-06-13 05:31:46 -070099
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +0000100 // Holds InstanceId for the current bound instance.
101 InstanceId bound_instance_id_ GUARDED_BY(lock_) = kInvalidInstanceId;
102
103 base::Lock lock_;
Robert Liaof66a9cf2017-08-26 01:40:35 +0000104
105 // Signalled when the number of tasks in flight is 0 and ensures that
106 // UnbindInstance() does not return until all tasks have completed.
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +0000107 base::ConditionVariable no_tasks_in_flight_cv_
108 GUARDED_BY(tasks_in_flight_lock_);
Robert Liaof66a9cf2017-08-26 01:40:35 +0000109
110 // Number of tasks in flight.
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +0000111 int tasks_in_flight_ GUARDED_BY(tasks_in_flight_lock_) = 0;
toyoshimccb8ff92017-06-13 05:31:46 -0700112
Takashi Toyoshima88b4ac02019-02-12 11:25:56 +0000113 base::Lock tasks_in_flight_lock_;
toyoshimccb8ff92017-06-13 05:31:46 -0700114
Robert Liaoa4512b62017-08-29 16:38:28 +0000115 // Verifies all UnbindInstance() calls occur on the same sequence as
Takashi Toyoshimad2bdc592017-09-13 10:02:54 +0000116 // BindInstance().
Robert Liaoa4512b62017-08-29 16:38:28 +0000117 SEQUENCE_CHECKER(instance_binding_sequence_checker_);
toyoshimccb8ff92017-06-13 05:31:46 -0700118};
119
Nico Webera0faaf72019-02-07 19:07:54 +0000120} // namespace midi
toyoshimccb8ff92017-06-13 05:31:46 -0700121
122#endif // MEDIA_MIDI_TASK_SERVICE_H_