mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-11-30 02:47:56 +08:00
fixed one bug in events_enable_read of events_epoll_thr.c; add some samples for lib_fiber;
This commit is contained in:
parent
3c8dc7b019
commit
0c54b8c0d5
@ -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 数据元素
|
||||
|
||||
|
@ -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",
|
||||
@ -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",
|
||||
@ -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,
|
||||
@ -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",
|
||||
@ -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",
|
||||
@ -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)
|
||||
@ -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 */
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
213
lib_fiber/README.md
Normal file
213
lib_fiber/README.md
Normal file
@ -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
lib_fiber/author.txt
Normal file
3
lib_fiber/author.txt
Normal file
@ -0,0 +1,3 @@
|
||||
Author:
|
||||
niukey@qq.com
|
||||
shuxin.zheng@qq.com
|
@ -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
|
||||
|
555
lib_fiber/c/src/dev/fiber.c
Normal file
555
lib_fiber/c/src/dev/fiber.c
Normal file
@ -0,0 +1,555 @@
|
||||
#include "stdafx.h"
|
||||
#define __USE_GNU
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifdef USE_VALGRIND
|
||||
#include <valgrind/valgrind.h>
|
||||
#endif
|
||||
|
||||
#include "fiber/lib_fiber.h"
|
||||
#include "event_epoll.h" /* just for hook_epoll */
|
||||
#include "fiber.h"
|
||||
|
||||
typedef int *(*errno_fn)(void);
|
||||
typedef int (*fcntl_fn)(int, int, ...);
|
||||
|
||||
static errno_fn __sys_errno = NULL;
|
||||
static fcntl_fn __sys_fcntl = NULL;
|
||||
|
||||
typedef struct {
|
||||
ACL_RING ready; /* ready fiber queue */
|
||||
ACL_RING dead; /* dead fiber queue */
|
||||
ACL_FIBER **fibers;
|
||||
size_t size;
|
||||
int exitcode;
|
||||
ACL_FIBER *running;
|
||||
ACL_FIBER *schedule;
|
||||
ACL_FIBER *fiber;
|
||||
int errnum;
|
||||
size_t idgen;
|
||||
int count;
|
||||
int switched;
|
||||
} FIBER_TLS;
|
||||
|
||||
static FIBER_TLS *__main_fiber = NULL;
|
||||
static __thread FIBER_TLS *__thread_fiber = NULL;
|
||||
__thread int acl_var_hook_sys_api = 0;
|
||||
|
||||
static acl_pthread_key_t __fiber_key;
|
||||
static void fiber_free(ACL_FIBER *fiber);
|
||||
static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
|
||||
void *arg, size_t size);
|
||||
|
||||
void acl_fiber_hook_api(int onoff)
|
||||
{
|
||||
acl_var_hook_sys_api = onoff;
|
||||
}
|
||||
|
||||
static void thread_free(void *ctx)
|
||||
{
|
||||
FIBER_TLS *tf = (FIBER_TLS *) ctx;
|
||||
|
||||
if (__thread_fiber == NULL)
|
||||
return;
|
||||
|
||||
if (tf->fibers)
|
||||
acl_myfree(tf->fibers);
|
||||
fiber_free(tf->schedule);
|
||||
fiber_free(tf->fiber);
|
||||
acl_myfree(tf);
|
||||
if (__main_fiber == __thread_fiber)
|
||||
__main_fiber = NULL;
|
||||
__thread_fiber = NULL;
|
||||
}
|
||||
|
||||
static void fiber_schedule_main_free(void)
|
||||
{
|
||||
if (__main_fiber) {
|
||||
thread_free(__main_fiber);
|
||||
if (__thread_fiber == __main_fiber)
|
||||
__thread_fiber = NULL;
|
||||
__main_fiber = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void thread_init(void)
|
||||
{
|
||||
acl_assert(acl_pthread_key_create(&__fiber_key, thread_free) == 0);
|
||||
}
|
||||
|
||||
static acl_pthread_once_t __once_control = ACL_PTHREAD_ONCE_INIT;
|
||||
|
||||
static void fiber_check(void)
|
||||
{
|
||||
if (__thread_fiber != NULL)
|
||||
return;
|
||||
|
||||
acl_assert(acl_pthread_once(&__once_control, thread_init) == 0);
|
||||
|
||||
__thread_fiber = (FIBER_TLS *) acl_mycalloc(1, sizeof(FIBER_TLS));
|
||||
__thread_fiber->fibers = NULL;
|
||||
__thread_fiber->size = 0;
|
||||
__thread_fiber->idgen = 0;
|
||||
__thread_fiber->count = 0;
|
||||
__thread_fiber->schedule = fiber_alloc(NULL, NULL, 6400000);
|
||||
__thread_fiber->fiber = fiber_alloc(NULL, NULL, 6400000);
|
||||
|
||||
acl_ring_init(&__thread_fiber->ready);
|
||||
acl_ring_init(&__thread_fiber->dead);
|
||||
|
||||
if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) {
|
||||
__main_fiber = __thread_fiber;
|
||||
atexit(fiber_schedule_main_free);
|
||||
} else if (acl_pthread_setspecific(__fiber_key, __thread_fiber) != 0)
|
||||
acl_msg_fatal("acl_pthread_setspecific error!");
|
||||
}
|
||||
|
||||
/* see /usr/include/bits/errno.h for __errno_location */
|
||||
int *__errno_location(void)
|
||||
{
|
||||
if (!acl_var_hook_sys_api)
|
||||
return __sys_errno();
|
||||
|
||||
if (__thread_fiber == NULL)
|
||||
fiber_check();
|
||||
|
||||
if (__thread_fiber->running)
|
||||
return &__thread_fiber->running->errnum;
|
||||
else
|
||||
return &__thread_fiber->schedule->errnum;
|
||||
}
|
||||
|
||||
int fcntl(int fd, int cmd, ...)
|
||||
{
|
||||
long arg;
|
||||
struct flock *lock;
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case F_GETFD:
|
||||
case F_GETFL:
|
||||
ret = __sys_fcntl(fd, cmd);
|
||||
break;
|
||||
case F_SETFD:
|
||||
case F_SETFL:
|
||||
arg = va_arg(ap, long);
|
||||
ret = __sys_fcntl(fd, cmd, arg);
|
||||
break;
|
||||
case F_GETLK:
|
||||
case F_SETLK:
|
||||
case F_SETLKW:
|
||||
lock = va_arg(ap, struct flock*);
|
||||
ret = __sys_fcntl(fd, cmd, lock);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
acl_msg_error("%s(%d), %s: unknown cmd: %d, fd: %d",
|
||||
__FILE__, __LINE__, __FUNCTION__, cmd, fd);
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
if (ret < 0)
|
||||
fiber_save_errno();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void acl_fiber_set_errno(ACL_FIBER *fiber, int errnum)
|
||||
{
|
||||
fiber->errnum = errnum;
|
||||
}
|
||||
|
||||
int acl_fiber_errno(ACL_FIBER *fiber)
|
||||
{
|
||||
fiber->flag |= FIBER_F_SAVE_ERRNO;
|
||||
return fiber->errnum;
|
||||
}
|
||||
|
||||
void fiber_save_errno(void)
|
||||
{
|
||||
ACL_FIBER *curr;
|
||||
|
||||
if (__thread_fiber == NULL)
|
||||
fiber_check();
|
||||
|
||||
if ((curr = __thread_fiber->running) == NULL)
|
||||
curr = __thread_fiber->schedule;
|
||||
|
||||
if (curr->flag & FIBER_F_SAVE_ERRNO) {
|
||||
curr->flag &= ~FIBER_F_SAVE_ERRNO;
|
||||
return;
|
||||
}
|
||||
|
||||
if (__sys_errno != NULL)
|
||||
curr->errnum = *__sys_errno();
|
||||
else
|
||||
curr->errnum = errno;
|
||||
}
|
||||
|
||||
static void fiber_swap(ACL_FIBER *from, ACL_FIBER *to)
|
||||
{
|
||||
ACL_FIBER *fiber = __thread_fiber->fiber;
|
||||
int i;
|
||||
|
||||
if (&from->uctx != &__thread_fiber->schedule->uctx) {
|
||||
ssize_t off = (char *) from->stack_top - (char *) &i + 1024;
|
||||
printf("----->fiber-%d: off: %ld, size: %ld, off: %p, %p\r\n",
|
||||
acl_fiber_id(from), off, from->size, &i,
|
||||
from->stack_top);
|
||||
assert(off > 0);
|
||||
assert(from->size);
|
||||
if (off > (ssize_t) from->size) {
|
||||
acl_myfree(from->buff);
|
||||
from->buff = (char *) acl_mycalloc(1, off);
|
||||
from->size = off;
|
||||
from->uctx.uc_stack.ss_sp = from->buff + 8;
|
||||
from->uctx.uc_stack.ss_size = from->size - 64;
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("from fiber-%d: size: %ld; to fiber-%d, size: %ld\n",
|
||||
acl_fiber_id(from), from->size,
|
||||
acl_fiber_id(to), to->size);
|
||||
|
||||
fiber->errnum = 0;
|
||||
fiber->fn = to->fn;
|
||||
fiber->arg = to->arg;
|
||||
fiber->id = to->id;
|
||||
|
||||
memcpy(&fiber->uctx, &to->uctx, sizeof(to->uctx));
|
||||
assert(fiber->size >= to->size);
|
||||
memcpy(fiber->buff, to->buff, to->size);
|
||||
fiber->uctx.uc_stack.ss_sp = fiber->buff + 8;
|
||||
fiber->uctx.uc_stack.ss_size = fiber->size - 64;
|
||||
printf("----ss_size: %ld\r\n", fiber->uctx.uc_stack.ss_size);
|
||||
|
||||
if (swapcontext(&from->uctx, &fiber->uctx) < 0)
|
||||
acl_msg_fatal("%s(%d), %s: swapcontext error %s",
|
||||
__FILE__, __LINE__, __FUNCTION__, acl_last_serror());
|
||||
}
|
||||
|
||||
ACL_FIBER *fiber_running(void)
|
||||
{
|
||||
fiber_check();
|
||||
return __thread_fiber->running;
|
||||
}
|
||||
|
||||
void fiber_exit(int exit_code)
|
||||
{
|
||||
fiber_check();
|
||||
|
||||
__thread_fiber->exitcode = exit_code;
|
||||
__thread_fiber->running->status = FIBER_STATUS_EXITING;
|
||||
|
||||
acl_fiber_switch();
|
||||
}
|
||||
|
||||
void acl_fiber_ready(ACL_FIBER *fiber)
|
||||
{
|
||||
fiber->status = FIBER_STATUS_READY;
|
||||
acl_ring_prepend(&__thread_fiber->ready, &fiber->me);
|
||||
}
|
||||
|
||||
int acl_fiber_yield(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (acl_ring_size(&__thread_fiber->ready) == 0)
|
||||
return 0;
|
||||
|
||||
n = __thread_fiber->switched;
|
||||
acl_fiber_ready(__thread_fiber->running);
|
||||
acl_fiber_switch();
|
||||
|
||||
return __thread_fiber->switched - n - 1;
|
||||
}
|
||||
|
||||
union cc_arg
|
||||
{
|
||||
void *p;
|
||||
int i[2];
|
||||
};
|
||||
|
||||
static void fiber_start(unsigned int x, unsigned int y)
|
||||
{
|
||||
union cc_arg arg;
|
||||
ACL_FIBER *fiber;
|
||||
int i;
|
||||
|
||||
arg.i[0] = x;
|
||||
arg.i[1] = y;
|
||||
|
||||
fiber = (ACL_FIBER *) arg.p;
|
||||
fiber->stack_top = &i;
|
||||
|
||||
fiber->fn(fiber, fiber->arg);
|
||||
|
||||
for (i = 0; i < fiber->nlocal; i++) {
|
||||
if (fiber->locals[i]->free_fn)
|
||||
fiber->locals[i]->free_fn(fiber->locals[i]->ctx);
|
||||
}
|
||||
|
||||
if (fiber->locals) {
|
||||
acl_myfree(fiber->locals);
|
||||
fiber->locals = NULL;
|
||||
fiber->nlocal = 0;
|
||||
}
|
||||
|
||||
fiber_exit(0);
|
||||
}
|
||||
|
||||
#define MAX_CACHE 100
|
||||
|
||||
static void fiber_free(ACL_FIBER *fiber)
|
||||
{
|
||||
acl_myfree(fiber->buff);
|
||||
acl_myfree(fiber);
|
||||
}
|
||||
|
||||
static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
|
||||
void *arg, size_t size)
|
||||
{
|
||||
ACL_FIBER *fiber;
|
||||
sigset_t zero;
|
||||
union cc_arg carg;
|
||||
ACL_RING *head;
|
||||
size_t n;
|
||||
|
||||
fiber_check();
|
||||
|
||||
n = acl_ring_size(&__thread_fiber->dead);
|
||||
if (n > MAX_CACHE) {
|
||||
n -= MAX_CACHE;
|
||||
while (n > 0) {
|
||||
head = acl_ring_pop_head(&__thread_fiber->dead);
|
||||
acl_assert(head != NULL);
|
||||
fiber = ACL_RING_TO_APPL(head, ACL_FIBER,me);
|
||||
fiber_free(fiber);
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
#define APPL ACL_RING_TO_APPL
|
||||
|
||||
head = acl_ring_pop_head(&__thread_fiber->dead);
|
||||
if (head == NULL) {
|
||||
fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER));
|
||||
fiber->buff = (char *) acl_mycalloc(1, size);
|
||||
} else if ((fiber = APPL(head, ACL_FIBER, me))->size < size) {
|
||||
acl_myfree(fiber->buff);
|
||||
fiber->buff = (char *) acl_mycalloc(1, size);
|
||||
} else
|
||||
size = fiber->size;
|
||||
|
||||
fiber->errnum = 0;
|
||||
fiber->fn = fn;
|
||||
fiber->arg = arg;
|
||||
fiber->size = size;
|
||||
fiber->id = ++__thread_fiber->idgen;
|
||||
|
||||
sigemptyset(&zero);
|
||||
sigprocmask(SIG_BLOCK, &zero, &fiber->uctx.uc_sigmask);
|
||||
|
||||
if (getcontext(&fiber->uctx) < 0)
|
||||
acl_msg_fatal("%s(%d), %s: getcontext error: %s",
|
||||
__FILE__, __LINE__, __FUNCTION__, acl_last_serror());
|
||||
|
||||
fiber->uctx.uc_stack.ss_sp = fiber->buff + 8;
|
||||
fiber->uctx.uc_stack.ss_size = fiber->size - 64;
|
||||
//fiber->uctx.uc_stack.ss_sp = fiber->buff;
|
||||
//fiber->uctx.uc_stack.ss_size = fiber->size;
|
||||
if (__thread_fiber->schedule != NULL)
|
||||
fiber->uctx.uc_link = &__thread_fiber->schedule->uctx;
|
||||
|
||||
#ifdef USE_VALGRIND
|
||||
fiber->vid = VALGRIND_STACK_REGISTER(fiber->uctx.uc_stack.ss_sp,
|
||||
fiber->uctx.uc_stack.ss_sp
|
||||
+ fiber->uctx.uc_stack.ss_size);
|
||||
#endif
|
||||
|
||||
carg.p = fiber;
|
||||
makecontext(&fiber->uctx, (void(*)(void)) fiber_start,
|
||||
2, carg.i[0], carg.i[1]);
|
||||
|
||||
return fiber;
|
||||
}
|
||||
|
||||
ACL_FIBER *acl_fiber_create(void (*fn)(ACL_FIBER *, void *), void *arg, size_t size)
|
||||
{
|
||||
ACL_FIBER *fiber = fiber_alloc(fn, arg, size);
|
||||
|
||||
__thread_fiber->count++;
|
||||
if (__thread_fiber->size % 64 == 0)
|
||||
__thread_fiber->fibers = (ACL_FIBER **) acl_myrealloc(
|
||||
__thread_fiber->fibers,
|
||||
(__thread_fiber->size + 64) * sizeof(ACL_FIBER *));
|
||||
|
||||
fiber->slot = __thread_fiber->size;
|
||||
__thread_fiber->fibers[__thread_fiber->size++] = fiber;
|
||||
acl_fiber_ready(fiber);
|
||||
|
||||
return fiber;
|
||||
}
|
||||
|
||||
int acl_fiber_id(const ACL_FIBER *fiber)
|
||||
{
|
||||
return fiber->id;
|
||||
}
|
||||
|
||||
int acl_fiber_self(void)
|
||||
{
|
||||
ACL_FIBER *curr = fiber_running();
|
||||
return acl_fiber_id(curr);
|
||||
}
|
||||
|
||||
int acl_fiber_status(const ACL_FIBER *fiber)
|
||||
{
|
||||
return fiber->status;
|
||||
}
|
||||
|
||||
static void fiber_init(void) __attribute__ ((constructor));
|
||||
|
||||
static void fiber_init(void)
|
||||
{
|
||||
static int __called = 0;
|
||||
|
||||
if (__called != 0)
|
||||
return;
|
||||
|
||||
__called++;
|
||||
|
||||
__sys_errno = (errno_fn) dlsym(RTLD_NEXT, "__errno_location");
|
||||
__sys_fcntl = (fcntl_fn) dlsym(RTLD_NEXT, "fcntl");
|
||||
|
||||
hook_io();
|
||||
hook_net();
|
||||
hook_epoll();
|
||||
}
|
||||
|
||||
void acl_fiber_schedule(void)
|
||||
{
|
||||
ACL_FIBER *fiber;
|
||||
ACL_RING *head;
|
||||
|
||||
acl_fiber_hook_api(1);
|
||||
|
||||
for (;;) {
|
||||
head = acl_ring_pop_head(&__thread_fiber->ready);
|
||||
if (head == NULL) {
|
||||
acl_msg_info("------- NO ACL_FIBER NOW --------");
|
||||
break;
|
||||
}
|
||||
|
||||
fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me);
|
||||
fiber->status = FIBER_STATUS_READY;
|
||||
|
||||
__thread_fiber->running = fiber;
|
||||
__thread_fiber->switched++;
|
||||
|
||||
fiber_swap(__thread_fiber->schedule, fiber);
|
||||
__thread_fiber->running = NULL;
|
||||
}
|
||||
|
||||
/* release dead fiber */
|
||||
while ((head = acl_ring_pop_head(&__thread_fiber->dead)) != NULL) {
|
||||
fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me);
|
||||
fiber_free(fiber);
|
||||
}
|
||||
}
|
||||
|
||||
void fiber_system(void)
|
||||
{
|
||||
if (!__thread_fiber->running->sys) {
|
||||
__thread_fiber->running->sys = 1;
|
||||
__thread_fiber->count--;
|
||||
}
|
||||
}
|
||||
|
||||
void fiber_count_inc(void)
|
||||
{
|
||||
__thread_fiber->count++;
|
||||
}
|
||||
|
||||
void fiber_count_dec(void)
|
||||
{
|
||||
__thread_fiber->count--;
|
||||
}
|
||||
|
||||
void acl_fiber_switch(void)
|
||||
{
|
||||
ACL_FIBER *fiber, *current = __thread_fiber->running;
|
||||
ACL_RING *head;
|
||||
|
||||
#ifdef _DEBUG
|
||||
acl_assert(current);
|
||||
#endif
|
||||
|
||||
if (current->status == FIBER_STATUS_EXITING) {
|
||||
size_t slot = current->slot;
|
||||
|
||||
if (!current->sys)
|
||||
__thread_fiber->count--;
|
||||
|
||||
__thread_fiber->fibers[slot] =
|
||||
__thread_fiber->fibers[--__thread_fiber->size];
|
||||
__thread_fiber->fibers[slot]->slot = slot;
|
||||
acl_ring_append(&__thread_fiber->dead, ¤t->me);
|
||||
}
|
||||
|
||||
head = acl_ring_pop_head(&__thread_fiber->ready);
|
||||
|
||||
if (head == NULL) {
|
||||
fiber_swap(current, __thread_fiber->schedule);
|
||||
return;
|
||||
}
|
||||
|
||||
fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me);
|
||||
fiber->status = FIBER_STATUS_READY;
|
||||
|
||||
__thread_fiber->running = fiber;
|
||||
__thread_fiber->switched++;
|
||||
fiber_swap(current, __thread_fiber->running);
|
||||
}
|
||||
|
||||
int acl_fiber_set_specific(void *ctx, void (*free_fn)(void *))
|
||||
{
|
||||
FIBER_LOCAL *local;
|
||||
ACL_FIBER *curr;
|
||||
int key;
|
||||
|
||||
if (__thread_fiber == NULL || __thread_fiber->running == NULL)
|
||||
return -1;
|
||||
|
||||
curr = __thread_fiber->running;
|
||||
|
||||
key = curr->nlocal;
|
||||
local = (FIBER_LOCAL *) acl_mymalloc(sizeof(FIBER_LOCAL));
|
||||
local->ctx = ctx;
|
||||
local->free_fn = free_fn;
|
||||
|
||||
if (curr->nlocal % 64 == 0)
|
||||
curr->locals = (FIBER_LOCAL **) acl_myrealloc(curr->locals,
|
||||
(curr->nlocal + 64) * sizeof(FIBER_LOCAL*));
|
||||
curr->locals[curr->nlocal++] = local;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
void *acl_fiber_get_specific(int key)
|
||||
{
|
||||
ACL_FIBER *curr;
|
||||
|
||||
if (__thread_fiber == NULL || __thread_fiber->running == NULL)
|
||||
return NULL;
|
||||
|
||||
curr = __thread_fiber->running;
|
||||
if (key >= curr->nlocal || key < 0)
|
||||
return NULL;
|
||||
|
||||
return curr->locals[key];
|
||||
}
|
128
lib_fiber/c/src/dev/fiber.h
Normal file
128
lib_fiber/c/src/dev/fiber.h
Normal file
@ -0,0 +1,128 @@
|
||||
#ifndef FIBER_INCLUDE_H
|
||||
#define FIBER_INCLUDE_H
|
||||
|
||||
#include <ucontext.h>
|
||||
#include "event.h"
|
||||
|
||||
typedef enum {
|
||||
FIBER_STATUS_READY,
|
||||
FIBER_STATUS_RUNNING,
|
||||
FIBER_STATUS_EXITING,
|
||||
} fiber_status_t;
|
||||
|
||||
typedef struct {
|
||||
void *ctx;
|
||||
void (*free_fn)(void *);
|
||||
} FIBER_LOCAL;
|
||||
|
||||
struct ACL_FIBER {
|
||||
#ifdef USE_VALGRIND
|
||||
unsigned int vid;
|
||||
#endif
|
||||
fiber_status_t status;
|
||||
ACL_RING me;
|
||||
size_t id;
|
||||
size_t slot;
|
||||
acl_int64 when;
|
||||
int errnum;
|
||||
int sys;
|
||||
unsigned int flag;
|
||||
#define FIBER_F_SAVE_ERRNO (unsigned) 1 << 0
|
||||
|
||||
FIBER_LOCAL **locals;
|
||||
int nlocal;
|
||||
|
||||
ucontext_t uctx;
|
||||
void (*fn)(ACL_FIBER *, void *);
|
||||
void *arg;
|
||||
void (*timer_fn)(ACL_FIBER *, void *);
|
||||
size_t size;
|
||||
void *stack_top;
|
||||
char *buff;
|
||||
};
|
||||
|
||||
/*
|
||||
* channel communication
|
||||
*/
|
||||
enum
|
||||
{
|
||||
CHANEND,
|
||||
CHANSND,
|
||||
CHANRCV,
|
||||
CHANNOP,
|
||||
CHANNOBLK,
|
||||
};
|
||||
|
||||
typedef struct FIBER_ALT FIBER_ALT;
|
||||
typedef struct FIBER_ALT_ARRAY FIBER_ALT_ARRAY;
|
||||
|
||||
struct FIBER_ALT {
|
||||
ACL_CHANNEL *c;
|
||||
void *v;
|
||||
unsigned int op;
|
||||
ACL_FIBER *fiber;
|
||||
FIBER_ALT *xalt;
|
||||
};
|
||||
|
||||
struct FIBER_ALT_ARRAY {
|
||||
FIBER_ALT **a;
|
||||
unsigned int n;
|
||||
unsigned int m;
|
||||
};
|
||||
|
||||
struct ACL_CHANNEL {
|
||||
unsigned int bufsize;
|
||||
unsigned int elemsize;
|
||||
unsigned char *buf;
|
||||
unsigned int nbuf;
|
||||
unsigned int off;
|
||||
FIBER_ALT_ARRAY asend;
|
||||
FIBER_ALT_ARRAY arecv;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct ACL_FIBER_MUTEX {
|
||||
ACL_FIBER *owner;
|
||||
ACL_RING waiting;
|
||||
};
|
||||
|
||||
struct ACL_FIBER_RWLOCK {
|
||||
int readers;
|
||||
ACL_FIBER *writer;
|
||||
ACL_RING rwaiting;
|
||||
ACL_RING wwaiting;
|
||||
};
|
||||
|
||||
struct ACL_FIBER_SEM {
|
||||
int num;
|
||||
ACL_RING waiting;
|
||||
};
|
||||
|
||||
/* in fiber.c */
|
||||
extern __thread int acl_var_hook_sys_api;
|
||||
|
||||
/* in fiber_schedule.c */
|
||||
ACL_FIBER *fiber_running(void);
|
||||
void fiber_save_errno(void);
|
||||
void fiber_exit(int exit_code);
|
||||
void fiber_system(void);
|
||||
void fiber_count_inc(void);
|
||||
void fiber_count_dec(void);
|
||||
|
||||
/* in fiber_io.c */
|
||||
void fiber_io_check(void);
|
||||
void fiber_io_close(int fd);
|
||||
void fiber_wait_read(int fd);
|
||||
void fiber_wait_write(int fd);
|
||||
void fiber_io_dec(void);
|
||||
void fiber_io_inc(void);
|
||||
EVENT *fiber_io_event(void);
|
||||
|
||||
/* in hook_io.c */
|
||||
void hook_io(void);
|
||||
|
||||
/* in fiber_net.c */
|
||||
void hook_net(void);
|
||||
int epoll_event_close(int epfd);
|
||||
|
||||
#endif
|
@ -23,7 +23,7 @@ typedef struct {
|
||||
size_t size;
|
||||
int exitcode;
|
||||
ACL_FIBER *running;
|
||||
ACL_FIBER schedule;
|
||||
ACL_FIBER original;
|
||||
int errnum;
|
||||
size_t idgen;
|
||||
int count;
|
||||
@ -50,7 +50,10 @@ static void thread_free(void *ctx)
|
||||
|
||||
if (tf->fibers)
|
||||
acl_myfree(tf->fibers);
|
||||
if (tf->original.context)
|
||||
acl_myfree(tf->original.context);
|
||||
acl_myfree(tf);
|
||||
|
||||
if (__main_fiber == __thread_fiber)
|
||||
__main_fiber = NULL;
|
||||
__thread_fiber = NULL;
|
||||
@ -81,6 +84,15 @@ static void fiber_check(void)
|
||||
acl_assert(acl_pthread_once(&__once_control, thread_init) == 0);
|
||||
|
||||
__thread_fiber = (FIBER_TLS *) acl_mycalloc(1, sizeof(FIBER_TLS));
|
||||
#ifdef USE_JMP
|
||||
/* set context NULL when using setjmp that setcontext will not be
|
||||
* called in fiber_swap.
|
||||
*/
|
||||
__thread_fiber->original.context = NULL;
|
||||
#else
|
||||
__thread_fiber->original.context = (ucontext_t *)
|
||||
acl_mycalloc(1, sizeof(ucontext_t));
|
||||
#endif
|
||||
__thread_fiber->fibers = NULL;
|
||||
__thread_fiber->size = 0;
|
||||
__thread_fiber->idgen = 0;
|
||||
@ -108,7 +120,7 @@ int *__errno_location(void)
|
||||
if (__thread_fiber->running)
|
||||
return &__thread_fiber->running->errnum;
|
||||
else
|
||||
return &__thread_fiber->schedule.errnum;
|
||||
return &__thread_fiber->original.errnum;
|
||||
}
|
||||
|
||||
int fcntl(int fd, int cmd, ...)
|
||||
@ -170,7 +182,7 @@ void fiber_save_errno(void)
|
||||
fiber_check();
|
||||
|
||||
if ((curr = __thread_fiber->running) == NULL)
|
||||
curr = &__thread_fiber->schedule;
|
||||
curr = &__thread_fiber->original;
|
||||
|
||||
if (curr->flag & FIBER_F_SAVE_ERRNO) {
|
||||
curr->flag &= ~FIBER_F_SAVE_ERRNO;
|
||||
@ -183,11 +195,69 @@ void fiber_save_errno(void)
|
||||
curr->errnum = errno;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define SETJMP(ctx) ({\
|
||||
int ret;\
|
||||
asm ("lea LJMPRET%=(%%rip), %%rcx\n\t"\
|
||||
"xor %%rax, %%rax\n\t"\
|
||||
"mov %%rbx, (%%rdx)\n\t"\
|
||||
"mov %%rbp, 8(%%rdx)\n\t"\
|
||||
"mov %%r12, 16(%%rdx)\n\t"\
|
||||
"mov %%rsp, 24(%%rdx)\n\t"\
|
||||
"mov %%r13, 32(%%rdx)\n\t"\
|
||||
"mov %%r14, 40(%%rdx)\n\t"\
|
||||
"mov %%r15, 48(%%rdx)\n\t"\
|
||||
"mov %%rcx, 56(%%rdx)\n\t"\
|
||||
"mov %%rdi, 64(%%rdx)\n\t"\
|
||||
"mov %%rsi, 72(%%rdx)\n\t"\
|
||||
"LJMPRET%=:\n\t"\
|
||||
: "=a" (ret)\
|
||||
: "d" (ctx) : "memory");\
|
||||
ret;\
|
||||
})
|
||||
#define LONGJMP(ctx) \
|
||||
asm("movq (%%rax), %%rbx\n\t"\
|
||||
"movq 8(%%rax), %%rbp\n\t"\
|
||||
"movq 16(%%rax), %%r12\n\t"\
|
||||
"movq 24(%%rax), %%rdx\n\t"\
|
||||
"movq 32(%%rax), %%r13\n\t"\
|
||||
"movq 40(%%rax), %%r14\n\t"\
|
||||
"mov %%rdx, %%rsp\n\t"\
|
||||
"movq 48(%%rax), %%r15\n\t"\
|
||||
"movq 56(%%rax), %%rdx\n\t"\
|
||||
"movq 64(%%rax), %%rdi\n\t"\
|
||||
"movq 72(%%rax), %%rsi\n\t"\
|
||||
"jmp *%%rdx\n\t"\
|
||||
: : "a" (ctx) : "rdx" \
|
||||
)
|
||||
#else
|
||||
#define SETJMP(ctx) \
|
||||
sigsetjmp(ctx, 0)
|
||||
#define LONGJMP(ctx) \
|
||||
siglongjmp(ctx, 1)
|
||||
#endif
|
||||
|
||||
static void fiber_swap(ACL_FIBER *from, ACL_FIBER *to)
|
||||
{
|
||||
if (swapcontext(&from->uctx, &to->uctx) < 0)
|
||||
#ifdef USE_JMP
|
||||
/* use setcontext() for the initial jump, as it allows us to set up
|
||||
* a stack, but continue with longjmp() as it's much faster.
|
||||
*/
|
||||
if (SETJMP(from->jbuf) == 0) {
|
||||
/* context just be used once for set up a stack, which will
|
||||
* be freed in fiber_start. The context in __thread_fiber
|
||||
* was set NULL.
|
||||
*/
|
||||
if (to->context != NULL)
|
||||
setcontext(to->context);
|
||||
else
|
||||
LONGJMP(to->jbuf);
|
||||
}
|
||||
#else
|
||||
if (swapcontext(from->context, to->context) < 0)
|
||||
acl_msg_fatal("%s(%d), %s: swapcontext error %s",
|
||||
__FILE__, __LINE__, __FUNCTION__, acl_last_serror());
|
||||
#endif
|
||||
}
|
||||
|
||||
ACL_FIBER *fiber_running(void)
|
||||
@ -243,6 +313,14 @@ static void fiber_start(unsigned int x, unsigned int y)
|
||||
|
||||
fiber = (ACL_FIBER *) arg.p;
|
||||
|
||||
#ifdef USE_JMP
|
||||
/* when using setjmp/longjmp, the context just be used only once */
|
||||
if (fiber->context != NULL) {
|
||||
acl_myfree(fiber->context);
|
||||
fiber->context = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
fiber->fn(fiber, fiber->arg);
|
||||
|
||||
for (i = 0; i < fiber->nlocal; i++) {
|
||||
@ -261,9 +339,11 @@ static void fiber_start(unsigned int x, unsigned int y)
|
||||
|
||||
#define MAX_CACHE 100
|
||||
|
||||
static void fiber_free(FIBER_TLS *tls, ACL_FIBER *fiber)
|
||||
static void fiber_free(ACL_FIBER *fiber)
|
||||
{
|
||||
(void) tls;
|
||||
if (fiber->context)
|
||||
acl_myfree(fiber->context);
|
||||
acl_myfree(fiber->buff);
|
||||
acl_myfree(fiber);
|
||||
}
|
||||
|
||||
@ -279,58 +359,70 @@ static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *),
|
||||
fiber_check();
|
||||
|
||||
n = acl_ring_size(&__thread_fiber->dead);
|
||||
|
||||
/* if the cached dead fibers reached the limit, some will be freed */
|
||||
if (n > MAX_CACHE) {
|
||||
n -= MAX_CACHE;
|
||||
while (n > 0) {
|
||||
head = acl_ring_pop_head(&__thread_fiber->dead);
|
||||
acl_assert(head != NULL);
|
||||
fiber = ACL_RING_TO_APPL(head, ACL_FIBER,me);
|
||||
fiber_free(__thread_fiber, fiber);
|
||||
fiber_free(fiber);
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
#define APPL ACL_RING_TO_APPL
|
||||
|
||||
/* try to reuse the fiber memory in dead queue */
|
||||
head = acl_ring_pop_head(&__thread_fiber->dead);
|
||||
if (head == NULL)
|
||||
fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER) + size);
|
||||
else if ((fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me))->size < size) {
|
||||
fiber_free(__thread_fiber, fiber);
|
||||
fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER) + size);
|
||||
} else
|
||||
if (head == NULL) {
|
||||
fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER));
|
||||
fiber->buff = (char *) acl_mycalloc(1, size);
|
||||
} else if ((fiber = APPL(head, ACL_FIBER, me))->size < size)
|
||||
fiber->buff = (char *) acl_myrealloc(fiber->buff, size);
|
||||
else
|
||||
size = fiber->size;
|
||||
|
||||
fiber->errnum = 0;
|
||||
fiber->fn = fn;
|
||||
fiber->arg = arg;
|
||||
fiber->stack = fiber->buf;
|
||||
fiber->size = size;
|
||||
fiber->id = ++__thread_fiber->idgen;
|
||||
|
||||
sigemptyset(&zero);
|
||||
sigprocmask(SIG_BLOCK, &zero, &fiber->uctx.uc_sigmask);
|
||||
carg.p = fiber;
|
||||
|
||||
if (getcontext(&fiber->uctx) < 0)
|
||||
fiber->context = (ucontext_t *) acl_mymalloc(sizeof(ucontext_t));
|
||||
sigemptyset(&zero);
|
||||
sigprocmask(SIG_BLOCK, &zero, &fiber->context->uc_sigmask);
|
||||
|
||||
if (getcontext(fiber->context) < 0)
|
||||
acl_msg_fatal("%s(%d), %s: getcontext error: %s",
|
||||
__FILE__, __LINE__, __FUNCTION__, acl_last_serror());
|
||||
|
||||
fiber->uctx.uc_stack.ss_sp = fiber->stack + 8;
|
||||
fiber->uctx.uc_stack.ss_size = fiber->size - 64;
|
||||
fiber->uctx.uc_link = &__thread_fiber->schedule.uctx;
|
||||
fiber->context->uc_stack.ss_sp = fiber->buff + 8;
|
||||
fiber->context->uc_stack.ss_size = fiber->size - 64;
|
||||
|
||||
#ifdef USE_VALGRIND
|
||||
fiber->vid = VALGRIND_STACK_REGISTER(fiber->uctx.uc_stack.ss_sp,
|
||||
fiber->uctx.uc_stack.ss_sp
|
||||
+ fiber->uctx.uc_stack.ss_size);
|
||||
#ifdef USE_JMP
|
||||
fiber->context->uc_link = NULL;
|
||||
#else
|
||||
fiber->context->uc_link = __thread_fiber->original.context;
|
||||
#endif
|
||||
|
||||
carg.p = fiber;
|
||||
makecontext(&fiber->uctx, (void(*)(void)) fiber_start,
|
||||
#ifdef USE_VALGRIND
|
||||
/* avoding the valgrind's warning */
|
||||
fiber->vid = VALGRIND_STACK_REGISTER(fiber->context->uc_stack.ss_sp,
|
||||
fiber->context.uc_stack.ss_sp
|
||||
+ fiber->init_context.uc_stack.ss_size);
|
||||
#endif
|
||||
makecontext(fiber->context, (void(*)(void)) fiber_start,
|
||||
2, carg.i[0], carg.i[1]);
|
||||
|
||||
return fiber;
|
||||
}
|
||||
|
||||
ACL_FIBER *acl_fiber_create(void (*fn)(ACL_FIBER *, void *), void *arg, size_t size)
|
||||
ACL_FIBER *acl_fiber_create(void (*fn)(ACL_FIBER *, void *),
|
||||
void *arg, size_t size)
|
||||
{
|
||||
ACL_FIBER *fiber = fiber_alloc(fn, arg, size);
|
||||
|
||||
@ -402,15 +494,17 @@ void acl_fiber_schedule(void)
|
||||
__thread_fiber->running = fiber;
|
||||
__thread_fiber->switched++;
|
||||
|
||||
fiber_swap(&__thread_fiber->schedule, fiber);
|
||||
fiber_swap(&__thread_fiber->original, fiber);
|
||||
__thread_fiber->running = NULL;
|
||||
}
|
||||
|
||||
/* release dead fiber */
|
||||
while ((head = acl_ring_pop_head(&__thread_fiber->dead)) != NULL) {
|
||||
fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me);
|
||||
fiber_free(__thread_fiber, fiber);
|
||||
fiber_free(fiber);
|
||||
}
|
||||
|
||||
acl_fiber_hook_api(0);
|
||||
}
|
||||
|
||||
void fiber_system(void)
|
||||
@ -455,7 +549,7 @@ void acl_fiber_switch(void)
|
||||
head = acl_ring_pop_head(&__thread_fiber->ready);
|
||||
|
||||
if (head == NULL) {
|
||||
fiber_swap(current, &__thread_fiber->schedule);
|
||||
fiber_swap(current, &__thread_fiber->original);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define FIBER_INCLUDE_H
|
||||
|
||||
#include <ucontext.h>
|
||||
#include <setjmp.h>
|
||||
#include "event.h"
|
||||
|
||||
typedef enum {
|
||||
@ -32,13 +33,15 @@ struct ACL_FIBER {
|
||||
FIBER_LOCAL **locals;
|
||||
int nlocal;
|
||||
|
||||
ucontext_t uctx;
|
||||
#ifdef USE_JMP
|
||||
jmp_buf jbuf;
|
||||
#endif
|
||||
ucontext_t *context;
|
||||
void (*fn)(ACL_FIBER *, void *);
|
||||
void *arg;
|
||||
char *stack;
|
||||
size_t size;
|
||||
void (*timer_fn)(ACL_FIBER *, void *);
|
||||
char buf[1];
|
||||
size_t size;
|
||||
char *buff;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -233,7 +233,6 @@ ssize_t read(int fd, void *buf, size_t count)
|
||||
event_clear_readable(ev, fd);
|
||||
|
||||
ret = __sys_read(fd, buf, count);
|
||||
//printf("---read ret: %ld----\r\n", ret);
|
||||
if (ret > 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
19) 2016.8.10
|
||||
19.1) performance&feature: 允许使用 setjmp/longjmp 进行栈的跳转,性能更好
|
||||
|
||||
18) 2016.8.7
|
||||
18.1) feature: fiber.c 中在 acl_fiber_schedule 结束前自动将 acl_var_hook_sys_api
|
||||
置 0,从而恢复系统 API 调用过程
|
||||
|
||||
17) 2016.8.5
|
||||
17.1) feature: hook_io.c 中增加系统 API sleep 的 hook 函数
|
||||
|
202
lib_fiber/cxx/Makefile
Normal file
202
lib_fiber/cxx/Makefile
Normal file
@ -0,0 +1,202 @@
|
||||
SHELL = /bin/sh
|
||||
#CC = g++
|
||||
CC = ${ENV_CPP}
|
||||
AR = ${ENV_AR}
|
||||
ARFL = rv
|
||||
#ARFL = cru
|
||||
RANLIB = ${ENV_RANLIB}
|
||||
|
||||
FLAGS = ${ENV_FLAGS}
|
||||
|
||||
CFLAGS = -c -g -W \
|
||||
-O3 \
|
||||
-Wall \
|
||||
-Wpointer-arith \
|
||||
-Wshadow \
|
||||
-D_REENTRANT \
|
||||
-D_POSIX_PTHREAD_SEMANTICS \
|
||||
-Wno-long-long \
|
||||
-Wformat \
|
||||
-Winvalid-pch \
|
||||
-DACL_PREPARE_COMPILE
|
||||
#-DUSE_DYNAMIC
|
||||
# -Wcast-align
|
||||
#-Wcast-qual
|
||||
#just for freebsd's iconv.h
|
||||
CFLAGS += -I/usr/local/include
|
||||
|
||||
shared_ldflags = -l_acl_cpp -l_protocol -l_acl -lz -lpthread
|
||||
|
||||
###########################################################
|
||||
#Check system:
|
||||
# Linux, SunOS, Solaris, BSD variants, AIX, HP-UX
|
||||
SYSLIB =
|
||||
CHECKSYSRES = @echo "Unknow system type!";exit 1
|
||||
UNIXNAME = $(shell uname -sm)
|
||||
UNIXTYPE = LINUX
|
||||
|
||||
ifeq ($(CC),)
|
||||
CC = g++
|
||||
endif
|
||||
|
||||
ifeq ($(AR),)
|
||||
AR = ar
|
||||
endif
|
||||
|
||||
ifeq ($(RANLIB),)
|
||||
RANLIB = ranlib
|
||||
endif
|
||||
|
||||
ifeq ($(findstring clang++, $(CC)), clang++)
|
||||
CFLAGS += -Wno-invalid-source-encoding \
|
||||
-Wno-extended-offsetof
|
||||
endif
|
||||
|
||||
# For FreeBSD
|
||||
ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD)
|
||||
CFLAGS += -DFREEBSD -fPIC -Werror
|
||||
UNIXTYPE = FREEBSD
|
||||
shared_ldflags = -l_acl_cpp -l_protocol -l_acl -L/usr/local/lib -liconv -lz -lpthread
|
||||
endif
|
||||
|
||||
# For Darwin
|
||||
ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin)
|
||||
CFLAGS += -DMACOSX -Wno-invalid-source-encoding \
|
||||
-Wno-extended-offsetof -fPIC -Werror \
|
||||
-Wno-unused-private-field
|
||||
UNIXTYPE = MACOSX
|
||||
shared_ldflags = -l_acl_cpp -l_protocol -l_acl -L/usr/lib -liconv -lz -lpthread
|
||||
endif
|
||||
|
||||
# For Linux
|
||||
ifeq ($(findstring Linux, $(UNIXNAME)), Linux)
|
||||
CFLAGS += -DLINUX2 -fPIC -Werror
|
||||
UNIXTYPE = LINUX
|
||||
shared_ldflags = -l_acl_cpp -l_protocol -l_acl -lrt -lpthread -lz -ldl
|
||||
endif
|
||||
|
||||
# For MINGW
|
||||
ifeq ($(findstring MINGW, $(UNIXNAME)), MINGW)
|
||||
CFLAGS += -DLINUX2 -DMINGW
|
||||
UNIXTYPE = LINUX
|
||||
endif
|
||||
|
||||
# For SunOS
|
||||
ifeq ($(findstring SunOS, $(UNIXNAME)), SunOS)
|
||||
ifeq ($(findstring 86, $(UNIXNAME)), 86)
|
||||
SYSLIB = -lsocket -lnsl -lrt
|
||||
endif
|
||||
ifeq ($(findstring sun4u, $(UNIXNAME)), sun4u)
|
||||
SYSLIB = -lsocket -lnsl -lrt
|
||||
endif
|
||||
CFLAGS += -DSUNOS5 -fPIC -Werror
|
||||
UNIXTYPE = SUNOS5
|
||||
endif
|
||||
|
||||
# For HP-UX
|
||||
ifeq ($(findstring HP-UX, $(UNIXNAME)), HP-UX)
|
||||
CFLAGS += -DHP_UX -DHPUX11 -fPIC -Werror
|
||||
UNIXTYPE = HPUX
|
||||
endif
|
||||
|
||||
#Find system type.
|
||||
ifneq ($(SYSPATH),)
|
||||
CHECKSYSRES = @echo "System is $(shell uname -sm)"
|
||||
endif
|
||||
###########################################################
|
||||
|
||||
OBJ_PATH_DST = ./debug
|
||||
LIB_PATH_DST = ../lib
|
||||
DEF_PATH_DST = ./debug
|
||||
|
||||
CFLAGS += -I./src -I../c/include -I./include -I../../lib_acl/include -I../../lib_acl_cpp/include
|
||||
|
||||
#Project's objs
|
||||
|
||||
OBJS_DST = $(patsubst %.cpp, $(OBJ_PATH_DST)/%.o, $(notdir $(wildcard src/*.cpp)))
|
||||
OBJS_DEF = $(patsubst %.cpp, $(DEF_PATH_DST)/%.inc, $(notdir $(wildcard src/*.cpp)))
|
||||
|
||||
###########################################################
|
||||
.PHONY = static shared clean
|
||||
VERSION = 0.9
|
||||
DATE_NOW = 20`date +%y`.`date +%m`.`date +%d`
|
||||
|
||||
STATIC_LIBNAME = lib_fiber_cpp.a
|
||||
SHARED_LIBNAME = lib_fiber_cpp.so
|
||||
PCH = ./acl_stdafx.hpp.gch
|
||||
|
||||
lib: static
|
||||
all: static shared sample
|
||||
|
||||
$(shell mkdir -p $(DEF_PATH_DST))
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(OBJS_DEF)
|
||||
endif
|
||||
|
||||
COMPILE = $(CC) $(CFLAGS)
|
||||
COMPILE_OBJ = @(echo 'building $<'; $(COMPILE) $< -o $@)
|
||||
CREATE_DEF = @(echo 'creating $@'; rm -f $@; \
|
||||
$(COMPILE) -MM $< > $@.$$$$; \
|
||||
sed 's,.*.o\( \)*:,$(patsubst %.inc,%.o,$@) $@ :,g' < $@.$$$$ > $@; \
|
||||
rm -f $@.$$$$)
|
||||
|
||||
###########################################################
|
||||
|
||||
sample: static
|
||||
@(cd samples; make)
|
||||
|
||||
static: depends $(OBJS_DST)
|
||||
@echo 'creating $(LIB_PATH_DST)/$(STATIC_LIBNAME)'
|
||||
@$(AR) $(ARFL) $(LIB_PATH_DST)/$(STATIC_LIBNAME) $(OBJS_DST)
|
||||
@$(RANLIB) $(LIB_PATH_DST)/$(STATIC_LIBNAME)
|
||||
@echo 'create $(LIB_PATH_DST)/$(STATIC_LIBNAME) ok!'
|
||||
|
||||
shared: depends pch $(OBJS_DST)
|
||||
@echo 'creating $(SHARED_LIBNAME)'
|
||||
@if test -n "$(rpath)" && test "$(UNIXTYPE)" = "LINUX"; then \
|
||||
echo "building for linux"; \
|
||||
$(CC) -shared -o $(rpath)/$(SHARED_LIBNAME) $(OBJS_DST) \
|
||||
-L$(rpath) $(shared_ldflags) -Wl,-rpath,$(rpath); \
|
||||
echo 'build $(rpath)/$(SHARED_LIBNAME) ok!'; \
|
||||
elif test -n "$(rpath)" && test "$(UNIXTYPE)" = "SUNOS5"; then \
|
||||
echo "building for sunos5"; \
|
||||
$(CC) -shared -o $(rpath)/$(SHARED_LIBNAME) $(OBJS_DST) \
|
||||
-R$(rpath) -L$(rpath) $(shared_ldflags); \
|
||||
echo 'build $(rpath)/$(SHARED_LIBNAME) ok!'; \
|
||||
elif test -n "$(rpath)" && test "$(UNIXTYPE)" = "MACOSX"; then \
|
||||
echo "building for Darwin"; \
|
||||
$(CC) -shared -o $(rpath)/$(SHARED_LIBNAME) $(OBJS_DST) \
|
||||
-R$(rpath) -L$(rpath) $(shared_ldflags); \
|
||||
echo 'build $(rpath)/$(SHARED_LIBNAME) ok!'; \
|
||||
elif test -n "$(rpath)" && test "$(UNIXTYPE)" = "FREEBSD"; then \
|
||||
echo "building for Darwin"; \
|
||||
$(CC) -shared -o $(rpath)/$(SHARED_LIBNAME) $(OBJS_DST) \
|
||||
-R$(rpath) -L$(rpath) $(shared_ldflags); \
|
||||
echo 'build $(rpath)/$(SHARED_LIBNAME) ok!'; \
|
||||
else \
|
||||
echo 'skip build $(SHARED_LIBNAME); usage: make shared rpath=xxx'; \
|
||||
fi
|
||||
|
||||
depends: $(OBJS_DEF)
|
||||
pch: ./acl_stdafx.hpp
|
||||
rm -f $(PCH)
|
||||
@if test "$(UNIXTYPE)" = "LINUX" || test "$(UNIXTYPE)" = "FREEBSD" \
|
||||
|| test "$(UNIXTYPE)" = "MACOSX"; then \
|
||||
$(CC) -o $(PCH) -x c++-header $(CFLAGS) src/acl_stdafx.hpp; \
|
||||
fi
|
||||
|
||||
# src
|
||||
$(OBJ_PATH_DST)/%.o: ./src/%.cpp
|
||||
$(COMPILE_OBJ)
|
||||
|
||||
$(DEF_PATH_DST)/%.inc: ./src/%.cpp
|
||||
$(CREATE_DEF)
|
||||
|
||||
clean:
|
||||
rm -f $(LIB_PATH_DST)/lib_fiber_cpp.a
|
||||
rm -f $(LIB_PATH_DST)/lib_fiber_cpp.so
|
||||
rm -f $(OBJS_DST)
|
||||
rm -f $(OBJS_DEF)
|
||||
rm -f $(PCH)
|
||||
|
||||
rebuild rb: clean static
|
1
lib_fiber/cxx/README.md
Normal file
1
lib_fiber/cxx/README.md
Normal file
@ -0,0 +1 @@
|
||||
using c++1x
|
1
lib_fiber/cxx/debug/keep
Normal file
1
lib_fiber/cxx/debug/keep
Normal file
@ -0,0 +1 @@
|
||||
keepme
|
1
lib_fiber/cxx/include/keep
Normal file
1
lib_fiber/cxx/include/keep
Normal file
@ -0,0 +1 @@
|
||||
keepme
|
1
lib_fiber/cxx/keep
Normal file
1
lib_fiber/cxx/keep
Normal file
@ -0,0 +1 @@
|
||||
keepme
|
1
lib_fiber/cxx/src/keep
Normal file
1
lib_fiber/cxx/src/keep
Normal file
@ -0,0 +1 @@
|
||||
keepme
|
@ -92,7 +92,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
acl_foreach(iter, tokens) {
|
||||
char* addr = (char* ) iter.data;
|
||||
acl_fiber_create(nslookup, addr, 8192);
|
||||
acl_fiber_create(nslookup, addr, 32000);
|
||||
}
|
||||
|
||||
acl_fiber_schedule();
|
||||
|
@ -8,17 +8,31 @@
|
||||
|
||||
static int __max_loop = 1000;
|
||||
static int __max_fiber = 1000;
|
||||
static int __display = 0;
|
||||
|
||||
static __thread struct timeval __begin;
|
||||
static __thread int __left_fiber = 1000;
|
||||
|
||||
static void stack_dummy(ACL_FIBER *fiber acl_unused)
|
||||
{
|
||||
char buf[81920];
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
}
|
||||
|
||||
static void fiber_main(ACL_FIBER *fiber, void *ctx acl_unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (0)
|
||||
stack_dummy(fiber);
|
||||
|
||||
errno = acl_fiber_errno(fiber);
|
||||
for (i = 0; i < __max_loop; i++) {
|
||||
acl_fiber_yield();
|
||||
if (!__display)
|
||||
continue;
|
||||
|
||||
if (i <= 2)
|
||||
printf("fiber-%d, errno: %d\r\n",
|
||||
acl_fiber_id(fiber), errno);
|
||||
@ -55,7 +69,7 @@ static void *thread_main(void *ctx acl_unused)
|
||||
|
||||
static void usage(const char *procname)
|
||||
{
|
||||
printf("usage: %s -h [help] -n max_loop -c max_fiber -t max_threads\r\n", procname);
|
||||
printf("usage: %s -h [help] -n max_loop -c max_fiber -t max_threads -e [if display]\r\n", procname);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@ -64,7 +78,7 @@ int main(int argc, char *argv[])
|
||||
acl_pthread_attr_t attr;
|
||||
acl_pthread_t *tids;
|
||||
|
||||
while ((ch = getopt(argc, argv, "hn:c:t:")) > 0) {
|
||||
while ((ch = getopt(argc, argv, "hn:c:t:e")) > 0) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
@ -80,6 +94,9 @@ int main(int argc, char *argv[])
|
||||
if (nthreads <= 0)
|
||||
nthreads = 1;
|
||||
break;
|
||||
case 'e':
|
||||
__display = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ static void http_server(ACL_FIBER *, void *ctx)
|
||||
delete conn;
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (ssl->handshake() == false)
|
||||
{
|
||||
printf("ssl handshake error\r\n");
|
||||
@ -34,11 +36,14 @@ static void http_server(ACL_FIBER *, void *ctx)
|
||||
}
|
||||
if (ssl->handshake_ok() == false)
|
||||
{
|
||||
printf("ssl handshake_ok error\r\n");
|
||||
printf("ssl handshake error\r\n");
|
||||
ssl->destroy();
|
||||
delete conn;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("ssl handshake_ok\r\n");
|
||||
|
||||
acl::memcache_session session("127.0.0.1:11211");
|
||||
http_servlet servlet(conn, &session);
|
||||
|
74
lib_fiber/samples/ping/benchmark.sh
Normal file
74
lib_fiber/samples/ping/benchmark.sh
Normal file
@ -0,0 +1,74 @@
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
./ping -d 0 -n 100 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
||||
127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \
|
@ -5,6 +5,8 @@
|
||||
|
||||
static int __nfibers = 0;
|
||||
static int __npkt = 10;
|
||||
static int __delay_seconds = 1; /* 发送 ping 包的时间间隔(秒)*/
|
||||
static int __benchmark = 0;
|
||||
|
||||
static void display_res(ICMP_CHAT *chat)
|
||||
{
|
||||
@ -21,7 +23,6 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg)
|
||||
const char *dest = (const char *) arg;
|
||||
ACL_DNS_DB* dns_db;
|
||||
const char *ip;
|
||||
int delay = 1; /* 发送 ping 包的时间间隔(秒)*/
|
||||
ICMP_CHAT *chat;
|
||||
|
||||
/* 通过域名解析出IP地址 */
|
||||
@ -44,9 +45,9 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg)
|
||||
|
||||
/* 开始 PING */
|
||||
if (strcmp(dest, ip) == 0)
|
||||
icmp_ping_one(chat, NULL, ip, __npkt, delay, 1);
|
||||
icmp_ping_one(chat, NULL, ip, __npkt, __delay_seconds, 1);
|
||||
else
|
||||
icmp_ping_one(chat, dest, ip, __npkt, delay, 1);
|
||||
icmp_ping_one(chat, dest, ip, __npkt, __delay_seconds, 1);
|
||||
|
||||
acl_netdb_free(dns_db); /* 释放域名解析对象 */
|
||||
display_res(chat); /* 显示 PING 结果 */
|
||||
@ -58,8 +59,12 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg)
|
||||
|
||||
static void usage(const char* progname)
|
||||
{
|
||||
printf("usage: %s [-h help] [-n npkt] [\"dest1 dest2 dest3...\"]\r\n",
|
||||
progname);
|
||||
printf("usage: %s -h help\r\n"
|
||||
" -d delay\r\n"
|
||||
" -z stack_size\r\n"
|
||||
" -b benchmark [if > 0 dest will be ignored]\r\n"
|
||||
" -n npkt dest1 dest2...\r\n", progname);
|
||||
|
||||
printf("example: %s -n 10 www.sina.com.cn www.qq.com\r\n", progname);
|
||||
}
|
||||
|
||||
@ -72,12 +77,12 @@ static void on_sigint(int signo acl_unused)
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char ch;
|
||||
int i;
|
||||
int i, stack_size = 16000;
|
||||
|
||||
signal(SIGINT, on_sigint); /* 用户按下 ctr + c 时中断 PING 程序 */
|
||||
acl_msg_stdout_enable(1); /* 允许 acl_msg_xxx 记录的信息输出至屏幕 */
|
||||
|
||||
while ((ch = getopt(argc, argv, "hn:")) > 0) {
|
||||
while ((ch = getopt(argc, argv, "hn:d:z:b:")) > 0) {
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
__npkt = atoi(optarg);
|
||||
@ -85,24 +90,42 @@ int main(int argc, char* argv[])
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
case 'z':
|
||||
stack_size = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
__delay_seconds = atoi(optarg);
|
||||
break;
|
||||
case 'b':
|
||||
__benchmark = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (__npkt <= 0)
|
||||
__npkt = 10;
|
||||
|
||||
/* 记录要启动的协程的总数 */
|
||||
__nfibers = argc - optind;
|
||||
if (__benchmark > 0) {
|
||||
static char *localhost = "127.0.0.1";
|
||||
|
||||
for (i = optind; i < argc; i++)
|
||||
acl_fiber_create(fiber_ping, argv[i], 32000);
|
||||
__nfibers = __benchmark;
|
||||
|
||||
for (i = 0; i < __benchmark; i++)
|
||||
acl_fiber_create(fiber_ping, localhost, stack_size);
|
||||
} else {
|
||||
if (optind == argc) {
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 记录要启动的协程的总数 */
|
||||
__nfibers = argc - optind;
|
||||
|
||||
for (i = optind; i < argc; i++)
|
||||
acl_fiber_create(fiber_ping, argv[i], stack_size);
|
||||
}
|
||||
|
||||
acl_fiber_schedule();
|
||||
|
||||
|
3
lib_fiber/samples/ssl_client/Makefile
Normal file
3
lib_fiber/samples/ssl_client/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
include ../Makefile_cpp.in
|
||||
EXTLIBS = -L../../../lib/linux64 -lpolarssl
|
||||
PROG = client
|
198
lib_fiber/samples/ssl_client/main.cpp
Normal file
198
lib_fiber/samples/ssl_client/main.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
#include "stdafx.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "stamp.h"
|
||||
|
||||
#define STACK_SIZE 32000
|
||||
|
||||
static int __rw_timeout = 0;
|
||||
static int __conn_timeout = 0;
|
||||
static int __max_fibers = 100;
|
||||
static int __left_fibers = 100;
|
||||
static int __max_loop = 100;
|
||||
static struct timeval __begin;
|
||||
|
||||
static acl::polarssl_conf *__ssl_conf = NULL;
|
||||
static bool __check_ssl = false;
|
||||
|
||||
static long long int __total_count = 0;
|
||||
static int __total_clients = 0;
|
||||
static int __total_error_clients = 0;
|
||||
|
||||
static bool ssl_init(acl::socket_stream& conn)
|
||||
{
|
||||
assert(__ssl_conf);
|
||||
|
||||
acl::polarssl_io* ssl = new acl::polarssl_io(*__ssl_conf, false);
|
||||
|
||||
if (conn.setup_hook(ssl) == ssl)
|
||||
{
|
||||
printf("setup_hook error\r\n");
|
||||
ssl->destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!__check_ssl)
|
||||
{
|
||||
printf("ssl handshake_ok\r\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ssl->handshake() == false)
|
||||
{
|
||||
printf("ssl handshake error\r\n");
|
||||
ssl->destroy();
|
||||
return false;
|
||||
}
|
||||
if (ssl->handshake_ok() == false)
|
||||
{
|
||||
printf("ssl handshake error\r\n");
|
||||
ssl->destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("ssl handshake_ok\r\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void run(const char* addr)
|
||||
{
|
||||
acl::socket_stream conn;
|
||||
|
||||
if (conn.open(addr, __conn_timeout, __rw_timeout) == false)
|
||||
{
|
||||
printf("connect %s error %s\r\n", addr, acl::last_serror());
|
||||
__total_error_clients++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (__ssl_conf != NULL && ssl_init(conn) == false)
|
||||
return;
|
||||
|
||||
__total_clients++;
|
||||
printf("fiber-%d: connect %s ok, clients: %d, fd: %d\r\n",
|
||||
acl_fiber_self(), addr, __total_clients, conn.sock_handle());
|
||||
|
||||
acl::string buf;
|
||||
const char req[] = "hello world\r\n";
|
||||
|
||||
for (int i = 0; i < __max_loop; i++)
|
||||
{
|
||||
if (conn.write(req, sizeof(req) - 1) == -1)
|
||||
{
|
||||
printf("write error: %s\r\n", acl::last_serror());
|
||||
break;
|
||||
}
|
||||
|
||||
if (conn.gets(buf, false) == false)
|
||||
{
|
||||
printf("gets error: %s\r\n", acl::last_serror());
|
||||
break;
|
||||
}
|
||||
buf.clear();
|
||||
__total_count++;
|
||||
}
|
||||
|
||||
printf("close one connection: %d, %s\r\n",
|
||||
conn.sock_handle(), acl::last_serror());
|
||||
}
|
||||
|
||||
static void fiber_connect(ACL_FIBER *fiber acl_unused, void *ctx)
|
||||
{
|
||||
const char *addr = (const char *) ctx;
|
||||
|
||||
run(addr);
|
||||
|
||||
--__left_fibers;
|
||||
printf("max_fibers: %d, left: %d\r\n", __max_fibers, __left_fibers);
|
||||
|
||||
if (__left_fibers == 0) {
|
||||
double spent;
|
||||
struct timeval end;
|
||||
|
||||
gettimeofday(&end, NULL);
|
||||
spent = stamp_sub(&end, &__begin);
|
||||
|
||||
printf("fibers: %d, clients: %d, error: %d, count: %lld, "
|
||||
"spent: %.2f, speed: %.2f\r\n", __max_fibers,
|
||||
__total_clients, __total_error_clients,
|
||||
__total_count, spent,
|
||||
(__total_count * 1000) / (spent > 0 ? spent : 1));
|
||||
|
||||
acl_fiber_stop();
|
||||
}
|
||||
}
|
||||
|
||||
static void fiber_main(ACL_FIBER *fiber acl_unused, void *ctx)
|
||||
{
|
||||
char *addr = (char *) ctx;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < __max_fibers; i++)
|
||||
{
|
||||
acl_fiber_create(fiber_connect, addr, 32768);
|
||||
//acl_fiber_sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(const char* procname)
|
||||
{
|
||||
printf("usage: %s -h [help]\r\n"
|
||||
" -s listen_addr\r\n"
|
||||
" -r rw_timeout\r\n"
|
||||
" -c max_fibers\r\n"
|
||||
" -C [if check ssl status]\r\n"
|
||||
" -n max_loop\r\n", procname);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
acl::string addr("127.0.0.1:9001");
|
||||
bool use_ssl = true;
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "hs:r:Pc:n:C")) > 0)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
case 's':
|
||||
addr = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
__rw_timeout = atoi(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
use_ssl = false;
|
||||
break;
|
||||
case 'c':
|
||||
__max_fibers = atoi(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
__max_loop = atoi(optarg);
|
||||
break;
|
||||
case 'C':
|
||||
__check_ssl = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
acl::acl_cpp_init();
|
||||
acl::log::stdout_open(true);
|
||||
|
||||
if (use_ssl)
|
||||
__ssl_conf = new acl::polarssl_conf;
|
||||
|
||||
gettimeofday(&__begin, NULL);
|
||||
acl_fiber_create(fiber_main, addr.c_str(), 32768);
|
||||
|
||||
acl_fiber_schedule();
|
||||
|
||||
delete __ssl_conf;
|
||||
|
||||
return 0;
|
||||
}
|
8
lib_fiber/samples/ssl_client/stdafx.cpp
Normal file
8
lib_fiber/samples/ssl_client/stdafx.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
||||
// master_threads.pch 将成为预编译头
|
||||
// stdafx.obj 将包含预编译类型信息
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 在 STDAFX.H 中
|
||||
//引用任何所需的附加头文件,而不是在此文件中引用
|
20
lib_fiber/samples/ssl_client/stdafx.h
Normal file
20
lib_fiber/samples/ssl_client/stdafx.h
Normal file
@ -0,0 +1,20 @@
|
||||
// stdafx.h : 标准系统包含文件的包含文件,
|
||||
// 或是常用但不常更改的项目特定的包含文件
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//#include <iostream>
|
||||
//#include <tchar.h>
|
||||
|
||||
// TODO: 在此处引用程序要求的附加头文件
|
||||
|
||||
#include "lib_acl.h"
|
||||
#include "fiber/lib_fiber.h"
|
||||
#include "acl_cpp/lib_acl.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
3
lib_fiber/samples/ssl_server/Makefile
Normal file
3
lib_fiber/samples/ssl_server/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
include ../Makefile_cpp.in
|
||||
EXTLIBS = -L../../../lib/linux64 -lpolarssl
|
||||
PROG = server
|
185
lib_fiber/samples/ssl_server/main.cpp
Normal file
185
lib_fiber/samples/ssl_server/main.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
#include "stdafx.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define STACK_SIZE 32000
|
||||
|
||||
static int __rw_timeout = 0;
|
||||
static acl::string __ssl_crt("../ssl_crt.pem");
|
||||
static acl::string __ssl_key("../ssl_key.pem");
|
||||
static acl::polarssl_conf *__ssl_conf = NULL;
|
||||
static bool __check_ssl = false;
|
||||
|
||||
static void http_server(ACL_FIBER *, void *ctx)
|
||||
{
|
||||
acl::socket_stream *conn = (acl::socket_stream *) ctx;
|
||||
|
||||
printf("start one server\r\n");
|
||||
|
||||
if (__ssl_conf != NULL)
|
||||
{
|
||||
acl::polarssl_io* ssl =
|
||||
new acl::polarssl_io(*__ssl_conf, true, false);
|
||||
|
||||
if (conn->setup_hook(ssl) == ssl)
|
||||
{
|
||||
printf("setup_hook error\r\n");
|
||||
ssl->destroy();
|
||||
delete conn;
|
||||
return;
|
||||
}
|
||||
|
||||
if (__check_ssl)
|
||||
{
|
||||
if (ssl->handshake() == false)
|
||||
{
|
||||
printf("ssl handshake error\r\n");
|
||||
ssl->destroy();
|
||||
delete conn;
|
||||
return;
|
||||
}
|
||||
if (ssl->handshake_ok() == false)
|
||||
{
|
||||
printf("ssl handshake error\r\n");
|
||||
ssl->destroy();
|
||||
delete conn;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("ssl handshake_ok\r\n");
|
||||
|
||||
acl::string buf;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (conn->gets(buf, false) == false)
|
||||
{
|
||||
printf("gets error: %s\r\n", acl::last_serror());
|
||||
break;
|
||||
}
|
||||
|
||||
if (conn->write(buf) == -1)
|
||||
{
|
||||
printf("write error: %s\r\n", acl::last_serror());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("close one connection: %d, %s\r\n", conn->sock_handle(),
|
||||
acl::last_serror());
|
||||
delete conn;
|
||||
}
|
||||
|
||||
static acl::polarssl_conf* ssl_init(const acl::string& crt,
|
||||
const acl::string& key)
|
||||
{
|
||||
|
||||
acl::polarssl_conf* conf = new acl::polarssl_conf;
|
||||
conf->enable_cache(1);
|
||||
|
||||
if (conf->add_cert(crt) == false)
|
||||
{
|
||||
printf("load %s error\r\n", crt.c_str());
|
||||
delete conf;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conf->set_key(key) == false)
|
||||
{
|
||||
printf("set_key %s error\r\n", key.c_str());
|
||||
delete conf;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printf(">>> ssl_init ok, ssl_crt: %s, ssl_key: %s\r\n",
|
||||
crt.c_str(), key.c_str());
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
static void fiber_accept(ACL_FIBER *, void *ctx)
|
||||
{
|
||||
const char* addr = (const char* ) ctx;
|
||||
acl::server_socket server;
|
||||
|
||||
__ssl_conf = ssl_init(__ssl_crt, __ssl_key);
|
||||
|
||||
if (server.open(addr) == false)
|
||||
{
|
||||
printf("open %s error\r\n", addr);
|
||||
exit (1);
|
||||
}
|
||||
else
|
||||
printf(">>> listen %s ok\r\n", addr);
|
||||
|
||||
while (true)
|
||||
{
|
||||
acl::socket_stream* client = server.accept();
|
||||
if (client == NULL)
|
||||
{
|
||||
printf("accept failed: %s\r\n", acl::last_serror());
|
||||
break;
|
||||
}
|
||||
|
||||
client->set_rw_timeout(__rw_timeout);
|
||||
printf("accept one: %d\r\n", client->sock_handle());
|
||||
acl_fiber_create(http_server, client, STACK_SIZE);
|
||||
}
|
||||
|
||||
delete __ssl_conf;
|
||||
exit (0);
|
||||
}
|
||||
|
||||
static void usage(const char* procname)
|
||||
{
|
||||
printf("usage: %s -h [help]\r\n"
|
||||
" -s listen_addr\r\n"
|
||||
" -r rw_timeout\r\n"
|
||||
" -c ssl_crt.pem\r\n"
|
||||
" -C [if check ssl status]\r\n"
|
||||
" -k ssl_key.pem\r\n", procname);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
acl::string addr(":9001");
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "hs:r:c:k:C")) > 0)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
case 's':
|
||||
addr = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
__rw_timeout = atoi(optarg);
|
||||
break;
|
||||
case 'c':
|
||||
__ssl_crt = optarg;
|
||||
break;
|
||||
case 'k':
|
||||
__ssl_key = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
__check_ssl = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
acl::acl_cpp_init();
|
||||
acl::log::stdout_open(true);
|
||||
|
||||
acl_fiber_create(fiber_accept, addr.c_str(), STACK_SIZE);
|
||||
|
||||
acl_fiber_schedule();
|
||||
|
||||
return 0;
|
||||
}
|
8
lib_fiber/samples/ssl_server/stdafx.cpp
Normal file
8
lib_fiber/samples/ssl_server/stdafx.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
||||
// master_threads.pch 将成为预编译头
|
||||
// stdafx.obj 将包含预编译类型信息
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
// TODO: 在 STDAFX.H 中
|
||||
//引用任何所需的附加头文件,而不是在此文件中引用
|
20
lib_fiber/samples/ssl_server/stdafx.h
Normal file
20
lib_fiber/samples/ssl_server/stdafx.h
Normal file
@ -0,0 +1,20 @@
|
||||
// stdafx.h : 标准系统包含文件的包含文件,
|
||||
// 或是常用但不常更改的项目特定的包含文件
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
//#include <iostream>
|
||||
//#include <tchar.h>
|
||||
|
||||
// TODO: 在此处引用程序要求的附加头文件
|
||||
|
||||
#include "lib_acl.h"
|
||||
#include "fiber/lib_fiber.h"
|
||||
#include "acl_cpp/lib_acl.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
1) 增加针对协程调度器的监控机制
|
||||
2) 增加更方便的协程异步调用接口
|
||||
3) 支持信号跳转方式
|
||||
3) 支持信号跳转方式 --- ok
|
||||
4) 支持 read 读缓冲
|
||||
5) 支持栈空间的自动扩充及共享堆栈
|
||||
|
Loading…
Reference in New Issue
Block a user