/
thread_pool.h
149 lines (108 loc) · 3.68 KB
/
thread_pool.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_VM_THREAD_POOL_H_
#define RUNTIME_VM_THREAD_POOL_H_
#include "vm/allocation.h"
#include "vm/globals.h"
#include "vm/os_thread.h"
namespace dart {
class ThreadPool {
public:
// Subclasses of Task are able to run on a ThreadPool.
class Task {
protected:
Task();
public:
virtual ~Task();
// Override this to provide task-specific behavior.
virtual void Run() = 0;
private:
DISALLOW_COPY_AND_ASSIGN(Task);
};
ThreadPool();
// Shuts down this thread pool. Causes workers to terminate
// themselves when they are active again.
~ThreadPool();
// Runs a task on the thread pool.
bool Run(Task* task);
// Some simple stats.
uint64_t workers_running() const { return count_running_; }
uint64_t workers_idle() const { return count_idle_; }
uint64_t workers_started() const { return count_started_; }
uint64_t workers_stopped() const { return count_stopped_; }
private:
class Worker {
public:
explicit Worker(ThreadPool* pool);
// Sets a task on the worker.
void SetTask(Task* task);
// Starts the thread for the worker. This should only be called
// after a task has been set by the initial call to SetTask().
void StartThread();
// Main loop for a worker. Returns true if worker is removed from thread
// lists, false otherwise.
bool Loop();
// Causes worker to terminate eventually.
void Shutdown();
// Get the Worker's thread id.
ThreadId id();
private:
friend class ThreadPool;
// The main entry point for new worker threads.
static void Main(uword args);
bool IsDone() const { return done_; }
// Fields owned by Worker.
Monitor monitor_;
ThreadPool* pool_;
Task* task_;
ThreadId id_;
bool done_;
// Fields owned by ThreadPool. Workers should not look at these
// directly. It's like looking at the sun.
bool owned_; // Protected by ThreadPool::mutex_
Worker* all_next_; // Protected by ThreadPool::mutex_
Worker* idle_next_; // Protected by ThreadPool::mutex_
Worker* shutdown_next_; // Protected by ThreadPool::exit_monitor
DISALLOW_COPY_AND_ASSIGN(Worker);
};
class JoinList {
public:
explicit JoinList(ThreadJoinId id, JoinList* next) : id_(id), next_(next) {}
// The thread pool's mutex_ must be held when calling this.
static void AddLocked(ThreadJoinId id, JoinList** list);
static void Join(JoinList** list);
ThreadJoinId id() const { return id_; }
JoinList* next() const { return next_; }
private:
ThreadJoinId id_;
JoinList* next_;
DISALLOW_COPY_AND_ASSIGN(JoinList);
};
void Shutdown();
// Expensive. Use only in assertions.
bool IsIdle(Worker* worker);
bool RemoveWorkerFromIdleList(Worker* worker);
bool RemoveWorkerFromAllList(Worker* worker);
void AddWorkerToShutdownList(Worker* worker);
bool RemoveWorkerFromShutdownList(Worker* worker);
void ReapExitedIdleThreads();
// Worker operations.
void SetIdleLocked(Worker* worker); // Assumes mutex_ is held.
void SetIdleAndReapExited(Worker* worker);
bool ReleaseIdleWorker(Worker* worker);
Mutex mutex_;
bool shutting_down_;
Worker* all_workers_;
Worker* idle_workers_;
uint64_t count_started_;
uint64_t count_stopped_;
uint64_t count_running_;
uint64_t count_idle_;
Monitor exit_monitor_;
Worker* shutting_down_workers_;
JoinList* join_list_;
DISALLOW_COPY_AND_ASSIGN(ThreadPool);
};
} // namespace dart
#endif // RUNTIME_VM_THREAD_POOL_H_