POCO中Event同步对象的POSIX实现

POCO1.4.1p1中Event同步对象的POSIX实现不够严谨,WIN32实现直接采用windows提供的event对象,而POSIX下采用条件变量模拟事件,但是没有考虑到cancellation point的问题,可能导致程序行为异常,下面代码注释的pthread_cleanup_push和pthread_cleanup_pop是我加上的,项目中放开这两个注释后暂时未重现异常问题。

 

void EventImpl::waitImpl() { //pthread_cleanup_push(pthread_mutex_unlock, &_mutex); if (pthread_mutex_lock(&_mutex)) throw SystemException("wait for event failed (lock)"); while (!_state) { if (pthread_cond_wait(&_cond, &_mutex)) { pthread_mutex_unlock(&_mutex); throw SystemException("wait for event failed"); } } if (_auto) _state = false; pthread_mutex_unlock(&_mutex); //pthread_cleanup_pop(0); } bool EventImpl::waitImpl(long milliseconds) { int rc = 0; struct timespec abstime; #if defined(__VMS) struct timespec delta; delta.tv_sec = milliseconds / 1000; delta.tv_nsec = (milliseconds % 1000)*1000000; pthread_get_expiration_np(&delta, &abstime); #elif defined(POCO_VXWORKS) clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += milliseconds / 1000; abstime.tv_nsec += (milliseconds % 1000)*1000000; if (abstime.tv_nsec >= 1000000000) { abstime.tv_nsec -= 1000000000; abstime.tv_sec++; } #else struct timeval tv; gettimeofday(&tv, NULL); abstime.tv_sec = tv.tv_sec + milliseconds / 1000; abstime.tv_nsec = tv.tv_usec*1000 + (milliseconds % 1000)*1000000; if (abstime.tv_nsec >= 1000000000) { abstime.tv_nsec -= 1000000000; abstime.tv_sec++; } #endif //pthread_cleanup_push(pthread_mutex_unlock, &_mutex); if (pthread_mutex_lock(&_mutex) != 0) throw SystemException("wait for event failed (lock)"); while (!_state) { if ((rc = pthread_cond_timedwait(&_cond, &_mutex, &abstime))) { if (rc == ETIMEDOUT) break; pthread_mutex_unlock(&_mutex); throw SystemException("cannot wait for event"); } } if (rc == 0 && _auto) _state = false; pthread_mutex_unlock(&_mutex); //pthread_cleanup_pop(0); return rc == 0; }

你可能感兴趣的:(POCO中Event同步对象的POSIX实现)