28
28
29
29
### ** workbranch**
30
30
31
- ** workbranch** (工作分支)是动态线程池的抽象,内置了一条线程安全的** 任务队列** 用于同步任务。其管理的每一条异步工作线程被称为** worker** ,负责从任务队列不断获取任务并执行。(以下示例位于 ` workspace/example/ ` )
31
+ ** workbranch** (工作分支)是动态线程池的抽象,内置了一条线程安全的** 任务队列** 用于同步任务。其管理的每一条异步工作线程被称为** worker** ,负责从任务队列不断获取任务并执行。(以下示例按顺序置于 ` workspace/example/ ` )
32
32
<br >
33
33
34
34
让我们先简单地提交一点任务,当你的任务带有返回值时,workbranch会返回一个std::future,否则返回void。
38
38
39
39
int main () {
40
40
// 2 threads
41
- wsp::workbranch br("My First BR", 2);
41
+ wsp::workbranch br(2);
42
42
// return void
43
43
br.submit([]{ std::cout<<"hello world"<<std::endl; });
44
44
// return std::future<int>
@@ -59,7 +59,7 @@ int main() {
59
59
60
60
int main () {
61
61
// 1 threads
62
- wsp::workbranch br("My Second BR") ;
62
+ wsp::workbranch br;
63
63
br.submit<wsp::task::nor>([]{ std::cout<<"task B done\n";}); // normal task
64
64
br.submit<wsp::task::urg>([]{ std::cout<<"task A done\n";}); // urgent task
65
65
br.wait_tasks(); // wait for tasks done (timeout: no limit)
@@ -82,7 +82,7 @@ task B done
82
82
#include < workspace/workspace.h>
83
83
84
84
int main () {
85
- wsp::workbranch br("My Third BR") ;
85
+ wsp::workbranch br;
86
86
// sequence tasks
87
87
br.submit<wsp::task::seq>([]{std::cout<<"task 1 done\n";},
88
88
[]{std::cout<<"task 2 done\n";},
@@ -145,7 +145,7 @@ Caught error: YYYY
145
145
146
146
### ** supervisor**
147
147
148
- supervisor是异步管理者线程的抽象,负责监控workbranch的负载情况并进行动态调整。它自带简单的日志系统,并允许你在每一次检查workbranch的时候插入一个小任务,比如:定制你的专属日志(如加入时间)、简单地统计任务负载等 。
148
+ supervisor是异步管理者线程的抽象,负责监控workbranch的负载情况并进行动态调整。它允许你在每一次调控workbranch之后执行一个小任务,你可以用来 ** 写日志 ** 或者做一些其它调控等 。
149
149
<br >
150
150
151
151
每一个supervisor可以管理多个workbranch。此时workbranch之间共享supervisor的所有设定。
@@ -154,99 +154,53 @@ supervisor是异步管理者线程的抽象,负责监控workbranch的负载情
154
154
#include < workspace/workspace.h>
155
155
156
156
int main () {
157
- wsp::workbranch br1("BR-1", 2);
158
- wsp::workbranch br2("BR-2", 2);
157
+ wsp::workbranch br1(2);
158
+ wsp::workbranch br2(2);
159
159
160
160
// 2 <= thread number <= 4
161
161
// time interval: 1000 ms
162
162
wsp::supervisor sp(2, 4, 1000);
163
163
164
- sp.enable_log(std::cout);
165
- sp.set_tick_cb([]{
166
- static char buffer[40];
164
+ sp.set_tick_cb([&br1, &br2]{
167
165
auto now = std::chrono::system_clock::now();
168
166
std::time_t timestamp = std::chrono::system_clock::to_time_t(now);
169
167
std::tm local_time = *std::localtime(×tamp);
168
+ static char buffer[40];
170
169
std::strftime (buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &local_time);
171
- std::cout<<"[ "<<buffer<<"] ";
170
+ std::cout<<"[ "<<buffer<<"] "<<"br1: [ workers] "<<br1.num_workers()<<" | [ blocking-tasks] "<<br1.num_tasks()<<'\n';
171
+ std::cout<<"[ "<<buffer<<"] "<<"br2: [ workers] "<<br2.num_workers()<<" | [ blocking-tasks] "<<br2.num_tasks()<<'\n';
172
172
});
173
+
173
174
sp.supervise(br1); // start supervising
174
175
sp.supervise(br2); // start supervising
175
176
176
177
for (int i = 0; i < 1000; ++i) {
177
178
br1.submit([]{std::this_thread::sleep_for(std::chrono::milliseconds(10));});
178
179
br2.submit([]{std::this_thread::sleep_for(std::chrono::milliseconds(20));});
179
180
}
181
+
180
182
br1.wait_tasks();
181
183
br2.wait_tasks();
182
184
}
183
185
```
184
186
185
- 在我的机器上,输出样式如下 :
187
+ 在我的机器上,输出如下 :
186
188
187
189
```
188
190
jack@xxx:~/workspace/example/build$ ./e4
189
- [2023-04-24 16:37:15] workspace: BR-2 workers: 2 [min] | blocking-task: 0
190
- [2023-04-24 16:37:15] workspace: BR-1 workers: 2 [min] | blocking-task: 0
191
- [2023-04-24 16:37:16] workspace: BR-2 workers: 2 [min] | blocking-task: 900
192
- [2023-04-24 16:37:16] workspace: BR-1 workers: 2 [min] | blocking-task: 802
193
- [2023-04-24 16:37:17] workspace: BR-2 workers: 4 [max] | blocking-task: 700
194
- [2023-04-24 16:37:17] workspace: BR-1 workers: 4 [max] | blocking-task: 406
195
- [2023-04-24 16:37:18] workspace: BR-2 workers: 4 [max] | blocking-task: 500
196
- [2023-04-24 16:37:18] workspace: BR-1 workers: 4 [max] | blocking-task: 10
197
- [2023-04-24 16:37:19] workspace: BR-2 workers: 4 [max] | blocking-task: 302
198
- [2023-04-24 16:37:19] workspace: BR-1 workers: 4 [max] | blocking-task: 0
199
- [2023-04-24 16:37:20] workspace: BR-2 workers: 4 [max] | blocking-task: 104
200
- [2023-04-24 16:37:20] workspace: BR-1 workers: 3 [mid] | blocking-task: 0
201
- ```
202
-
203
- 其中:
204
-
205
- - ` workers ` :代表线程数
206
-
207
- - ` [min]|[mid]|[max] ` : 代表了<最小|中等|最大>的线程数。
208
-
209
- - ` blocking-task ` :代表了当前任务队列中阻塞的任务数。
210
-
211
- 从代码中可以看到,我们在每一次检查的间隔插入了一个日志任务,用于补充supervisor的日志信息 —— 将当前的系统时间安插到默认日志之前。
212
- <br >
213
-
214
- 我们也可以让每一个supervisor单独管理一个workbranch,如下:
215
-
216
- ``` c++
217
- #include < workspace/workspace.h>
218
- #define TASKS 1000
219
- #define SLEEP_FOR(ms) std::this_thread::sleep_for(std::chrono::milliseconds(ms))
220
-
221
- int main () {
222
- wsp::workbranch main_br("Main ");
223
- wsp::workbranch help_br("Helper");
224
-
225
- wsp::supervisor main_br_sp(2, 4); // interval 500(ms)
226
- wsp::supervisor help_br_sp(0, 2); // interval 500(ms)
227
- main_br_sp.enable_log();
228
- help_br_sp.enable_log();
229
-
230
- main_br_sp.supervise(main_br);
231
- help_br_sp.supervise(help_br);
232
-
233
- for (int i = 0; i < TASKS; ++i) {
234
- if (main_br.num_tasks() > 200) {
235
- if (help_br.num_tasks() > 200)
236
- SLEEP_FOR (20);
237
- else
238
- help_br.submit([ ] {SLEEP_FOR(10);});
239
- } else {
240
- main_br.submit([ ] {SLEEP_FOR(10);});
241
- }
242
- }
243
- main_br.wait_tasks();
244
- help_br.wait_tasks();
245
- }
191
+ [2023-06-13 12:24:31] br1: [workers] 4 | [blocking-tasks] 606
192
+ [2023-06-13 12:24:31] br2: [workers] 4 | [blocking-tasks] 800
193
+ [2023-06-13 12:24:32] br1: [workers] 4 | [blocking-tasks] 213
194
+ [2023-06-13 12:24:32] br2: [workers] 4 | [blocking-tasks] 600
195
+ [2023-06-13 12:24:33] br1: [workers] 4 | [blocking-tasks] 0
196
+ [2023-06-13 12:24:33] br2: [workers] 4 | [blocking-tasks] 404
197
+ [2023-06-13 12:24:34] br1: [workers] 3 | [blocking-tasks] 0
198
+ [2023-06-13 12:24:34] br2: [workers] 4 | [blocking-tasks] 204
199
+ [2023-06-13 12:24:35] br1: [workers] 2 | [blocking-tasks] 0
200
+ [2023-06-13 12:24:35] br2: [workers] 4 | [blocking-tasks] 4
201
+ [2023-06-13 12:24:35] br1: [workers] 2 | [blocking-tasks] 0
202
+ [2023-06-13 12:24:35] br2: [workers] 4 | [blocking-tasks] 0
246
203
```
247
-
248
- 在这个例子中我们申请了两个工作分支,并将其中一个作为** 主要分支** ,另一个作为** 辅助分支** ,接纳主要分支无法容纳的任务。值得注意的是:各个supervisor之间的输出** 线程安全** 的。
249
-
250
204
---
251
205
252
206
### ** workspace**
@@ -258,25 +212,20 @@ workspace是一个**托管器**/**任务分发器**,你可以将workbranch和s
258
212
- 避免空悬指针问题:当workbranch先于supervisor析构会造成** 空悬指针** 的问题,使用workspace可以避免这种情况
259
213
- 更低的框架开销:workspace的任务分发机制能减少与工作线程的竞争,提高性能(见下Benchmark)。
260
214
261
- 我们可以通过workspace自带的任务分发机制( 调用` submit ` ),或者调用 ` for_each ` 来进行任务分发。前者显然是更好的方式 。
215
+ 我们可以通过workspace自带的任务分发机制来异步执行任务( 调用` submit ` ) 。
262
216
263
217
``` C++
264
218
#include < workspace/workspace.h>
265
219
266
220
int main () {
267
221
wsp::workspace spc;
268
- auto bid1 = spc.attach(new wsp::workbranch("BR1") );
269
- auto bid2 = spc.attach(new wsp::workbranch("BR2") );
222
+ auto bid1 = spc.attach(new wsp::workbranch);
223
+ auto bid2 = spc.attach(new wsp::workbranch);
270
224
auto sid1 = spc.attach(new wsp::supervisor(2, 4));
271
225
auto sid2 = spc.attach(new wsp::supervisor(2, 4));
272
226
spc[sid1].supervise(spc[bid1]); // start supervising
273
227
spc[sid2].supervise(spc[bid2]); // start supervising
274
228
275
- // Manual assignment
276
- spc.for_each([](wsp::workbranch& each){
277
- each.submit([]{std::cout<<std::this_thread::get_id()<<" executed task"<<std::endl;});
278
- each.wait_tasks();
279
- });
280
229
// Automatic assignment
281
230
spc.submit([]{std::cout<<std::this_thread::get_id()<<" executed task"<<std::endl;});
282
231
spc.submit([]{std::cout<<std::this_thread::get_id()<<" executed task"<<std::endl;});
0 commit comments