blob: 0424046776b6c662eba68564788942bb1ef7f497 [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"
11#include "base/single_thread_task_runner.h"
Robert Liaof66a9cf2017-08-26 01:40:35 +000012#include "base/synchronization/condition_variable.h"
toyoshimccb8ff92017-06-13 05:31:46 -070013#include "base/synchronization/lock.h"
14#include "base/threading/thread.h"
15#include "base/time/time.h"
16#include "media/midi/midi_export.h"
17
18namespace midi {
19
20// TaskService manages TaskRunners that can be used in midi and provides
21// functionalities to ensure thread safety.
22class MIDI_EXPORT TaskService final {
23 public:
24 using RunnerId = size_t;
25 using InstanceId = int;
26
27 static constexpr RunnerId kDefaultRunnerId = 0;
28
29 TaskService();
30 ~TaskService();
31
32 // Issues an InstanceId internally to post tasks via PostBoundTask() and
33 // PostDelayedBoundTask() with the InstanceId. Once UnbindInstance() is
34 // called, tasks posted via these methods with unbind InstanceId won't be
35 // invoked any more.
36 // Returns true if call is bound or unbound correctly. Otherwise returns
37 // false, that happens when the BindInstance() is called twice without
38 // unbinding the previous instance.
39 bool BindInstance();
40 bool UnbindInstance();
41
Takashi Toyoshima143f0fd2017-08-01 16:15:33 +000042 // Checks if the current thread belongs to the specified runner.
43 bool IsOnTaskRunner(RunnerId runner_id);
44
toyoshimccb8ff92017-06-13 05:31:46 -070045 // Posts a task to run on a specified TaskRunner. |runner_id| should be
46 // kDefaultRunnerId or a positive number. If kDefaultRunnerId is specified
47 // the task runs on the thread on which BindInstance() is called. Other number
48 // will run the task on a dedicated thread that is bound to the |runner_id|.
49 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.
53 // See PostStaticTask() for |runner_id|.
54 void PostBoundTask(RunnerId runner, base::OnceClosure task);
55 void PostBoundDelayedTask(RunnerId runner_id,
56 base::OnceClosure task,
57 base::TimeDelta delay);
58
59 private:
60 // Returns a SingleThreadTaskRunner reference. Each TaskRunner will be
61 // constructed on demand.
62 scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(RunnerId runner_id);
63
64 // Helps to run a posted bound task on TaskRunner safely.
65 void RunTask(InstanceId instance_id,
66 RunnerId runner_id,
67 base::OnceClosure task);
68
Robert Liaof66a9cf2017-08-26 01:40:35 +000069 // Returns true if |instance_id| is equal to |bound_instance_id_|.
70 bool IsInstanceIdStillBound(InstanceId instance_id);
71
toyoshimccb8ff92017-06-13 05:31:46 -070072 // Keeps a TaskRunner for the thread that calls BindInstance() as a default
73 // task runner to run posted tasks.
74 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
75
76 // Holds threads to host SingleThreadTaskRunners.
77 std::vector<std::unique_ptr<base::Thread>> threads_;
78
Robert Liaof66a9cf2017-08-26 01:40:35 +000079 // Protects |tasks_in_flight_|.
80 base::Lock tasks_in_flight_lock_;
81
82 // Signalled when the number of tasks in flight is 0 and ensures that
83 // UnbindInstance() does not return until all tasks have completed.
84 base::ConditionVariable no_tasks_in_flight_cv_;
85
86 // Number of tasks in flight.
87 int tasks_in_flight_;
toyoshimccb8ff92017-06-13 05:31:46 -070088
89 // Holds InstanceId for the next bound instance.
90 InstanceId next_instance_id_;
91
92 // Holds InstanceId for the current bound instance.
93 InstanceId bound_instance_id_;
94
Robert Liaof66a9cf2017-08-26 01:40:35 +000095 // Protects all members other than |tasks_in_flight_|.
toyoshimccb8ff92017-06-13 05:31:46 -070096 base::Lock lock_;
97
toyoshimccb8ff92017-06-13 05:31:46 -070098 DISALLOW_COPY_AND_ASSIGN(TaskService);
99};
100
101}; // namespace midi
102
103#endif // MEDIA_MIDI_TASK_SERVICE_H_