static void io_timer(ACL_FIBER *fiber, void *ctx) { FIBER_TIMER *ft = (FIBER_TIMER *) ctx; assert(fiber == ft->timer); acl_fiber_set_errno(ft->fiber, ETIMEDOUT); acl_fiber_keep_errno(ft->fiber, 1); printf("timer-%d wakeup, set fiber-%d, errno: %d, %d\r\n", acl_fiber_id(fiber), acl_fiber_id(ft->fiber), ETIMEDOUT, acl_fiber_errno(ft->fiber)); acl_fiber_ready(ft->fiber); }
inline ssize_t fiber_sendmsg(int sockfd, const struct msghdr *msg, int flags) { ACL_FIBER *me; while (1) { ssize_t n = __sys_sendmsg(sockfd, msg, flags); if (!acl_var_hook_sys_api) return n; if (n >= 0) return n; fiber_save_errno(); #if EAGAIN == EWOULDBLOCK if (errno != EAGAIN) #else if (errno != EAGAIN && errno != EWOULDBLOCK) #endif return -1; fiber_wait_write(sockfd); me = acl_fiber_running(); if (acl_fiber_killed(me)) acl_msg_info("%s(%d), %s: fiber-%d is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); } }
inline ssize_t fiber_write(int fd, const void *buf, size_t count) { ACL_FIBER *me; while (1) { ssize_t n = __sys_write(fd, buf, count); if (!acl_var_hook_sys_api) return n; if (n >= 0) return n; fiber_save_errno(); #if EAGAIN == EWOULDBLOCK if (errno != EAGAIN) #else if (errno != EAGAIN && errno != EWOULDBLOCK) #endif return -1; fiber_wait_write(fd); me = acl_fiber_running(); if (acl_fiber_killed(me)) acl_msg_info("%s(%d), %s: fiber-%d is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); } }
ssize_t sendfile64(int out_fd, int in_fd, off64_t *offset, size_t count) { ACL_FIBER *me; if (__sys_sendfile64 == NULL) hook_io(); while (1) { ssize_t n = __sys_sendfile64(out_fd, in_fd, offset, count); if (!acl_var_hook_sys_api || n >= 0) return n; fiber_save_errno(); #if EAGAIN == EWOULDBLOCK if (errno != EAGAIN) #else if (errno != EAGAIN && errno != EWOULDBLOCK) #endif return -1; fiber_wait_write(out_fd); me = acl_fiber_running(); if (acl_fiber_killed(me)) { acl_msg_info("%s(%d), %s: fiber-%u is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); return -1; } } }
void acl_fiber_kill(ACL_FIBER *fiber) { ACL_FIBER *curr = __thread_fiber->running; if (fiber == NULL) { acl_msg_error("%s(%d), %s: fiber NULL", __FILE__, __LINE__, __FUNCTION__); return; } if (curr == NULL) { acl_msg_error("%s(%d), %s: current fiber NULL", __FILE__, __LINE__, __FUNCTION__); return; } fiber->flag |= FIBER_F_KILLED; if (fiber == curr) { acl_msg_error("%s(%d), %s: fiber-%d kill itself disable!", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(fiber)); return; } acl_ring_detach(&curr->me); acl_ring_detach(&fiber->me); acl_fiber_ready(fiber); acl_fiber_yield(); }
inline ssize_t fiber_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { ACL_FIBER *me; while (1) { ssize_t n = __sys_sendto(sockfd, buf, len, flags, dest_addr, addrlen); if (!acl_var_hook_sys_api) return n; if (n >= 0) return n; fiber_save_errno(); #if EAGAIN == EWOULDBLOCK if (errno != EAGAIN) #else if (errno != EAGAIN && errno != EWOULDBLOCK) #endif return -1; fiber_wait_write(sockfd); me = acl_fiber_running(); if (acl_fiber_killed(me)) acl_msg_info("%s(%d), %s: fiber-%d is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); } }
inline ssize_t fiber_recv(int sockfd, void *buf, size_t len, int flags) { ACL_FIBER *me; if (__sys_recv == NULL) hook_io(); while (1) { ssize_t n = __sys_recv(sockfd, buf, len, flags); if (!acl_var_hook_sys_api) return n; if (n >= 0) return n; fiber_save_errno(); #if EAGAIN == EWOULDBLOCK if (errno != EAGAIN) #else if (errno != EAGAIN && errno != EWOULDBLOCK) #endif return -1; fiber_wait_read(sockfd); me = acl_fiber_running(); if (acl_fiber_killed(me)) acl_msg_info("%s(%d), %s: fiber-%u is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); } }
inline ssize_t fiber_readv(int fd, const struct iovec *iov, int iovcnt) { ACL_FIBER *me; if (__sys_readv == NULL) hook_io(); while (1) { ssize_t n = __sys_readv(fd, iov, iovcnt); if (!acl_var_hook_sys_api) return n; if (n >= 0) return n; fiber_save_errno(); #if EAGAIN == EWOULDBLOCK if (errno != EAGAIN) #else if (errno != EAGAIN && errno != EWOULDBLOCK) #endif return -1; fiber_wait_read(fd); me = acl_fiber_running(); if (acl_fiber_killed(me)) acl_msg_info("%s(%d), %s: fiber-%u is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); } }
static bool redis_set(ACL_FIBER& fiber, ACL_CHANNEL &chan, PKT& pkt) { acl::redis cmd(&__redis_cluster); pkt.success = false; if (pkt.key.empty()) { printf("%s(%d): fiber-%d: key empty!\r\n", __FUNCTION__, __LINE__, acl_fiber_id(&fiber)); pkt.val = "key empty"; acl_channel_sendp(&chan, &pkt); return false; } if (pkt.val.empty()) { printf("%s(%d): fiber-%d: val empty\r\n", __FUNCTION__, __LINE__, acl_fiber_id(&fiber)); pkt.val = "val empty"; acl_channel_sendp(&chan, &pkt); return false; } if (cmd.set(pkt.key, pkt.val) == false) { printf("%s(%d): fiber-%d: set error, key: %s, val: %s\r\n", __FUNCTION__, __LINE__, acl_fiber_id(&fiber), pkt.key.c_str(), pkt.val.c_str()); acl_channel_sendp(&chan, &pkt); return false; } pkt.success = true; if (acl_channel_sendp(&chan, &pkt) < 0) { printf("%s(%d): fiber-%d: acl_channel_sendp error, key %s\r\n", __FUNCTION__, __LINE__, acl_fiber_id(&fiber), pkt.key.c_str()); return false; } return true; }
static void fiber_worker(ACL_FIBER *fiber, void *ctx) { ACL_CHANNEL *chan = ((MYCHAN *) ctx)->chan; while (true) { PKT* pkt = (PKT *) acl_channel_recvp(chan); if (pkt == NULL) { printf("fiber-%d: acl_channel_recvp NULL\r\n", acl_fiber_id(fiber)); break; } if (pkt->cmd.equal("set", false)) { if (redis_set(*fiber, *chan, *pkt) == false) { printf("fiber-%d: redis_set error\r\n", acl_fiber_id(fiber)); break; } } else if (pkt->cmd.equal("get", false)) { if (redis_get(*fiber, *chan, *pkt) == false) { printf("fiber-%d: redis_get error\r\n", acl_fiber_id(fiber)); break; } } else if (pkt->cmd.equal("del", false)) { if (redis_del(*fiber, *chan, *pkt) == false) { printf("fiber-%d: redis_del error\r\n", acl_fiber_id(fiber)); break; } } else printf("unknown cmd: %s\r\n", pkt->cmd.c_str()); } }
static void fiber_producer(ACL_FIBER *fiber, void *ctx) { ACL_CHANNEL *chan = (ACL_CHANNEL *) ctx; while (__nsend < __max) { int ret = acl_channel_sendul(chan, __nsend); __nsend++; if (ret <= 0) { printf("fiber-%d, channel_sendul error!\r\n", acl_fiber_id(fiber)); break; } if (__nsend < __display) printf(">>fiber-%d, send: %d %s\r\n", acl_fiber_id(fiber), __nsend, ret > 0 ? "ok" : "error"); } }
static void echo_client(ACL_FIBER *fiber, void *ctx) { ACL_VSTREAM *cstream = (ACL_VSTREAM *) ctx; char buf[8192]; int ret, count = 0; int ntimeout = 0; FIBER_TIMER *ft = (FIBER_TIMER *) acl_mymalloc(sizeof(FIBER_TIMER)); ft->fiber = fiber; ft->timer = acl_fiber_create_timer(__rw_timeout * 1000, 320000, io_timer, ft); ft->conn = cstream; #define SOCK ACL_VSTREAM_SOCK while (1) { printf("begin read\n"); ret = acl_vstream_gets(cstream, buf, sizeof(buf) - 1); if (ret == ACL_VSTREAM_EOF) { printf("fiber-%d, gets error: %s, %d, %d, fd: %d, " "count: %d\r\n", acl_fiber_id(fiber), acl_last_serror(), errno, acl_fiber_errno(fiber), SOCK(cstream), count); if (errno != ETIMEDOUT) break; if (++ntimeout > 2) { printf("too many timeout: %d\r\n", ntimeout); break; } printf("ntimeout: %d\r\n", ntimeout); ft->timer = acl_fiber_create_timer(__rw_timeout * 1000, 320000, io_timer, ft); } acl_fiber_reset_timer(ft->timer, __rw_timeout * 1000); buf[ret] = 0; //printf("gets line: %s", buf); if (acl_vstream_writen(cstream, buf, ret) == ACL_VSTREAM_EOF) { printf("write error, fd: %d\r\n", SOCK(cstream)); break; } count++; } acl_myfree(ft); acl_vstream_close(cstream); }
static void fiber_consumer(ACL_FIBER *fiber, void *ctx) { ACL_CHANNEL *chan = (ACL_CHANNEL *) ctx; while (__nread < __max) { unsigned long n = acl_channel_recvul(chan); __nread++; if (__nread < __display) printf(">>fiber-%d, recv: %lu\r\n", acl_fiber_id(fiber), n); } }
inline ssize_t fiber_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { ssize_t ret; EVENT *ev; ACL_FIBER *me; if (sockfd < 0) { acl_msg_error("%s: invalid sockfd: %d", __FUNCTION__, sockfd); return -1; } if (!acl_var_hook_sys_api) { if (__sys_recvfrom == NULL) hook_io(); return __sys_recvfrom(sockfd, buf, len, flags, src_addr, addrlen); } ev = fiber_io_event(); if (ev && event_readable(ev, sockfd)) { event_clear_readable(ev, sockfd); ret = __sys_recvfrom(sockfd, buf, len, flags, src_addr, addrlen); if (ret < 0) fiber_save_errno(); return ret; } fiber_wait_read(sockfd); if (ev) event_clear_readable(ev, sockfd); ret = __sys_recvfrom(sockfd, buf, len, flags, src_addr, addrlen); if (ret >= 0) return ret; fiber_save_errno(); me = acl_fiber_running(); if (acl_fiber_killed(me)) { acl_msg_info("%s(%d), %s: fiber-%u is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); return -1; } return ret; }
static bool redis_get(ACL_FIBER& fiber, ACL_CHANNEL &chan, PKT &pkt) { acl::redis cmd(&__redis_cluster); pkt.success = false; if (pkt.key.empty()) { printf("fiber-%d: key empty!\r\n", acl_fiber_id(&fiber)); pkt.val = "key empty"; acl_channel_sendp(&chan, &pkt); return false; } if (cmd.get(pkt.key, pkt.val) == false) { printf("fiber-%d: get error, key: %s\r\n", acl_fiber_id(&fiber), pkt.key.c_str()); pkt.val = "get error"; acl_channel_sendp(&chan, &pkt); return false; } pkt.success = true; if (acl_channel_sendp(&chan, &pkt) < 0) { printf("fiber-%d: acl_channel_sendp error, key: %s\r\n", acl_fiber_id(&fiber), pkt.key.c_str()); return false; } return true; }
static void fiber_wait(ACL_FIBER *, void *ctx) { ACL_CHANNEL *chan = (ACL_CHANNEL *) ctx; unsigned long n = acl_channel_recvul(chan); printf("----fiber-%d: get n: %lu---\r\n", acl_fiber_self(), n); for (int i = 0; __workers[i] != NULL; i++) { printf("kill fiber-%d\r\n", acl_fiber_id(__workers[i])); acl_fiber_kill(__workers[i]); } printf("---- fiber schedul stopping now ----\r\n"); acl_fiber_schedule_stop(); }
inline ssize_t fiber_recvmsg(int sockfd, struct msghdr *msg, int flags) { ssize_t ret; EVENT *ev; ACL_FIBER *me; if (sockfd < 0) { acl_msg_error("%s: invalid sockfd: %d", __FUNCTION__, sockfd); return -1; } if (!acl_var_hook_sys_api) { if (__sys_recvmsg == NULL) hook_io(); return __sys_recvmsg(sockfd, msg, flags); } ev = fiber_io_event(); if (ev && event_readable(ev, sockfd)) { event_clear_readable(ev, sockfd); ret = __sys_recvmsg(sockfd, msg, flags); if (ret < 0) fiber_save_errno(); return ret; } fiber_wait_read(sockfd); if (ev) event_clear_readable(ev, sockfd); ret = __sys_recvmsg(sockfd, msg, flags); if (ret >= 0) return ret; fiber_save_errno(); me = acl_fiber_running(); if (acl_fiber_killed(me)) acl_msg_info("%s(%d), %s: fiber-%u is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); return ret; }
inline ssize_t fiber_readv(int fd, const struct iovec *iov, int iovcnt) { ssize_t ret; EVENT *ev; ACL_FIBER *me; if (fd < 0) { acl_msg_error("%s: invalid fd: %d", __FUNCTION__, fd); return -1; } if (!acl_var_hook_sys_api) { if (__sys_readv == NULL) hook_io(); return __sys_readv(fd, iov, iovcnt); } ev = fiber_io_event(); if (ev && event_readable(ev, fd)) { event_clear_readable(ev, fd); ret = __sys_readv(fd, iov, iovcnt); if (ret < 0) fiber_save_errno(); return ret; } fiber_wait_read(fd); if (ev) event_clear_readable(ev, fd); ret = __sys_readv(fd, iov, iovcnt); if (ret >= 0) return ret; fiber_save_errno(); me = acl_fiber_running(); if (acl_fiber_killed(me)) acl_msg_info("%s(%d), %s: fiber-%u is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); return ret; }
inline ssize_t fiber_read(int fd, void *buf, size_t count) { ssize_t ret; EVENT *ev; ACL_FIBER *me; if (fd < 0) { acl_msg_error("%s: invalid fd: %d", __FUNCTION__, fd); return -1; } if (!acl_var_hook_sys_api) return __sys_read(fd, buf, count); ev = fiber_io_event(); if (ev && event_readable(ev, fd)) { event_clear_readable(ev, fd); ret = __sys_read(fd, buf, count); if (ret < 0) fiber_save_errno(); return ret; } fiber_wait_read(fd); if (ev) event_clear_readable(ev, fd); ret = __sys_read(fd, buf, count); if (ret >= 0) return ret; fiber_save_errno(); me = acl_fiber_running(); if (acl_fiber_killed(me)) acl_msg_info("%s(%d), %s: fiber-%d is existing", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(me)); return ret; }
static int __lock(ACL_FIBER_MUTEX *lk, int block) { ACL_FIBER *curr = acl_fiber_running(); if (lk->owner == NULL) { lk->owner = acl_fiber_running(); acl_ring_prepend(&curr->holding, &lk->me); return 0; } // xxx: no support recursion lock assert(lk->owner != curr); if (!block) return -1; acl_ring_prepend(&lk->waiting, &curr->me); curr->waiting = lk; acl_fiber_switch(); /* if switch to me because other killed me, I should detach myself; * else if because other unlock, I'll be detached twice which is * hamless because ACL_RING can deal with it. */ acl_ring_detach(&curr->me); if (lk->owner == curr) return 0; if (acl_fiber_killed(curr)) acl_msg_info("%s(%d), %s: lock fiber-%u was killed", __FILE__, __LINE__, __FUNCTION__, acl_fiber_id(curr)); else acl_msg_warn("%s(%d), %s: qlock: owner=%p self=%p oops", __FILE__, __LINE__, __FUNCTION__, lk->owner, curr); return 0; }
static void fiber_redis(ACL_FIBER *fiber, void *ctx) { acl::redis_client_cluster *cluster = (acl::redis_client_cluster *) ctx; acl::redis cmd(cluster); acl::string key, val; int i = 0; struct timeval last, now; gettimeofday(&last, NULL); for (; i < __oper_count; i++) { key.format("key-%d-%d", acl_fiber_id(fiber), i); val.format("val-%d-%d", acl_fiber_id(fiber), i); if (cmd.set(key, val) == false) { printf("fiber-%d: set error: %s, key: %s\r\n", acl_fiber_id(fiber), cmd.result_error(), key.c_str()); break; } else if (i < 5) printf("fiber-%d: set ok, key: %s\r\n", acl_fiber_id(fiber), key.c_str()); cmd.clear(); } gettimeofday(&now, NULL); double spent = stamp_sub(&now, &last); printf("---set spent %.2f ms, count %d, speed: %.2f----\r\n", spent, i, (i * 1000) / (spent > 0 ? spent : 1)); gettimeofday(&last, NULL); for (int j = 0; j < i; j++) { key.format("key-%d-%d", acl_fiber_id(fiber), j); if (cmd.get(key, val) == false) { printf("fiber-%d: get error: %s, key: %s\r\n", acl_fiber_id(fiber), cmd.result_error(), key.c_str()); break; } val.clear(); cmd.clear(); } gettimeofday(&now, NULL); spent = stamp_sub(&now, &last); printf("---get spent %.2f ms, count %d, speed: %.2f----\r\n", spent, i, (i * 1000) / (spent > 0 ? spent : 1)); gettimeofday(&last, NULL); for (int j = 0; j < i; j++) { key.format("key-%d-%d", acl_fiber_id(fiber), j); if (cmd.del_one(key) < 0) { printf("fiber-%d: del error: %s, key: %s\r\n", acl_fiber_id(fiber), cmd.result_error(), key.c_str()); break; } cmd.clear(); } gettimeofday(&now, NULL); spent = stamp_sub(&now, &last); printf("---del spent %.2f ms, count %d, speed: %.2f----\r\n", spent, i, (i * 1000) / (spent > 0 ? spent : 1)); if (--__fibers_count == 0) { long long total = __fibers_max * i * 3; gettimeofday(&__end, NULL); spent = stamp_sub(&__end, &__begin); printf("fibers: %d, count: %lld, spent: %.2f, speed: %.2f\r\n", __fibers_max, total, spent, (total * 1000) / (spent > 0 ? spent : 1)); acl_fiber_stop(); } }
int fiber::get_id(void) const { return f_ ? acl_fiber_id(f_) : -1; }
static void fiber_result(ACL_FIBER *fiber, void *ctx) { MYCHANS *mychans = (MYCHANS *) ctx; MYCHAN *mychan = &mychans->chans[mychans->off++]; ACL_CHANNEL *chan = mychan->chan; PKT pkt; if (mychans->off == mychans->size) mychans->off = 0; pkt.cmd = mychan->cmd; for (int i = 0; i < __oper_count; i++) { pkt.key.format("key-%d-%d", acl_fiber_id(fiber), i); pkt.val.format("val-%d-%d", acl_fiber_id(fiber), i); if (acl_channel_sendp(chan, &pkt) < 0) { printf("%s(%d): fiber-%d: acl_channel_sendp error, key = %s\r\n", __FUNCTION__, __LINE__, acl_fiber_id(fiber), pkt.key.c_str()); break; } PKT* res = (PKT *) acl_channel_recvp(chan); if (res == NULL) { printf("%s(%d): fiber-%d: acl_channel_recvp error, key = %s\r\n", __FUNCTION__, __LINE__, acl_fiber_id(fiber), pkt.key.c_str()); break; } //assert(res == &pkt); if (!res->success) { printf("%s(%d): fiber-%d: cmd = %s, key = %s, failed\r\n", __FUNCTION__, __LINE__, acl_fiber_id(fiber), pkt.cmd.c_str(), pkt.key.c_str()); continue; } if (++__display >= 10) continue; if (pkt.cmd.equal("get", false)) printf("fiber-%d: cmd = %s, key = %s, val = %s\r\n", acl_fiber_id(fiber), pkt.cmd.c_str(), pkt.key.c_str(), res->val.c_str()); else printf("fiber-%d: cmd = %s, key = %s\r\n", acl_fiber_id(fiber), pkt.cmd.c_str(), pkt.key.c_str()); } if (--__fibers_count == 0) { printf("---All fibers are over!---\r\n"); unsigned long n = 100; acl_channel_sendul(__chan_exit, n); } }
unsigned int fiber::get_id(void) const { return f_ ? acl_fiber_id(f_) : 0; }
int acl_fiber_self(void) { ACL_FIBER *curr = acl_fiber_running(); return acl_fiber_id(curr); }
static int __timer_sleep = 1000; static int __max_fiber = 1000; static __thread struct timeval __begin; static __thread int __left_fiber = 1000; static void timer_main(ACL_FIBER *fiber, void *ctx acl_unused) { struct timeval now; double spent; gettimeofday(&now, NULL); spent = stamp_sub(&now, &__begin); printf("thread-%lu, timer-%d wakeup, spend: %.2f ms\r\n", (unsigned long) acl_pthread_self(), acl_fiber_id(fiber), spent); if (--__left_fiber == 0) { printf("All are over!\r\n"); //acl_fiber_schedule_stop(); } } static void *thread_main(void *ctx acl_unused) { int i; gettimeofday(&__begin, NULL); __left_fiber = __max_fiber; printf("thread: %lu\r\n", (unsigned long) acl_pthread_self());