blob: 46a4e02c35b09ceadd3b8299648cb758f76ee5ec [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"
12#include "base/synchronization/lock.h"
Takashi Toyoshima5bbd0f82017-07-04 17:05:09 +000013#include "base/synchronization/read_write_lock.h"
toyoshimccb8ff92017-06-13 05:31:46 -070014#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
69 // Keeps a TaskRunner for the thread that calls BindInstance() as a default
70 // task runner to run posted tasks.
71 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
72
73 // Holds threads to host SingleThreadTaskRunners.
74 std::vector<std::unique_ptr<base::Thread>> threads_;
75
Takashi Toyoshima5bbd0f82017-07-04 17:05:09 +000076 // Holds readers writer lock to ensure that tasks run only while the instance
77 // is bound. Writer lock should not be taken while |lock_| is acquired.
78 base::subtle::ReadWriteLock task_lock_;
toyoshimccb8ff92017-06-13 05:31:46 -070079
80 // Holds InstanceId for the next bound instance.
81 InstanceId next_instance_id_;
82
83 // Holds InstanceId for the current bound instance.
84 InstanceId bound_instance_id_;
85
Takashi Toyoshima5bbd0f82017-07-04 17:05:09 +000086 // Protects all members other than |task_lock_|.
toyoshimccb8ff92017-06-13 05:31:46 -070087 base::Lock lock_;
88
toyoshimccb8ff92017-06-13 05:31:46 -070089 DISALLOW_COPY_AND_ASSIGN(TaskService);
90};
91
92}; // namespace midi
93
94#endif // MEDIA_MIDI_TASK_SERVICE_H_