Skip to content

Commit 6109fb5

Browse files
authored
Merge pull request iqiyi#48 from acl-dev/master
Add more samples.
2 parents 91c4047 + f3aa571 commit 6109fb5

File tree

8 files changed

+243
-33
lines changed

8 files changed

+243
-33
lines changed

README.md

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
* [Resolve domain address in coroutine](#resolve-domain-address-in-coroutine)
1313
* [Create fiber with standard C++ API](#create-fiber-with-standard-c-api)
1414
* [Create fiber with C++1x API](#create-fiber-with-c1x-api)
15+
* [Transfer objects through box](#transfer-objects-through-box)
16+
* [Using wait_group to wait for the others done](#using-waitgroup-to-wait-for-the-others-done)
1517
* [Wait for the result from a thread](#wait-for-the-result-from-a-thread)
1618
* [Http server supporting http url route](#http-server-supporting-http-url-route)
1719
* [Windows GUI sample](#windows-gui-sample)
@@ -32,19 +34,19 @@
3234
<!-- vim-markdown-toc -->
3335

3436
## About
35-
The libfiber project comes from the coroutine module of the [acl project](#https://github.com/acl-dev/acl) in lib_fiber directory of which. It can be used on OS platfroms including Linux, FreeBSD, MacOS, and Windows, which supports select, poll, epoll, kqueue, iocp, and even Windows GUI messages for different platfrom. With libfiber, you can write network application services having the high performance and large cocurrent more easily than the traditional asynchronus framework with event-driven model. <b>What's more</b>, with the help of libfiber, you can even write network module of the Windows GUI application written by MFC, wtl or other GUI framework on Windows in coroutine way. That's realy amazing.
37+
The libfiber project comes from the coroutine module of the [acl project](#https://github.com/acl-dev/acl) in lib_fiber directory of which. It can be used on OS platforms including Linux, FreeBSD, macOS, and Windows, which supports select, poll, epoll, kqueue, iocp, and even Windows GUI messages for different platform. With libfiber, you can write network application services having the high performance and large concurrent more easily than the traditional asynchronous framework with event-driven model. <b>What's more</b>, with the help of libfiber, you can even write network module of the Windows GUI application written by MFC, wtl or other GUI framework on Windows in coroutine way. That's really amazing.
3638

3739
## Which IO events are supported ?
3840
The libfiber supports many events including select/poll/epoll/kqueue/iocp, and Windows GUI messages.
3941

40-
Event|Linux|BSD|Mac|Windows
41-
-----|----|------|---|---
42-
<b>select</b>|yes|yes|yes|yes
43-
<b>poll</b>|yes|yes|yes|yes
44-
<b>epoll</b>|yes|no|no|no
45-
<b>kqueue</b>|no|yes|yes|no
46-
<b>iocp</b>|no|no|no|yes
47-
<b>Win GUI message</b>|no|no|no|yes
42+
| Event | Linux | BSD | Mac | Windows |
43+
|------------------------|-------|-----|-----|---------|
44+
| <b>select</b> | yes | yes | yes | yes |
45+
| <b>poll</b> | yes | yes | yes | yes |
46+
| <b>epoll</b> | yes | no | no | no |
47+
| <b>kqueue</b> | no | yes | yes | no |
48+
| <b>iocp</b> | no | no | no | yes |
49+
| <b>Win GUI message</b> | no | no | no | yes |
4850

4951
## SAMPLES
5052

@@ -362,6 +364,70 @@ int main(void) {
362364
}
363365
```
364366
367+
### Transfer objects through box
368+
You can use fiber_tbox or fiber_tbox2 to transfer objs between different fibers and threads:
369+
```c++
370+
#include <memory>
371+
#include <thread>
372+
#include "fiber/fiber_tbox.hpp"
373+
374+
class myobj {
375+
public:
376+
myobj() = default;
377+
~myobj() = default;
378+
void run() { printf("hello world!\r\n"); }
379+
};
380+
381+
void test_tbox() {
382+
std::shared_ptr<acl::fiber_tbox<myobj>> box(new acl::fiber_tbox<myobj>);
383+
go[box] {
384+
myobj *o = box->pop();
385+
o->run();
386+
delete o;
387+
};
388+
go[box] {
389+
myobj *o = new myobj;
390+
box->push(o);
391+
};
392+
393+
go[box] {
394+
myobj *o = box->pop();
395+
o->run();
396+
delete o;
397+
};
398+
std::thread thread([box] {
399+
myobj *o = new myobj;
400+
box->push(o);
401+
});
402+
thread.detach();
403+
}
404+
```
405+
406+
### Using wait_group to wait for the others done
407+
You can use wait_group to wait for the other tasks:
408+
```c++
409+
#include "fiber/go_fiber.hpp"
410+
#include "fiber/wait_group.hpp"
411+
412+
void wait_others() {
413+
acl::wait_group wg;
414+
wg.add(2);
415+
416+
std::thread thr([&wg]{
417+
::sleep(1);
418+
wg.done();
419+
});
420+
thr.detach();
421+
422+
go[&wg] {
423+
::sleep(1);
424+
wg.done();
425+
};
426+
427+
wg.wait();
428+
}
429+
```
430+
365431
### Wait for the result from a thread
366432
```C
367433
#include <stdio.h>
@@ -447,9 +513,9 @@ int main(void) {
447513
```
448514

449515
### Windows GUI sample
450-
There is one Windows GUI sample with libfiber in [directory](samples/c/WinEchod). The screen shot is ![here](res/winecho.png)
516+
There is one Windows GUI sample with libfiber in [directory](samples/c/WinEchod). The screenshot is ![here](res/winecho.png)
451517

452-
The server coroutine and client coroutine are all running in the same thread as the GUI, so you can operate the GUI object in server and client coroutine without worrying about the memroy collision problem. And you can write network process with sequence way, other than asynchronus callback way which is so horrible. With the libfirber for Windows GUI, the asynchronus API like CAsyncSocket should be discarded. The network APIs are intergrated with the Windows GUI seamlessly because the libfiber using GUI message pump as event driven internal.
518+
The server coroutine and client coroutine are all running in the same thread as the GUI, so you can operate the GUI object in server and client coroutine without worrying about the memory collision problem. And you can write network process with sequence way, other than asynchronus callback way which is so horrible. With the libfirber for Windows GUI, the asynchronous API like CAsyncSocket should be discarded. The network APIs are intergrated with the Windows GUI seamlessly because the libfiber using GUI message pump as event driven internal.
453519

454520
### More SAMPLES
455521
You can get more samples in [samples](samples/), which use many APIs in [acl project](https://github.com/acl-dev/acl/tree/master/lib_fiber/samples) library.

cpp/include/fiber/fiber_tbox.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ namespace acl {
1515
*
1616
* class myobj {
1717
* public:
18-
* myobj(void) {}
18+
* myobj() {}
1919
* ~myobj(void) {}
2020
*
21-
* void test(void) { printf("hello world\r\n"); }
21+
* void test() { printf("hello world\r\n"); }
2222
* };
2323
*
2424
* acl::fiber_tbox<myobj> fiber_tbox;
2525
*
26-
* void thread_producer(void) {
26+
* void thread_producer() {
2727
* myobj* o = new myobj;
2828
* fiber_tbox.push(o);
2929
* }
3030
*
31-
* void thread_consumer(void) {
31+
* void thread_consumer() {
3232
* myobj* o = fiber_tbox.pop();
3333
* o->test();
3434
* delete o;
@@ -45,7 +45,7 @@ class fiber_tbox {
4545
*/
4646
fiber_tbox(bool free_obj = true) : size_(0), free_obj_(free_obj) {}
4747

48-
~fiber_tbox(void) {
48+
~fiber_tbox() {
4949
clear(free_obj_);
5050
}
5151

@@ -154,26 +154,26 @@ class fiber_tbox {
154154
* @return {bool}
155155
* @override
156156
*/
157-
bool has_null(void) const {
157+
bool has_null() const {
158158
return true;
159159
}
160160

161161
/**
162162
* 返回当前存在于消息队列中的消息数量
163163
* @return {size_t}
164164
*/
165-
size_t size(void) const {
165+
size_t size() const {
166166
return size_;
167167
}
168168

169169
public:
170-
void lock(void) {
170+
void lock() {
171171
if (mutex_.lock() == false) {
172172
abort();
173173
}
174174
}
175175

176-
void unlock(void) {
176+
void unlock() {
177177
if (mutex_.unlock() == false) {
178178
abort();
179179
}

cpp/include/fiber/fiber_tbox2.hpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ namespace acl {
1515
*
1616
* class myobj {
1717
* public:
18-
* myobj(void) {}
19-
* ~myobj(void) {}
18+
* myobj() {}
19+
* ~myobj() {}
2020
*
21-
* void test(void) { printf("hello world\r\n"); }
21+
* void test() { printf("hello world\r\n"); }
2222
* };
2323
*
2424
* acl::fiber_tbox2<myobj> tbox;
2525
*
26-
* void thread_producer(void) {
26+
* void thread_producer() {
2727
* myobj o;
2828
* tbox.push(o);
2929
* }
3030
*
31-
* void thread_consumer(void) {
31+
* void thread_consumer() {
3232
* myobj o;
3333
3434
* if (tbox.pop(o)) {
@@ -46,14 +46,14 @@ class fiber_tbox2 {
4646
/**
4747
* 构造方法
4848
*/
49-
fiber_tbox2(void) : size_(0) {}
49+
fiber_tbox2() : size_(0) {}
5050

51-
~fiber_tbox2(void) {}
51+
~fiber_tbox2() {}
5252

5353
/**
5454
* 清理消息队列中未被消费的消息对象
5555
*/
56-
void clear(void) {
56+
void clear() {
5757
tbox_.clear();
5858
}
5959

@@ -129,18 +129,18 @@ class fiber_tbox2 {
129129
* 返回当前存在于消息队列中的消息数量
130130
* @return {size_t}
131131
*/
132-
size_t size(void) const {
132+
size_t size() const {
133133
return size_;
134134
}
135135

136136
public:
137-
void lock(void) {
137+
void lock() {
138138
if (mutex_.lock() == false) {
139139
abort();
140140
}
141141
}
142142

143-
void unlock(void) {
143+
void unlock() {
144144
if (mutex_.unlock() == false) {
145145
abort();
146146
}

samples/cxx/fiber_tbox/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include ../Makefile.in
2+
PROG = fiber_tbox

samples/cxx/fiber_tbox/main.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <getopt.h>
4+
#include <thread>
5+
#include <iostream>
6+
7+
#include "fiber/fiber_tbox.hpp"
8+
#include "fiber/go_fiber.hpp"
9+
10+
class myobj {
11+
public:
12+
myobj() = default;
13+
~myobj() = default;
14+
15+
void run() {
16+
std::cout << "Thread: " << std::this_thread::get_id() << " hello world!\r\n";
17+
}
18+
};
19+
20+
static void usage(const char* procname) {
21+
printf("usage: %s -h [help]\r\n", procname);
22+
}
23+
24+
int main(int argc, char* argv[]) {
25+
int ch;
26+
27+
while ((ch = getopt(argc, argv, "h")) > 0) {
28+
switch (ch) {
29+
case 'h':
30+
usage(argv[0]);
31+
return 0;
32+
default:
33+
break;
34+
}
35+
}
36+
37+
std::shared_ptr<acl::fiber_tbox<myobj>> box(new acl::fiber_tbox<myobj>);
38+
39+
go[box] {
40+
myobj *o = box->pop();
41+
o->run();
42+
delete o;
43+
};
44+
45+
go[box] {
46+
myobj *o = new myobj;
47+
box->push(o);
48+
};
49+
50+
//////////////////////////////////////////////////////////////////////////
51+
52+
go[box] {
53+
myobj *o = new myobj;
54+
box->push(o);
55+
};
56+
57+
std::thread thread([box] {
58+
myobj *o = box->pop();
59+
o->run();
60+
delete o;
61+
});
62+
63+
acl::fiber::schedule();
64+
thread.join();
65+
return 0;
66+
}

samples/cxx/fiber_tbox2/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
include ../Makefile.in
2+
PROG = fiber_tbox2

samples/cxx/fiber_tbox2/main.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <getopt.h>
4+
#include <thread>
5+
#include <iostream>
6+
7+
#include "fiber/fiber_tbox2.hpp"
8+
#include "fiber/go_fiber.hpp"
9+
10+
class myobj {
11+
public:
12+
myobj() {
13+
std::cout << "Thread: " << std::this_thread::get_id() << " myobj created!\r\n";
14+
}
15+
16+
~myobj() {
17+
std::cout << "Thread: " << std::this_thread::get_id() << " myobj freed!\r\n";
18+
}
19+
20+
void run() {
21+
std::cout << "Thread: " << std::this_thread::get_id() << " hello world!\r\n";
22+
}
23+
};
24+
25+
using shared_myobj = std::shared_ptr<myobj>;
26+
using shared_tbox2 = std::shared_ptr<acl::fiber_tbox2<shared_myobj>>;
27+
28+
static void usage(const char* procname) {
29+
printf("usage: %s -h [help]\r\n", procname);
30+
}
31+
32+
int main(int argc, char* argv[]) {
33+
int ch;
34+
35+
while ((ch = getopt(argc, argv, "h")) > 0) {
36+
switch (ch) {
37+
case 'h':
38+
usage(argv[0]);
39+
return 0;
40+
default:
41+
break;
42+
}
43+
}
44+
45+
shared_tbox2 box(new acl::fiber_tbox2<shared_myobj>);
46+
47+
go[box] {
48+
shared_myobj o;
49+
box->pop(o);
50+
o->run();
51+
};
52+
53+
go[box] {
54+
shared_myobj o(new myobj);
55+
box->push(o);
56+
};
57+
58+
//////////////////////////////////////////////////////////////////////////
59+
60+
go[box] {
61+
shared_myobj o(new myobj);
62+
box->push(o);
63+
};
64+
65+
std::thread thread([box] {
66+
shared_myobj o;
67+
box->pop(o);
68+
o->run();
69+
});
70+
71+
acl::fiber::schedule();
72+
thread.join();
73+
return 0;
74+
}

0 commit comments

Comments
 (0)