fixed one bug in events_enable_read of events_epoll_thr.c; add some samples for lib_fiber;

This commit is contained in:
ubuntu14 2016-08-11 13:36:20 +08:00
parent 3c8dc7b019
commit 0c54b8c0d5
31 changed files with 1846 additions and 61 deletions

View File

@ -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 数据元素

View File

@ -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
View File

@ -0,0 +1,213 @@
本模块(lib_fiber)为基于协程方式进行高并发、高性能开发的网络协程库。使用者可以象创建线程一样创建协程,相对于线程而言,协程更为“轻量”,因此使用者可以创建大量(成千上万)的协程。每个协程可以与一个网络连接绑定;同时使用者可以采用“同步”思维方式编写网络程序,而不必象非阻塞程序一样采用异步回调方式,因此使用者使用起来并没有多大编程复杂度。
本网络协程库的协程部分是基于 Russ Cox (golang 的协程作者) 在 2005 年实现的 libtasklibtask 实现了协程编程的基本原型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
View File

@ -0,0 +1,3 @@
Author:
niukey@qq.com
shuxin.zheng@qq.com

View File

@ -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
View 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, &current->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
View 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

View File

@ -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;
}

View File

@ -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;
};
/*

View File

@ -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;

View File

@ -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
View 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
View File

@ -0,0 +1 @@
using c++1x

1
lib_fiber/cxx/debug/keep Normal file
View File

@ -0,0 +1 @@
keepme

View File

@ -0,0 +1 @@
keepme

1
lib_fiber/cxx/keep Normal file
View File

@ -0,0 +1 @@
keepme

1
lib_fiber/cxx/src/keep Normal file
View File

@ -0,0 +1 @@
keepme

View File

@ -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();

View File

@ -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;
}

View File

@ -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);

View 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 \

View File

@ -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();

View File

@ -0,0 +1,3 @@
include ../Makefile_cpp.in
EXTLIBS = -L../../../lib/linux64 -lpolarssl
PROG = client

View 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;
}

View File

@ -0,0 +1,8 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// master_threads.pch 将成为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中
//引用任何所需的附加头文件,而不是在此文件中引用

View 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

View File

@ -0,0 +1,3 @@
include ../Makefile_cpp.in
EXTLIBS = -L../../../lib/linux64 -lpolarssl
PROG = server

View 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;
}

View File

@ -0,0 +1,8 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// master_threads.pch 将成为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中
//引用任何所需的附加头文件,而不是在此文件中引用

View 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

View File

@ -1,5 +1,6 @@
1) 增加针对协程调度器的监控机制
2) 增加更方便的协程异步调用接口
3) 支持信号跳转方式
3) 支持信号跳转方式 --- ok
4) 支持 read 读缓冲
5) 支持栈空间的自动扩充及共享堆栈