Skip to content

Commit

Permalink
fixed one bug in events_enable_read of events_epoll_thr.c; add some s…
Browse files Browse the repository at this point in the history
…amples for lib_fiber;
  • Loading branch information
ubuntu14 committed Aug 11, 2016
1 parent 3c8dc7b commit 0c54b8c
Show file tree
Hide file tree
Showing 31 changed files with 1,845 additions and 60 deletions.
4 changes: 4 additions & 0 deletions lib_acl/changes.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
�޸���ʷ�б���

------------------------------------------------------------------------
557) 2016.8.11
557.1) bugfix: events_epoll_thr.c �е� event_enable_read ������������ù���
THREAD_UNLOCK ��Ҫ epoll_ctl ����֮���������̺߳����߳�ͬʱ����ͬһ����

556) 2016.7.29
556.1) feature: json ������֧�� double ����Ԫ��

Expand Down
15 changes: 11 additions & 4 deletions lib_acl/src/event/events_epoll_thr.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *fp,
fdp = event_fdtable_alloc();
fdp->listener = 0;
fdp->stream = fp;

/* fdp will be freed in acl_vstream_close */
fp->fdp = (void *) fdp;
} else if (fdp->flag & EVENT_FDTABLE_FLAG_WRITE)
acl_msg_panic("%s(%d), %s: fd %d: multiple I/O request",
Expand Down Expand Up @@ -135,8 +137,6 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *fp,
return;
}

THREAD_UNLOCK(&evthr->event.tb_mutex);

if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) {
if (errno == EEXIST)
acl_msg_warn("%s: epoll_ctl: %s, fd: %d",
Expand All @@ -150,6 +150,8 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *fp,
acl_msg_fatal("%s: epoll_ctl: %s, fd: %d, epfd: %d",
myname, acl_last_serror(), fd, evthr->handle);
}

THREAD_UNLOCK(&evthr->event.tb_mutex);
}

static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *fp,
Expand All @@ -167,6 +169,8 @@ static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *fp,
fdp = event_fdtable_alloc();
fdp->stream = fp;
fdp->listener = 1;

/* fdp will be freed in acl_vstream_close */
fp->fdp = (void *) fdp;
} else if (fdp->flag & EVENT_FDTABLE_FLAG_WRITE)
acl_msg_panic("%s(%d)->%s: fd %d: multiple I/O request",
Expand Down Expand Up @@ -237,6 +241,8 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *fp,
fdp = event_fdtable_alloc();
fdp->listener = 0;
fdp->stream = fp;

/* fdp will be freed in acl_vstream_close */
fp->fdp = (void *) fdp;
} else if (fdp->flag & EVENT_FDTABLE_FLAG_READ)
acl_msg_panic("%s(%d)->%s: fd %d: multiple I/O request",
Expand Down Expand Up @@ -293,8 +299,6 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *fp,
THREAD_UNLOCK(&evthr->event.tb_mutex);
return;
}

THREAD_UNLOCK(&evthr->event.tb_mutex);

if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) {
if (errno == EEXIST)
Expand All @@ -309,6 +313,8 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *fp,
acl_msg_fatal("%s: epoll_ctl: %s, fd: %d, epfd: %d",
myname, acl_last_serror(), fd, evthr->handle);
}

THREAD_UNLOCK(&evthr->event.tb_mutex);
}

/* event_disable_readwrite - disable request for read or write events */
Expand Down Expand Up @@ -376,6 +382,7 @@ static void event_disable_readwrite(ACL_EVENT *eventp, ACL_VSTREAM *stream)
myname, acl_last_serror(), sockfd);
}

/* fdp will be freed in acl_vstream_close */
event_fdtable_reset(fdp);
}

Expand Down
213 changes: 213 additions & 0 deletions lib_fiber/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
本模块(lib_fiber)为基于协程方式进行高并发、高性能开发的网络协程库。使用者可以象创建线程一样创建协程,相对于线程而言,协程更为“轻量”,因此使用者可以创建大量(成千上万)的协程。每个协程可以与一个网络连接绑定;同时使用者可以采用“同步”思维方式编写网络程序,而不必象非阻塞程序一样采用异步回调方式,因此使用者使用起来并没有多大编程复杂度。
本网络协程库的协程部分是基于 Russ Cox (golang 的协程作者) 在 2005 年实现的 libtask,libtask 实现了协程编程的基本原型,lib_fiber 一方面使协程编程接口更加简单易用(用户可以直接调用 acl_fiber_create 创建协程),另一方面 lib_fiber 实现了线程安全的协程库,通过给每个线程一个独立的协程调度器,从而方便用户使用多核,此外,lib_fiber 还增加了基于协程的信号量、协程局部变量等功能。
本网络协程库的异步 IO 事件部分基于 redis 中的 event 模块改造而来,增加了延迟删除、句柄缓存等功能。

下面是一个简单使用网络协程库编写的一个简单的高并发服务器:

```c++
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include "lib_acl.h"
#include "fiber/lib_fiber.h"

static int __nconnect = 0;
static int __count = 0;
static char __listen_ip[64];
static int __listen_port = 9001;
static int __listen_qlen = 64;
static int __rw_timeout = 0;
static int __echo_data = 1;
static int __stack_size = 32000;

static int check_read(int fd, int timeout)
{
struct pollfd pfd;
int n;

memset(&pfd, 0, sizeof(struct pollfd));
pfd.fd = fd;
pfd.events = POLLIN;

n = poll(&pfd, 1, timeout);
if (n < 0) {
printf("poll error: %s\r\n", strerror(errno));
return -1;
}

if (n == 0)
return 0;
if (pfd.revents & POLLIN)
return 1;
else
return 0;
}

static void echo_client(ACL_FIBER *fiber acl_unused, void *ctx)
{
int *cfd = (int *) ctx;
char buf[8192];
int ret;

printf("client fiber-%d: fd: %d\r\n", acl_fiber_self(), *cfd);

while (1) {
if (__rw_timeout > 0) {
ret = check_read(*cfd, 10000);
if (ret < 0)
break;
if (ret == 0)
continue;
}

ret = read(*cfd, buf, sizeof(buf));
if (ret == 0) {
printf("read close by peer fd: %d\r\n", *cfd);
break;
} else if (ret < 0) {
if (errno == EINTR) {
printf("catch a EINTR signal\r\n");
continue;
}

printf("read error %s, fd: %d\n", strerror(errno), *cfd);
break;
}

__count++;

if (!__echo_data)
continue;

if (write(*cfd, buf, ret) < 0) {
if (errno == EINTR)
continue;
printf("write error, fd: %d\r\n", *cfd);
break;
}
}

printf("close %d\r\n", *cfd);
close(*cfd);
free(cfd);

if (--__nconnect == 0) {
printf("\r\n----total read/write: %d----\r\n", __count);
__count = 0;
}
}

static void fiber_accept(ACL_FIBER *fiber acl_unused, void *ctx acl_unused)
{
int lfd, on = 1;
struct sockaddr_in sa;

memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(__listen_port);
sa.sin_addr.s_addr = inet_addr(__listen_ip);

lfd = socket(AF_INET, SOCK_STREAM, 0);
if (lfd < 0)
abort();

if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) {
printf("setsockopt error %s\r\n", strerror(errno));
exit (1);
}

if (bind(lfd, (struct sockaddr *) &sa, sizeof(struct sockaddr)) < 0) {
printf("bind error %s\r\n", strerror(errno));
exit (1);
}

if (listen(lfd, 128) < 0) {
printf("listen error %s\r\n", strerror(errno));
exit (1);
}

printf("fiber-%d listen %s:%d ok\r\n",
acl_fiber_self(), __listen_ip, __listen_port);

for (;;) {
int len = sizeof(sa), *fd;
int cfd = accept(lfd, (struct sockaddr *)& sa, (socklen_t *) &len);
if (cfd < 0) {
printf("accept error %s\r\n", strerror(errno));
break;
}

fd = malloc(sizeof(int));
assert(fd != NULL);
*fd = cfd;

__nconnect++;
printf("accept one, fd: %d\r\n", cfd);
acl_fiber_create(echo_client, fd, __stack_size);
}

close(lfd);
exit(0);
}

static void usage(const char *procname)
{
printf("usage: %s -h [help]\r\n"
" -s listen_ip\r\n"
" -p listen_port\r\n"
" -r rw_timeout\r\n"
" -q listen_queue\r\n"
" -z stack_size\r\n"
" -S [if using single IO, default: no]\r\n", procname);
}

int main(int argc, char *argv[])
{
int ch;

snprintf(__listen_ip, sizeof(__listen_ip), "%s", "127.0.0.1");

while ((ch = getopt(argc, argv, "hs:p:r:q:Sz:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
return 0;
case 's':
snprintf(__listen_ip, sizeof(__listen_ip), "%s", optarg);
break;
case 'p':
__listen_port = atoi(optarg);
break;
case 'r':
__rw_timeout = atoi(optarg);
break;
case 'q':
__listen_qlen = atoi(optarg);
break;
case 'S':
__echo_data = 0;
break;
case 'z':
__stack_size = atoi(optarg);
break;
default:
break;
}
}

signal(SIGPIPE, SIG_IGN);
acl_msg_stdout_enable(1);

printf("%s: call fiber_creater\r\n", __FUNCTION__);
acl_fiber_create(fiber_accept, NULL, 32768);

printf("call fiber_schedule\r\n");
acl_fiber_schedule();

return 0;
}
```
3 changes: 3 additions & 0 deletions lib_fiber/author.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Author:
[email protected]
[email protected]
3 changes: 2 additions & 1 deletion lib_fiber/c/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ CFLAGS = -c -g -W \
-D_REENTRANT \
-D_POSIX_PTHREAD_SEMANTICS \
-D_USE_FAST_MACRO \
-Wno-long-long
-Wno-long-long \
-DUSE_JMP
#-DUSE_VALGRIND
#-Wno-clobbered
#-O3
Expand Down
Loading

0 comments on commit 0c54b8c

Please sign in to comment.