double acl_meter_time(const char *filename, int line, const char *info) { struct timeval now; double f; METER_CTX_T *ctx = tls_calloc(sizeof(METER_CTX_T)); if (ctx->init_done == 0) { ctx->init_done = 1; gettimeofday(&ctx->stamp, NULL); } gettimeofday(&now, NULL); now.tv_usec -= ctx->stamp.tv_usec; if (now.tv_usec < 0) { --now.tv_sec; now.tv_usec += 1000000; } now.tv_sec -= ctx->stamp.tv_sec; f = now.tv_sec * 1000.0 + now.tv_usec/1000.0; if (info) printf("tid=%lu, %s(%d), %s: time inter = %8.3f ms\r\n", (unsigned long) acl_pthread_self(), filename, line, info, f); else printf("tid=%lu, %s(%d): time inter = %8.3f ms\r\n", (unsigned long) acl_pthread_self(), filename, line, f); gettimeofday(&ctx->stamp, NULL); return (f); }
static void thread_main(void*) { printf("%s: thread: %ld\r\n", __FUNCTION__, (unsigned long) acl_pthread_self()); acl::aio_handle* handle; // 每个线程创建单独的异步事件句柄 handle = new acl::aio_handle(__kernel_event ? acl::ENGINE_KERNEL : acl::ENGINE_SELECT); int i; for (i = 0; i < __parallel; i++) { async_file* fp = new async_file(handle, __path, i); if (fp->open_write() == false) { printf("open file error: %s\r\n", acl::last_serror()); delete fp; break; } } if (i == 0) { printf("thread(%lu) no file opened!\r\n", (unsigned long) acl_pthread_self()); delete handle; return; } // 进入异步事件循环过程 while (true) { if (handle->check() == false) break; if (__nok == __parallel) { printf("%s: thread(%lu) over, total: %d\r\n", __FUNCTION__, (unsigned long) acl_pthread_self(), __nok); break; } } // 因为 IO 句柄是延迟释放的,所以需要再次检查一遍 handle->check(); // 销毁异步事件句柄 delete handle; }
bool master_service::thread_on_read(acl::socket_stream* stream) { logger("thread id: %lu", acl_pthread_self()); acl::http_response res(stream); // 响应数据体为 xml 格式 res.response_header().set_content_type("text/html"); // 读 HTTP 请求头 if (res.read_header() == false) return false; acl::string buf; // 读 HTTP 请求体数据 if (res.get_body(buf) == false) return false; acl::http_client* client = res.get_client(); // 判断客户端是否希望保持长连接 bool keep_alive = client->keep_alive(); // 返回数据给客户端 res.response_header() .set_status(200) .set_keep_alive(keep_alive) .set_content_length(var_cfg_buf_size); if (res.response(res_buf_, var_cfg_buf_size) == false) return false; return keep_alive ? true : false; }
bool master_service::thread_on_accept(acl::socket_stream* conn) { if (0) acl_tcp_so_linger(conn->sock_handle(), 1, 0); logger("thread id: %lu", acl_pthread_self()); return true; }
void fiber_io_check(void) { if (__thread_fiber != NULL) return; acl_assert(acl_pthread_once(&__once_control, thread_init) == 0); __maxfd = acl_open_limit(0); if (__maxfd <= 0) __maxfd = MAXFD; __thread_fiber = (FIBER_TLS *) acl_mymalloc(sizeof(FIBER_TLS)); __thread_fiber->event = event_create(__maxfd); __thread_fiber->io_fibers = (ACL_FIBER **) acl_mycalloc(__maxfd, sizeof(ACL_FIBER *)); __thread_fiber->ev_fiber = acl_fiber_create(fiber_io_loop, __thread_fiber->event, STACK_SIZE); __thread_fiber->io_count = 0; __thread_fiber->nsleeping = 0; __thread_fiber->io_stop = 0; acl_ring_init(&__thread_fiber->ev_timer); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { __main_fiber = __thread_fiber; atexit(fiber_io_main_free); } else if (acl_pthread_setspecific(__fiber_key, __thread_fiber) != 0) acl_msg_fatal("acl_pthread_setspecific error!"); }
int acl_fiber_sem_wait(ACL_FIBER_SEM *sem) { ACL_FIBER *curr; if (sem->tid != acl_pthread_self()) return -1; if (sem->num > 0) { sem->num--; return sem->num; } curr = acl_fiber_running(); if (curr == NULL) return -1; acl_ring_prepend(&sem->waiting, &curr->me); 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); return sem->num; }
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)); #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->slot = 0; __thread_fiber->idgen = 0; __thread_fiber->count = 0; 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!"); }
ICMP_CHAT *icmp_chat_create(ACL_AIO* aio, int check_tid) { ICMP_CHAT *chat; chat = (ICMP_CHAT*) acl_mycalloc(1, sizeof(ICMP_CHAT)); chat->aio = aio; acl_ring_init(&chat->host_head); chat->is = icmp_stream_open(aio); chat->seq_no = 0; chat->count = 0; #ifdef ACL_UNIX chat->pid = getpid(); #elif defined(ACL_WINDOWS) chat->pid = _getpid(); #endif chat->tid = (unsigned long) acl_pthread_self(); chat->check_tid = check_tid; if (aio != NULL) icmp_chat_aio_init(chat, aio); else icmp_chat_sio_init(chat); return (chat); }
bool master_service::thread_on_read(acl::socket_stream* conn) { http_servlet* servlet = (http_servlet*) conn->get_ctx(); if (servlet == NULL) logger_fatal("servlet null!"); if (conf_ == NULL) return servlet->doRun("127.0.0.1:11211", conn); acl::stream_hook* hook = conn->get_hook(); if (hook != NULL) return servlet->doRun("127.0.0.1:11211", conn); // 对于使用 SSL 方式的流对象,需要将 SSL IO 流对象注册至网络 // 连接流对象中,即用 ssl io 替换 stream 中默认的底层 IO 过程 logger("begin setup ssl hook..."); acl::polarssl_io* ssl = new acl::polarssl_io(*conf_, true); if (conn->setup_hook(ssl) == ssl) { logger_error("setup_hook error!"); ssl->destroy(); return false; } logger("setup hook ok, tid: %lu", (unsigned long) acl_pthread_self()); return servlet->doRun("127.0.0.1:11211", conn); }
static void free_buf_fn(void *arg) { ACL_VSTRING *buf = (ACL_VSTRING*) arg; printf(">> current thread id=%u, buf = %s\r\n", (unsigned int) acl_pthread_self(), acl_vstring_str(buf)); acl_vstring_free(buf); }
static void free_vstring(void *arg) { const char *myname = "free_vstring"; ACL_VSTRING *buf = (ACL_VSTRING*) arg; acl_vstring_free(buf); printf("%s: tid=%d, free vstring ok\n", myname, (int) acl_pthread_self()); }
static void once_init(void) { if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { acl_pthread_key_create(&once_key, dummy); atexit(main_free_tls); } else acl_pthread_key_create(&once_key, free_tls); }
static void main_thread_atexit(void *arg) { ACL_VSTRING *buf = (ACL_VSTRING*) arg; printf("main thread exit now, tid=%u, buf=%s\r\n", (unsigned int) acl_pthread_self(), acl_vstring_str(buf)); printf("in the main thread_atexit, input any key to exit\r\n"); getchar(); }
static void *test_thread_fn(void *arg) { THREAD_CTX *ctx = (THREAD_CTX*) arg; ctx->i++; printf("current tid is: %lu\r\n", (unsigned long int) acl_pthread_self()); return (ctx); }
static void on_thread_exit(void *arg) { const char *myname = "on_thread_exit"; acl_pthread_pool_t *thr_pool = (acl_pthread_pool_t*) arg; /* 判断一下,仅是为了验证参数传递过程 */ assert(thr_pool == __thr_pool); printf("%s: thread(%u) exit now\r\n", myname, (unsigned int) acl_pthread_self()); }
// 子线程处理过程 static void thread_main(void*) { for (int i = 0; i < __loop_count; i++) { connect_pool* pool = (connect_pool*) __conn_manager->peek(); if (pool == NULL) { printf("\r\n>>>%lu(%d): peek pool failed<<<\r\n", (unsigned long) acl_pthread_self(), __LINE__); check_all_connections(); exit (1); } // 设置连接的超时时间及读超时时间 pool->set_timeout(2, 2); // 从连接池中获取一个连接 connect_client* conn = (connect_client*) pool->peek(); if (conn == NULL) { printf("\r\n>>>%lu: peek connect failed from %s<<<\r\n", (unsigned long) acl_pthread_self(), pool->get_addr()); check_all_connections(); exit (1); } // 需要对获得的连接重置状态,以清除上次请求过程的临时数据 else conn->reset(); // 开始新的 HTTP 请求过程 if (get(conn, i) == false) { printf("one request failed, close connection\r\n"); // 错误连接需要关闭 pool->put(conn, false); } else pool->put(conn, true); } printf(">>>>thread: %lu OVER<<<<\r\n", (unsigned long) acl_pthread_self()); }
ACL_FIBER_SEM *acl_fiber_sem_create(int num) { ACL_FIBER_SEM *sem = (ACL_FIBER_SEM *) acl_mymalloc(sizeof(ACL_FIBER_SEM)); sem->num = num; acl_ring_init(&sem->waiting); sem->tid = acl_pthread_self(); return sem; }
static void thread_free_dummy(void* ctx) { if ((unsigned long) acl_pthread_self() != acl_main_thread_self()) acl_myfree(ctx); #ifdef HAS_MYSQL_DLL if (__mysql_thread_end) __mysql_thread_end(); #endif }
int acl_read_wait(ACL_SOCKET fd, int timeout) { const char *myname = "acl_read_wait"; int op = EPOLL_CTL_ADD, delay = timeout * 1000, *epoll_fd; struct epoll_event ee, events[1]; acl_assert(acl_pthread_once(&epoll_once, thread_epoll_init) == 0); epoll_fd = (int*) acl_pthread_getspecific(epoll_key); if (epoll_fd == NULL) { epoll_fd = (int*) acl_mymalloc(sizeof(int)); acl_assert(acl_pthread_setspecific(epoll_key, epoll_fd) == 0); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { main_epoll_read_fd = epoll_fd; atexit(main_epoll_end); } *epoll_fd = epoll_create(1); } ee.events = EPOLLIN | EPOLLHUP | EPOLLERR; ee.data.u64 = 0; ee.data.fd = fd; if (epoll_ctl(*epoll_fd, op, fd, &ee) == -1) { acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d", myname, __LINE__, acl_last_serror(), fd); return -1; } if (epoll_wait(*epoll_fd, events, 1, delay) == -1) { acl_msg_error("%s(%d): epoll_wait error: %s, fd: %d", myname, __LINE__, acl_last_serror(), fd); return -1; } if ((events[0].events & (EPOLLERR | EPOLLHUP)) != 0) return -1; if ((events[0].events & EPOLLIN) == 0) { acl_set_error(ACL_ETIMEDOUT); return -1; } ee.events = 0; ee.data.u64 = 0; ee.data.fd = fd; if (epoll_ctl(*epoll_fd, EPOLL_CTL_DEL, fd, &ee) == -1) { acl_msg_error("%s(%d): epoll_ctl error: %s, fd: %d", myname, __LINE__, acl_last_serror(), fd); return -1; } return 0; }
static void slice_key_init(void) { unsigned long curr_tid = (unsigned long) acl_pthread_self(); unsigned long main_tid = (unsigned long) acl_main_thread_self(); if (curr_tid == main_tid) { acl_pthread_key_create(&__mem_slice_key, NULL); atexit(main_thread_slice_free); } else acl_pthread_key_create(&__mem_slice_key, (void (*)(void*)) mem_slice_free); }
static ACL_MEM_SLICE *mem_slice_create(void) { const char *myname = "mem_slice_create"; ACL_MEM_SLICE *mem_slice; acl_pthread_once(&once_control, slice_key_init); if (__mem_slice_key == (acl_pthread_key_t) -1) acl_msg_fatal("%s(%d): __mem_slice_key(%d) invalid," " call acl_mem_slice_init or acl_mem_slice_set first", myname, __LINE__, (int) __mem_slice_key); mem_slice = acl_pthread_getspecific(__mem_slice_key); if (mem_slice != NULL) return mem_slice; mem_slice = (ACL_MEM_SLICE*) acl_default_calloc(__FILE__, __LINE__, 1, sizeof(ACL_MEM_SLICE)); if (mem_slice == NULL) acl_msg_fatal("%s(%d): can't alloc for mem_slice(%s)", myname, __LINE__, acl_last_serror()); mem_slice->slice_pool = acl_slice_pool_create(__mem_base, __mem_nslice, __mem_slice_flag); mem_slice->tid = (unsigned long) acl_pthread_self(); mem_slice->list = private_array_create(__mem_list_init_size); MUTEX_INIT(mem_slice); mem_slice->tls_key = __mem_slice_key; mem_slice->nalloc_gc = __mem_nalloc_gc; mem_slice->slice_flag = __mem_slice_flag; acl_pthread_setspecific(__mem_slice_key, mem_slice); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) __main_mem_slice = mem_slice; acl_msg_info("%s(%d): thread(%ld) set myown mem_slice(%p)", myname, __LINE__, (long) mem_slice->tid, mem_slice); return mem_slice; }
static int on_thread_init(void *arg) { const char *myname = "on_thread_init"; acl_pthread_pool_t *thr_pool = (acl_pthread_pool_t*) arg; /* 判断一下,仅是为了验证参数传递过程 */ assert(thr_pool == __thr_pool); printf("%s: thread(%u) init now\r\n", myname, (unsigned int) acl_pthread_self()); /* 返回0表示继续执行该线程获得的新任务,返回-1表示停止执行该任务 */ return (0); }
void acl_mem_slice_destroy(void) { ACL_MEM_SLICE *mem_slice = acl_pthread_getspecific(__mem_slice_key); if (mem_slice == NULL) return; /* 释放该线程所拥有的内存切片池对象 */ mem_slice_free(mem_slice); acl_pthread_setspecific(__mem_slice_key, NULL); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) __main_mem_slice = NULL; }
int acl_fiber_sem_trywait(ACL_FIBER_SEM *sem) { if (sem->tid != acl_pthread_self()) return -1; if (sem->num > 0) { sem->num--; return sem->num; } return -1; }
static void thread_epoll_end(void *ctx) { const char *myname = "thread_epoll_end"; EPOLL_CTX *epoll_ctx = (EPOLL_CTX*) ctx; acl_msg_info("%s(%d), %s: close epoll_fd: %d, tid: %lu, %lu", __FILE__, __LINE__, myname, epoll_ctx->epfd, epoll_ctx->tid, acl_pthread_self()); close(epoll_ctx->epfd); acl_myfree(epoll_ctx); }
void master_service::proc_on_init() { logger("thread id: %lu", acl_pthread_self()); if (var_cfg_buf_size <= 0) var_cfg_buf_size = 1024; res_buf_ = (char*) acl_mymalloc(var_cfg_buf_size + 1); int i; for (i = 0; i < var_cfg_buf_size; i++) res_buf_[i] = 'X'; res_buf_[i] = 0; }
static void worker_thread(void *arg) { THREAD_CTX *ctx = (THREAD_CTX*) arg; /* 获得用户自定义对象 */ unsigned int i = 0; static __thread ACL_VSTRING *buf1 = NULL; static __thread ACL_VSTRING *buf2 = NULL; /* 仅是验证参数传递过程 */ assert(ctx->thr_pool == __thr_pool); if (buf1 == NULL) buf1 = acl_vstring_alloc(256); if (buf2 == NULL) buf2 = acl_vstring_alloc(256); acl_vstring_sprintf(buf1, "buf1: tid=%u", (unsigned int) acl_pthread_self()); acl_vstring_sprintf(buf2, "buf2: tid=%u", (unsigned int) acl_pthread_self()); /* 注册函数,当该线程退出时自动释放 buf 内存空间 */ acl_pthread_atexit_add(buf1, free_buf_fn); acl_pthread_atexit_add(buf2, free_buf_fn); while (i < 5) { if (__local != i) acl_msg_fatal("__local=%d invalid", __local); printf("thread id=%u, i=%d, __local=%d\r\n", (unsigned int) acl_pthread_self(), ctx->i, __local); i++; /* 在本线程中将线程局部变量加1 */ __local++; sleep(1); } acl_myfree(ctx); /* 至此,该工作线程进入空闲状态,直到空闲超时退出 */ }
static DWORD WINAPI RunThreadWrap(LPVOID data) #endif { acl_pthread_t *thread = (acl_pthread_t *) data; void *return_arg; ACL_FIFO *tls_value_list_ptr = tls_value_list_get(); unsigned long *tid = 0; /* 只是为了避免与主线程的 h_thread->handle = handle 产生冲突 */ if (__thread_inited) acl_pthread_mutex_lock(&__thread_lock); if (__thread_inited) acl_pthread_mutex_unlock(&__thread_lock); thread->id = acl_pthread_self(); return_arg = (void*) thread->start_routine(thread->routine_arg); /* 释放由 acl_pthread_setspecific 添加的线程局部变量 */ while (1) { TLS_VALUE *tls_value = private_fifo_pop(tls_value_list_ptr); if (tls_value == NULL) break; if (tls_value->tls_key == NULL || tls_value->tls_key->destructor == NULL || tls_value->tls_key->key < 0 || tls_value->tls_key->key >= ACL_PTHREAD_KEYS_MAX) { acl_default_free(__FILE__, __LINE__, tls_value); continue; } tls_value->tls_key->destructor(tls_value->value); acl_default_free(__FILE__, __LINE__, tls_value); } private_fifo_free(tls_value_list_ptr, NULL); /* 如果线程创建时为分离方式则需要关闭线程句柄 */ if (thread->detached) { if (!CloseHandle(thread->handle)) { acl_msg_error("close handle error(%s)", acl_last_serror()); } } acl_default_free(__FILE__, __LINE__, thread); return (DWORD) return_arg; }
static void main_epoll_end(void) { const char *myname = "main_epoll_end"; if (main_epoll_ctx != NULL) { acl_msg_info("%s(%d), %s: close epoll_fd: %d, tid: %lu, %lu", __FILE__, __LINE__, myname, main_epoll_ctx->epfd, main_epoll_ctx->tid, acl_pthread_self()); close(main_epoll_ctx->epfd); acl_myfree(main_epoll_ctx); main_epoll_ctx = NULL; } }
static void *tls_calloc(size_t len) { void *ptr; (void) acl_pthread_once(&once_control, once_init); ptr = (void*) acl_pthread_getspecific(once_key); if (ptr == NULL) { ptr = acl_mycalloc(1, len); acl_pthread_setspecific(once_key, ptr); if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) __tls = ptr; } return ptr; }