/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_print(tb_char_t const* string) { // check tb_check_return(string); // print to the ios device log asl_log(tb_null, tb_null, ASL_LEVEL_WARNING, "[%08x]: %s", (tb_uint32_t)tb_thread_self(), string); // print to the stdout fputs(string, stdout); }
tb_void_t tb_thread_store_setp(tb_thread_store_data_t const* data) { // enter lock tb_spinlock_enter(&g_lock); // get data if (g_store) tb_hash_map_insert(g_store, (tb_pointer_t)tb_thread_self(), data); // leave lock tb_spinlock_leave(&g_lock); }
static tb_int_t tb_demo_thread_local_stub(tb_cpointer_t priv) { // self tb_size_t self = tb_thread_self(); // trace tb_trace_i("thread[%lx]: init", self); // trace tb_trace_i("thread[%lx]: exit", self); // ok return 0; }
tb_thread_store_data_ref_t tb_thread_store_getp() { // init data tb_pointer_t data = tb_null; // enter lock tb_spinlock_enter(&g_lock); // get data if (g_store) data = tb_hash_map_get(g_store, (tb_pointer_t)tb_thread_self()); // leave lock tb_spinlock_leave(&g_lock); // ok? return (tb_thread_store_data_ref_t)data; }
static tb_int_t tb_demo_thread_local_test(tb_cpointer_t priv) { // self tb_size_t self = tb_thread_self(); // trace tb_trace_i("thread[%lx]: init", self); // init the thread local, only once static tb_thread_local_t s_local = TB_THREAD_LOCAL_INIT; if (!tb_thread_local_init(&s_local, tb_demo_thread_local_free)) return -1; // init start time tb_hong_t time = tb_mclock(); // done __tb_volatile__ tb_size_t count = 10000000; while (count--) { // attempt to get local variable tb_size_t local; if (!(local = (tb_size_t)tb_thread_local_get(&s_local))) { // init local variable if (tb_thread_local_set(&s_local, (tb_cpointer_t)self)) local = self; } // check if (local != self) { // trace tb_trace_i("thread[%lx]: invalid value: %lx", self, local); } } // compile the interval time time = tb_mclock() - time; // trace tb_trace_i("thread[%lx]: exit: %lld ms", self, time); // ok return 0; }
static tb_int_t tb_demo_loop(tb_cpointer_t priv) { // aicp tb_aicp_ref_t aicp = (tb_aicp_ref_t)priv; tb_size_t self = tb_thread_self(); // trace tb_trace_i("[loop: %lu]: init", self); // loop aicp if (aicp) tb_aicp_loop(aicp); // trace tb_trace_i("[loop: %lu]: exit", self); // exit return 0; }
static tb_void_t tb_demo_coroutine_listen(tb_cpointer_t priv) { // TODO: fix thundering herd issues tb_socket_ref_t sock = (tb_socket_ref_t)priv; while (tb_socket_wait(sock, TB_SOCKET_EVENT_ACPT, -1) > 0) { // accept client sockets tb_size_t count = 0; tb_socket_ref_t client = tb_null; while ((client = tb_socket_accept(sock, tb_null))) { // start client connection if (!tb_coroutine_start(tb_null, tb_demo_coroutine_client, client, TB_DEMO_STACKSIZE)) break; count++; } // trace tb_trace_d("[%#x]: listened %lu", tb_thread_self(), count); } }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ static tb_void_t tb_demo_thread_local_free(tb_cpointer_t priv) { tb_trace_i("thread[%lx]: free: %p", tb_thread_self(), priv); }
tb_void_t tb_trace_done_with_args(tb_char_t const* prefix, tb_char_t const* module, tb_char_t const* format, tb_va_list_t args) { // check tb_check_return(format); // enter tb_spinlock_enter_without_profiler(&g_lock); // done do { // check tb_check_break(g_mode); // init tb_char_t* p = g_line; tb_char_t* e = g_line + sizeof(g_line); // print prefix to file if ((g_mode & TB_TRACE_MODE_FILE) && g_file) { // print time to file tb_tm_t lt = {0}; if (p < e && tb_localtime(tb_time(), <)) p += tb_snprintf(p, e - p, "[%04ld-%02ld-%02ld %02ld:%02ld:%02ld]: ", lt.year, lt.month, lt.mday, lt.hour, lt.minute, lt.second); // print self to file if (p < e) p += tb_snprintf(p, e - p, "[%lx]: ", tb_thread_self()); } // append prefix tb_char_t* b = p; if (prefix && p < e) p += tb_snprintf(p, e - p, "[%s]: ", prefix); // append module if (module && p < e) p += tb_snprintf(p, e - p, "[%s]: ", module); // append format if (p < e) p += tb_vsnprintf(p, e - p, format, args); // append end if (p < e) *p = '\0'; e[-1] = '\0'; // print it if (g_mode & TB_TRACE_MODE_PRINT) tb_print(b); // print it to file if ((g_mode & TB_TRACE_MODE_FILE) && g_file) { // done tb_size_t size = p - g_line; tb_size_t writ = 0; while (writ < size) { // writ it tb_long_t real = tb_file_writ(g_file, (tb_byte_t const*)g_line + writ, size - writ); tb_check_break(real > 0); // save size writ += real; } } } while (0); // leave tb_spinlock_leave(&g_lock); }
static tb_long_t tb_aiop_ptor_spak(tb_aicp_ptor_impl_t* ptor, tb_handle_t loop, tb_aice_t* resp, tb_long_t timeout) { // check tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; tb_aicp_impl_t* aicp = impl? impl->base.aicp : tb_null; tb_assert_and_check_return_val(impl && impl->wait && aicp && resp, -1); // enter tb_spinlock_enter(&impl->lock); // done tb_long_t ok = -1; tb_bool_t null = tb_false; do { // check tb_assert_and_check_break(impl->spak[0] && impl->spak[1]); // clear ok ok = 0; // spak aice from the higher priority spak first if (!(null = tb_queue_null(impl->spak[0]))) { // get resp tb_aice_t const* aice = tb_queue_get(impl->spak[0]); if (aice) { // save resp *resp = *aice; // trace tb_trace_d("spak[%u]: code: %lu, priority: 0, size: %lu", (tb_uint16_t)tb_thread_self(), aice->code, tb_queue_size(impl->spak[0])); // pop it tb_queue_pop(impl->spak[0]); // ok ok = 1; } } // no aice? spak aice from the lower priority spak next if (!ok && !(null = tb_queue_null(impl->spak[1]))) { // get resp tb_aice_t const* aice = tb_queue_get(impl->spak[1]); if (aice) { // save resp *resp = *aice; // trace tb_trace_d("spak[%u]: code: %lu, priority: 1, size: %lu", (tb_uint16_t)tb_thread_self(), aice->code, tb_queue_size(impl->spak[1])); // pop it tb_queue_pop(impl->spak[1]); // ok ok = 1; } } } while (0); // leave tb_spinlock_leave(&impl->lock); // done it if (ok) ok = tb_aiop_spak_done(impl, resp); // null? wait it tb_check_return_val(!ok && null, ok); // killed? break it tb_check_return_val(!tb_atomic_get(&aicp->kill), -1); // trace tb_trace_d("wait[%u]: ..", (tb_uint16_t)tb_thread_self()); // wait some time if (tb_semaphore_wait(impl->wait, timeout) < 0) return -1; // timeout return 0; }