blob: 4134df59db6d92b4c1b61908dbda6ca106bf7fa7 [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
toyoshimccb8ff92017-06-13 05:31:46 -070046 // Posts a task to run on a specified TaskRunner. |runner_id| should be
47 // kDefaultRunnerId or a positive number. If kDefaultRunnerId is specified
48 // the task runs on the thread on which BindInstance() is called. Other number
49 // will run the task on a dedicated thread that is bound to the |runner_id|.
50 void PostStaticTask(RunnerId runner_id, base::OnceClosure task);
51
52 // Posts a task to run on a specified TaskRunner, and ensures that the bound
53 // instance should not quit UnbindInstance() while a bound task is running.
54 // See PostStaticTask() for |runner_id|.
55 void PostBoundTask(RunnerId runner, base::OnceClosure task);
56 void PostBoundDelayedTask(RunnerId runner_id,
57 base::OnceClosure task,
58 base::TimeDelta delay);
59
60 private:
61 // Returns a SingleThreadTaskRunner reference. Each TaskRunner will be
62 // constructed on demand.
63 scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(RunnerId runner_id);
64
65 // Helps to run a posted bound task on TaskRunner safely.
66 void RunTask(InstanceId instance_id,
67 RunnerId runner_id,
68 base::OnceClosure task);
69
Robert Liaof66a9cf2017-08-26 01:40:35 +000070 // Returns true if |instance_id| is equal to |bound_instance_id_|.
71 bool IsInstanceIdStillBound(InstanceId instance_id);
72
toyoshimccb8ff92017-06-13 05:31:46 -070073 // Keeps a TaskRunner for the thread that calls BindInstance() as a default
74 // task runner to run posted tasks.
75 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
76
77 // Holds threads to host SingleThreadTaskRunners.
78 std::vector<std::unique_ptr<base::Thread>> threads_;
79
Robert Liaof66a9cf2017-08-26 01:40:35 +000080 // Protects |tasks_in_flight_|.
81 base::Lock tasks_in_flight_lock_;
82
83 // Signalled when the number of tasks in flight is 0 and ensures that
84 // UnbindInstance() does not return until all tasks have completed.
85 base::ConditionVariable no_tasks_in_flight_cv_;
86
87 // Number of tasks in flight.
88 int tasks_in_flight_;
toyoshimccb8ff92017-06-13 05:31:46 -070089
90 // Holds InstanceId for the next bound instance.
91 InstanceId next_instance_id_;
92
93 // Holds InstanceId for the current bound instance.
94 InstanceId bound_instance_id_;
95
Robert Liaof66a9cf2017-08-26 01:40:35 +000096 // Protects all members other than |tasks_in_flight_|.
toyoshimccb8ff92017-06-13 05:31:46 -070097 base::Lock lock_;
98
Robert Liaoa4512b62017-08-29 16:38:28 +000099 // Verifies all UnbindInstance() calls occur on the same sequence as
100 // BindSequence().
101 SEQUENCE_CHECKER(instance_binding_sequence_checker_);
102
toyoshimccb8ff92017-06-13 05:31:46 -0700103 DISALLOW_COPY_AND_ASSIGN(TaskService);
104};
105
106}; // namespace midi
107
108#endif // MEDIA_MIDI_TASK_SERVICE_H_