//返回当前信号灯的当前值, 很遗憾,WINDOWS下不支持,ReleaseSemaphore有类似功能,但是lReleaseCount参数不能为0 //如果用ReleaseSemaphore和WaitForSingleObject拼凑一个那么可能更超级糟糕, //微软的API实现的真烂。Visual studio也承诺增加这个特性,但是在2010版本是不要做指望了。 int ZCE_OS::sem_getvalue(sem_t *sem, int *sval) { #if defined (ZCE_OS_WINDOWS) ZCE_UNUSED_ARG(sem); ZCE_UNUSED_ARG(sval); errno = EINVAL; return -1; #elif defined (ZCE_OS_LINUX) return ::sem_getvalue(sem, sval); #endif }
//初始化读写锁对象 int ZCE_LIB::pthread_rwlock_initex(pthread_rwlock_t *rwlock, bool use_win_slim, bool priority_to_write) { int result = 0; pthread_rwlockattr_t attr; #if defined ZCE_OS_WINDOWS attr.priority_to_write_ = priority_to_write; //如果支持2008才能设置这个变量 #if defined ZCE_SUPPORT_WINSVR2008 && ZCE_SUPPORT_WINSVR2008 == 1 rwlock->use_win_slim_ = use_win_slim; #else rwlock->use_win_slim_ = false; ZCE_UNUSED_ARG(use_win_slim); #endif #elif defined ZCE_OS_LINUX ZCE_UNUSED_ARG(use_win_slim); ZCE_UNUSED_ARG(priority_to_write); //其实我在想,不如搞个NULL,其实都一样 result = ::pthread_rwlockattr_init(&attr); if (result != 0) { return result; } result = ::pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); if (result != 0) { return result; } #endif result = ZCE_LIB::pthread_rwlock_init(rwlock, &attr); if (result != 0) { return result; } return 0; }
int test_hashtable(int /*argc*/ , char * /*argv*/ []) { size_t numnode = 100,real_num=0; size_t szalloc = ZCE_LIB::shm_hashtable <int, int >::getallocsize(numnode, real_num); std::cout << "need mem: " << (int)szalloc << " num of node:" << (int)real_num << std::endl; std::cout << "sizeof smem_hashtable:" << sizeof(ZCE_LIB::shm_hashtable <int, int >) << std::endl; char *tmproom = new char [szalloc + 4]; memset(tmproom, 0, szalloc + 4); ZCE_LIB::shm_hashtable<int, int >* pmmap = ZCE_LIB::shm_hashtable<int, int >::initialize(numnode, real_num,tmproom); pmmap->insert_unique(1001); ZCE_LIB::shm_hashtable<int, int >::iterator it = pmmap->find_value(1001); std::cout << "it serial: " << (int)(it.getserial()) << std::endl; bool bdel = pmmap->erase_unique(1001); it = pmmap->find_value(1002); bdel = pmmap->erase_unique(1001); std::cout << "it serial: " << (int)(it.getserial()) << std::endl; if (it == pmmap->end()) { std::cout << "Not Fount." << std::endl; } ZCE_UNUSED_ARG(bdel); return 0; }
virtual void on_run(void *outer_data, bool &continue_run) { ZCE_UNUSED_ARG(outer_data); switch (get_stage()) { case FMS1_STAGE_1: std::cout << "FSM1 stage " << get_stage() << " start."<< std::endl; continue_run = true; set_stage(FMS1_STAGE_2); break; case FMS1_STAGE_2: std::cout << "FSM1 stage " << get_stage() << std::endl; continue_run = true; set_stage(FSM1_STAGE_3); break; case FSM1_STAGE_3: std::cout << "FSM1 stage " << get_stage() << std::endl; continue_run = true; set_stage(FSM1_STAGE_4); break; case FSM1_STAGE_4: std::cout << "FSM1 stage " << get_stage() << " end."<<std::endl; continue_run = false; break; default: //一个无法识别的状态 ZCE_ASSERT(false); break; } return; }
int ZCE_Event_INotify::rm_watch(ZCE_HANDLE watch_handle) { #if defined (ZCE_OS_LINUX) //先用句柄查询 HDL_TO_EIN_MAP::iterator iter_del = watch_event_map_.find(watch_handle); if (iter_del == watch_event_map_.end()) { return -1; } int ret = ::inotify_rm_watch(inotify_handle_, iter_del->second.watch_handle_); if (ret != 0) { return -1; } //从MAP中删除这个NODe watch_event_map_.erase(iter_del); return 0; #elif defined (ZCE_OS_WINDOWS) ZCE_UNUSED_ARG(watch_handle); if (watch_handle_ != ZCE_INVALID_HANDLE) { //从反应器移除 reactor()->remove_handler(this, false); ::CloseHandle(watch_handle_); watch_handle_ = ZCE_INVALID_HANDLE; watch_path_[0] = '\0'; } return 0; #endif }
//用于测试某些特殊情况的代码。 int test_timer_expire2(int /*argc*/, char * /*argv*/ []) { ZCE_Timer_Queue_Base::instance(new ZCE_Timer_Wheel(1024)); Test_Timer_Handler test_timer[10]; int timer_id[10]; ZCE_Time_Value delay_time(1, 0); ZCE_Time_Value interval_time(1, 0); for (size_t i = 0; i < TEST_TIMER_NUMBER; ++i) { delay_time.sec(i); timer_id[i] = ZCE_Timer_Queue_Base::instance()->schedule_timer(&test_timer[i], &TEST_TIMER_ACT[i], delay_time, interval_time); } //一些特殊情况下,定时器很长时间无法触发,导致的问题 for (size_t j = 0; j < 100000; j++) { ZCE_LIB::sleep(60); ZCE_Timer_Queue_Base::instance()->expire(); } ZCE_UNUSED_ARG(timer_id); return 0; }
//打开(有名)信号灯,最大值不是标准参数,所以用默认只修饰了,这个主要用于创建有名信号灯, //打开后,要使用sem_close,sem_unlink sem_t *ZCE_OS::sem_open(const char *name, int oflag, mode_t mode, unsigned int init_value, unsigned int max_val) { #if defined (ZCE_OS_WINDOWS) ZCE_UNUSED_ARG (oflag); ZCE_UNUSED_ARG (mode); //为了保存变量还是先new出来 sem_t *ret_sem = new sem_t (); ret_sem->sem_unnamed_ = false; HANDLE sem_handle = ::CreateSemaphoreA(NULL, init_value, max_val, name); if (sem_handle == 0) { delete ret_sem; ret_sem = NULL; return SEM_FAILED; } else { // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary. errno = ::GetLastError (); ret_sem->sem_hanlde_ = sem_handle; return ret_sem; } #elif defined (ZCE_OS_LINUX) //非标准参数 ZCE_UNUSED_ARG(max_val); return ::sem_open (name, oflag, mode, init_value); #endif }
//删除信号灯 int ZCE_OS::sem_unlink(const char *name) { #if defined (ZCE_OS_WINDOWS) ZCE_UNUSED_ARG (name); return 0; #elif defined (ZCE_OS_LINUX) return ::sem_unlink(name); #endif }
//互斥量属性销毁 int ZCE_LIB::pthread_mutexattr_destroy(pthread_mutexattr_t *attr) { #if defined (ZCE_OS_WINDOWS) ZCE_UNUSED_ARG(attr); return 0; #elif defined (ZCE_OS_LINUX) return ::pthread_mutexattr_init (attr); #endif }
int ZCE_OS::pthread_condattr_destroy(pthread_condattr_t *attr) { #if defined (ZCE_OS_WINDOWS) ZCE_UNUSED_ARG(attr); return 0; #elif defined (ZCE_OS_LINUX) return ::pthread_condattr_destroy (attr); #endif }
ZCE_Mysql_STMT_Command::~ZCE_Mysql_STMT_Command() { if ( NULL != mysql_stmt_) { int tmpret = ::mysql_stmt_free_result(mysql_stmt_); tmpret = ::mysql_stmt_close(mysql_stmt_); ZCE_UNUSED_ARG(tmpret); } }
int test_nonr_thread_mutex(int, char * []) { ZCE_Thread_NONR_Mutex abc; abc.lock(); int last_error = ZCE_LIB::last_error(); abc.lock(); last_error = ZCE_LIB::last_error(); ZCE_UNUSED_ARG(last_error); return 0; }
//对一个线程进行松绑 int ZCE_OS::pthread_detach(ZCE_THREAD_ID threadid) { #if defined (ZCE_OS_WINDOWS) //Windows线程本来就是detach的,呵呵 ZCE_UNUSED_ARG(threadid); return 0; #endif //#if defined (ZCE_OS_WINDOWS) #if defined (ZCE_OS_LINUX) return ::pthread_detach (threadid); #endif //#if defined (ZCE_OS_LINUX) }
//初始化,创建一个无名(匿名)信号灯,对应的销毁函数sem_destroy int ZCE_OS::sem_init(sem_t *sem, int pshared, unsigned int init_value, unsigned int max_val) { #if defined (ZCE_OS_WINDOWS) //字符串长度为0表示是匿名信号灯 sem->sem_unnamed_ = true; ZCE_UNUSED_ARG (pshared); HANDLE sem_handle = ::CreateSemaphoreA(NULL, init_value, max_val, NULL); if (sem_handle == 0) { return -1; } else { // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary. errno = ::GetLastError (); sem->sem_hanlde_ = sem_handle; return 0; } #elif defined (ZCE_OS_LINUX) // //非标准参数 ZCE_UNUSED_ARG(max_val); return ::sem_init (sem, pshared, init_value); #endif }
int ZCE_LIB::exchage_coroutine(coroutine_t *save_hdl, coroutine_t *goto_hdl) { #if defined ZCE_OS_WINDOWS // ZCE_UNUSED_ARG(save_hdl); ::SwitchToFiber(goto_hdl->coroutine_); return 0; #elif defined ZCE_OS_LINUX return ::swapcontext(&save_hdl->coroutine_, &goto_hdl->coroutine_); #endif }
int Comm_Timer_Handler::handle_timeout(const ZCE_Time_Value &now_time, const void *act /*= 0*/) { ZCE_UNUSED_ARG(act); // 定时更新时间 update_time(now_time); // reload配置 notify_reload(); // 处理监控 check_monitor(now_time); return SOAR_RET::SOAR_RET_SUCC; }
//初始化条件变量对象,不同的平台给不同的默认定义 //非标准,但是建议你使用,简单多了, //如果要多进程共享,麻烦你老给个名字,同时在LINUX平台下,你必须pthread_condattr_t放入共享内存 int ZCE_LIB::pthread_cond_initex(pthread_cond_t *cond, bool win_mutex_or_sema) { //前面有错误返回, int result = 0; pthread_condattr_t attr; result = ZCE_LIB::pthread_condattr_init (&attr); if (0 != result) { return result; } //这个是我在WINDOWS下用的,用于某些时候我可以用临界区,而不是更重的互斥量 #if defined (ZCE_OS_WINDOWS) //默认还是用递归的锁 attr.outer_lock_type_ |= PTHREAD_MUTEX_RECURSIVE; if (win_mutex_or_sema) { attr.outer_lock_type_ |= PTHREAD_MUTEX_TIMEOUT; } #elif defined (ZCE_OS_LINUX) ZCE_UNUSED_ARG(win_mutex_or_sema); result = ::pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); if (0 != result) { return result; } #endif result = ZCE_LIB::pthread_cond_init(cond, &attr); ZCE_LIB::pthread_condattr_destroy (&attr); if (0 != result) { return EINVAL; } return 0; }
int initialize(size_t data_number, bool if_restore) { int ret = 0; data_number_ = data_number; size_t malloc_size = HASH_TABLE_MY_DATA::getallocsize(data_number, data_number_); ret = mmap_file_.open("./LUX_DATA_.MMAP", malloc_size); hash_my_data_ = HASH_TABLE_MY_DATA::initialize(data_number, data_number_, (char *)(mmap_file_.addr()), if_restore); if (hash_my_data_) { return -1; } ZCE_UNUSED_ARG(ret); return 0; }
//超时处理 int Server_Timer_Base::timer_timeout(const ZCE_Time_Value &now_time, const void *act ) { ZCE_UNUSED_ARG(act); //记录当前时间, now_time_ = now_time; const int timeid = *(static_cast<const int *>(act)); if (SERVER_TIMER_ID[0] == timeid) { ++heartbeat_counter_; heart_total_mesc_ = heartbeat_counter_ * heart_precision_.total_msec(); // 处理监控 check_monitor(now_time); } return 0; }
//destructor 参数对于WIN32平台没有用,建议不用。 // int ZCE_OS::pthread_key_create(pthread_key_t *key, void (*destructor)(void *)) { #if defined (ZCE_OS_WINDOWS) ZCE_UNUSED_ARG(destructor); *key = ::TlsAlloc (); //如果返回FALSE标识失败 if (TLS_OUT_OF_INDEXES == *key) { errno = GetLastError(); return -1; } return 0; #elif defined (ZCE_OS_LINUX) // return ::pthread_key_create(key, destructor); #endif }
int test_lru_hashtable2(int /*argc*/ , char * /*argv*/ []) { size_t numnode = 100, real_num = 0; size_t num_count = 0; size_t szalloc = ZCE_LIB::shm_hashtable_expire <int, int >::getallocsize(numnode, real_num); std::cout << "need mem: " << (int)szalloc << " num of node:" << (int)numnode << std::endl; std::cout << "sizeof :" << sizeof(ZCE_LIB::shm_hashtable_expire <int, int >) << std::endl; char *tmproom = new char [szalloc + 4]; memset(tmproom, 0, szalloc + 4); // ZCE_LIB::shm_hashtable_expire<int, int >* pmmap = ZCE_LIB::shm_hashtable_expire<int, int >::initialize(numnode, real_num, tmproom); pmmap->insert_unique(1001, static_cast<unsigned int>(time(NULL))); pmmap->insert_unique(38636, static_cast<unsigned int>(time(NULL))); pmmap->insert_unique(36384378, static_cast<unsigned int>(time(NULL))); pmmap->insert_unique(65231237, static_cast<unsigned int>(time(NULL))); num_count = pmmap->count(1001); ZCE_LIB::shm_hashtable_expire<int, int >::iterator it_tmp = pmmap->begin(); ZCE_LIB::shm_hashtable_expire<int, int >::iterator it_end = pmmap->end(); for (; it_tmp != it_end; ++it_tmp) { std::cout << "it_tmp value: " << (*it_tmp) << std::endl; } pmmap->active_unique(1001, static_cast<unsigned int>(time(NULL))); it_tmp = pmmap->begin(); for (; it_tmp != it_end; ++it_tmp) { std::cout << "it_tmp value: " << (*it_tmp) << std::endl; } ZCE_UNUSED_ARG(num_count); return 0; }
//设置线程的属性,不同的平台给不同的默认定义 //非标准,但是建议你使用,简单多了, //如果要多进程共享,麻烦你老给个名字,同时在LINUX平台下,你必须pthread_mutex_t放入共享内存 int ZCE_LIB::pthread_mutex_initex(pthread_mutex_t *mutex, bool process_share, bool recursive, bool need_timeout, const char *mutex_name) { //前面有错误返回, int result = 0; pthread_mutexattr_t attr; result = ZCE_LIB::pthread_mutexattr_init (&attr); if (0 != result) { return result; } int lock_shared = 0; if (process_share) { lock_shared = PTHREAD_PROCESS_SHARED; //进程共享,必须有个名字,WIN和LINUX都必须一样,LINUX下用名字创建共享内存 if (mutex_name) { #if defined (ZCE_OS_WINDOWS) strncpy(attr.mutex_name_, mutex_name, PATH_MAX); #endif } } else { lock_shared = PTHREAD_PROCESS_PRIVATE; } //设置共享属性 result = ZCE_LIB::pthread_mutexattr_setpshared(&attr, lock_shared); if (0 != result) { ZCE_LIB::pthread_mutexattr_destroy (&attr); return -1; } int lock_type = 0; if ( recursive ) { lock_type |= PTHREAD_MUTEX_RECURSIVE; } //这个是我在WINDOWS下用的,用于某些时候我可以用临界区,而不是更重的互斥量 #if defined (ZCE_OS_WINDOWS) if (need_timeout) { lock_type |= PTHREAD_MUTEX_TIMEOUT; } #else ZCE_UNUSED_ARG(need_timeout); #endif //设置属性 result = ZCE_LIB::pthread_mutexattr_settype(&attr, lock_type); if (0 != result) { ZCE_LIB::pthread_mutexattr_destroy (&attr); return result; } result = ZCE_LIB::pthread_mutex_init(mutex, &attr); ZCE_LIB::pthread_mutexattr_destroy (&attr); if (0 != result) { return result; } return 0; }
int ZCE_LIB::backtrace_stack(ZCE_LOG_PRIORITY dbg_lvl, const char *dbg_info) { //跟踪函数的层数 const size_t SIZE_OF_BACKTRACE_FUNC = 100; #if defined(ZCE_OS_LINUX) ZCE_LOG(dbg_lvl, "[BACKTRACE]This program compiled by Linux GCC. %s", dbg_info); //Windows 下必须是2008或者VISTA之后的SDK才支持, #elif defined(ZCE_OS_WINDOWS) && ZCE_SUPPORT_WINSVR2008 == 1 ZCE_LOG(dbg_lvl, "[BACKTRACE]This program compiled by Windows Visual studio .%s", dbg_info); #else ZCE_UNUSED_ARG(SIZE_OF_BACKTRACE_FUNC); ZCE_LOG(dbg_lvl, "[BACKTRACE]back_trace_stack don't support this system.%s", dbg_info); #endif //这个方法是提供给Linux 下的GCC使用的 #if defined(ZCE_OS_LINUX) void *backtrace_buffer[SIZE_OF_BACKTRACE_FUNC]; char **symbols_strings; int sz_of_stack = ::backtrace(backtrace_buffer, SIZE_OF_BACKTRACE_FUNC); // symbols_strings = ::backtrace_symbols(backtrace_buffer, sz_of_stack); if (symbols_strings == NULL) { ZCE_LOG(dbg_lvl, "%s", "[BACKTRACE] backtrace_symbols return fail."); } //打印所有的堆栈信息,有些时候信息无法显示符号表,建议使用 for (int j = 0; j < sz_of_stack; j++) { ZCE_LOG(dbg_lvl, "[BACKTRACE] %u, %s.", j + 1, symbols_strings[j]); } //释放空间 ::free(symbols_strings); #elif defined(ZCE_OS_WINDOWS) && ZCE_SUPPORT_WINSVR2008 == 1 //我还没有时间看完dbghelp所有的东西,目前的代码参考后一个版本居多,目前这个东东必须有pdb文件, //http://blog.csdn.net/skies457/article/details/7201185 // Max length of symbols' name. const size_t MAX_NAME_LENGTH = 256; // Store register addresses. CONTEXT context; // Call stack. STACKFRAME64 stackframe; // Handle to current process & thread. HANDLE process, cur_thread; // Generally it can be subsitituted with 0xFFFFFFFF & 0xFFFFFFFE. // Debugging symbol's information. PSYMBOL_INFO symbol; // Source information (file name & line number) IMAGEHLP_LINE64 source_info; // Source line displacement. DWORD displacement; // Initialize PSYMBOL_INFO structure. // Allocate a properly-sized block. symbol = (PSYMBOL_INFO)malloc(sizeof(SYMBOL_INFO) + (MAX_NAME_LENGTH) * sizeof(char)); memset(symbol, 0, sizeof(SYMBOL_INFO) + (MAX_NAME_LENGTH) * sizeof(TCHAR)); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); // SizeOfStruct *MUST BE* set to sizeof(SYMBOL_INFO). symbol->MaxNameLen = MAX_NAME_LENGTH; // Initialize IMAGEHLP_LINE64 structure. memset(&source_info, 0, sizeof(IMAGEHLP_LINE64)); source_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64); // Initialize STACKFRAME64 structure. RtlCaptureContext(&context); // Get context. memset(&stackframe, 0, sizeof(STACKFRAME64)); // Fill in register addresses (EIP, ESP, EBP). stackframe.AddrPC.Mode = AddrModeFlat; stackframe.AddrStack.Mode = AddrModeFlat; stackframe.AddrFrame.Mode = AddrModeFlat; #if defined ZCE_WIN32 stackframe.AddrPC.Offset = context.Eip; stackframe.AddrStack.Offset = context.Esp; stackframe.AddrFrame.Offset = context.Ebp; #elif defined ZCE_WIN64 stackframe.AddrPC.Offset = context.Rip; stackframe.AddrStack.Offset = context.Rsp; stackframe.AddrFrame.Offset = context.Rbp; #else #endif // Get current process & thread. process = GetCurrentProcess(); cur_thread = GetCurrentThread(); // Initialize dbghelp library. if (!SymInitialize(process, NULL, TRUE)) { return -1; } //这些空间是绝对足够的,我也不做详细的检查了 const size_t LINE_OUTLEN = 1024; char line_out[LINE_OUTLEN]; int use_len = 0; uint32_t k = 0; // Enumerate call stack frame. while (StackWalk64(IMAGE_FILE_MACHINE_I386, process, cur_thread, &stackframe, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { use_len = 0; // End reaches. if (stackframe.AddrFrame.Offset == 0 || k > SIZE_OF_BACKTRACE_FUNC) { break; } // Get symbol. if (SymFromAddr(process, stackframe.AddrPC.Offset, NULL, symbol)) { use_len += snprintf(line_out + use_len, LINE_OUTLEN - use_len, " %s", symbol->Name); } if (SymGetLineFromAddr64(process, stackframe.AddrPC.Offset, &displacement, &source_info)) { // Get source information. use_len += snprintf(line_out + use_len, LINE_OUTLEN - use_len, "\t[ %s: %d] at addr 0x % 08LX", source_info.FileName, source_info.LineNumber, stackframe.AddrPC.Offset); } else { // If err_code == 0x1e7, no symbol was found. if (GetLastError() == 0x1E7) { use_len += snprintf(line_out + use_len, LINE_OUTLEN - use_len, "%s", "\tNo debug symbol loaded for this function."); } } ZCE_LOG(dbg_lvl, "[BACKTRACE] %u, %s.", k + 1, line_out); ++k; } SymCleanup(process); // Clean up and exit. free(symbol); #endif // return 0; }