blob: 2e19b2ca2d7746f4e97ac9df97d77b4d08d6b689 [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
8#include "base/callback_forward.h"
9#include "base/macros.h"
10#include "base/memory/ref_counted.h"
Robert Liaoa4512b62017-08-29 16:38:28 +000011#include "base/sequence_checker.h"
toyoshimccb8ff92017-06-13 05:31:46 -070012#include "base/single_thread_task_runner.h"
Robert Liaof66a9cf2017-08-26 01:40:35 +000013#include "base/synchronization/condition_variable.h"
toyoshimccb8ff92017-06-13 05:31:46 -070014#include "base/synchronization/lock.h"
15#include "base/threading/thread.h"
16#include "base/time/time.h"
17#include "media/midi/midi_export.h"
18
19namespace midi {
20
21// TaskService manages TaskRunners that can be used in midi and provides
22// functionalities to ensure thread safety.
23class MIDI_EXPORT TaskService final {
24 public:
25 using RunnerId = size_t;
26 using InstanceId = int;
27
28 static constexpr RunnerId kDefaultRunnerId = 0;
29
30 TaskService();
31 ~TaskService();
32
33 // Issues an InstanceId internally to post tasks via PostBoundTask() and
34 // PostDelayedBoundTask() with the InstanceId. Once UnbindInstance() is
35 // called, tasks posted via these methods with unbind InstanceId won't be
36 // invoked any more.
37 // Returns true if call is bound or unbound correctly. Otherwise returns
38 // false, that happens when the BindInstance() is called twice without
39 // unbinding the previous instance.
40 bool BindInstance();
41 bool UnbindInstance();
42
Takashi Toyoshima143f0fd2017-08-01 16:15:33 +000043 // Checks if the current thread belongs to the specified runner.
44 bool IsOnTaskRunner(RunnerId runner_id);
45
Takashi Toyoshima3f0ea8f2018-01-17 09:19:59 +000046 // Posts a task to run on a specified TaskRunner. |runner_id| should be a
47 // positive number that represents a dedicated thread on that |task| will run.
48 // |task| will run even without a bound instance.
toyoshimccb8ff92017-06-13 05:31:46 -070049 void PostStaticTask(RunnerId runner_id, base::OnceClosure task);
50
51 // Posts a task to run on a specified TaskRunner, and ensures that the bound
52 // instance should not quit UnbindInstance() while a bound task is running.
Takashi Toyoshima3f0ea8f2018-01-17 09:19:59 +000053 // |runner_id| should be |kDefaultRunnerId| or a positive number. If
54 // |kDefaultRunnerId| is specified, the task runs on the thread on which
55 // BindInstance() was called.
toyoshimccb8ff92017-06-13 05:31:46 -070056 void PostBoundTask(RunnerId runner, base::OnceClosure task);
57 void PostBoundDelayedTask(RunnerId runner_id,
58 base::OnceClosure task,
59 base::TimeDelta delay);
60
61 private:
62 // Returns a SingleThreadTaskRunner reference. Each TaskRunner will be
63 // constructed on demand.
64 scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(RunnerId runner_id);
65
66 // Helps to run a posted bound task on TaskRunner safely.
67 void RunTask(InstanceId instance_id,
68 RunnerId runner_id,
69 base::OnceClosure task);
70
Robert Liaof66a9cf2017-08-26 01:40:35 +000071 // Returns true if |instance_id| is equal to |bound_instance_id_|.
72 bool IsInstanceIdStillBound(InstanceId instance_id);
73
toyoshimccb8ff92017-06-13 05:31:46 -070074 // Keeps a TaskRunner for the thread that calls BindInstance() as a default
75 // task runner to run posted tasks.
76 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
77
78 // Holds threads to host SingleThreadTaskRunners.
79 std::vector<std::unique_ptr<base::Thread>> threads_;
80
Robert Liaof66a9cf2017-08-26 01:40:35 +000081 // Protects |tasks_in_flight_|.
82 base::Lock tasks_in_flight_lock_;
83
84 // Signalled when the number of tasks in flight is 0 and ensures that
85 // UnbindInstance() does not return until all tasks have completed.
86 base::ConditionVariable no_tasks_in_flight_cv_;
87
88 // Number of tasks in flight.
89 int tasks_in_flight_;
toyoshimccb8ff92017-06-13 05:31:46 -070090
91 // Holds InstanceId for the next bound instance.
92 InstanceId next_instance_id_;
93
94 // Holds InstanceId for the current bound instance.
95 InstanceId bound_instance_id_;
96
Robert Liaof66a9cf2017-08-26 01:40:35 +000097 // Protects all members other than |tasks_in_flight_|.
toyoshimccb8ff92017-06-13 05:31:46 -070098 base::Lock lock_;
99
Robert Liaoa4512b62017-08-29 16:38:28 +0000100 // Verifies all UnbindInstance() calls occur on the same sequence as
Takashi Toyoshimad2bdc592017-09-13 10:02:54 +0000101 // BindInstance().
Robert Liaoa4512b62017-08-29 16:38:28 +0000102 SEQUENCE_CHECKER(instance_binding_sequence_checker_);
103
toyoshimccb8ff92017-06-13 05:31:46 -0700104 DISALLOW_COPY_AND_ASSIGN(TaskService);
105};
106
Nico Webera0faaf72019-02-07 19:07:54 +0000107} // namespace midi
toyoshimccb8ff92017-06-13 05:31:46 -0700108
109#endif // MEDIA_MIDI_TASK_SERVICE_H_