bool CLock::timed_lock(uint32_t millisecond) { int retval; if (0 == millisecond) { retval = pthread_mutex_lock(&_mutex); } else { struct timespec abstime; #if _POSIX_C_SOURCE >= 199309L clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += millisecond / 1000; abstime.tv_nsec += (millisecond % 1000) * 1000000; #else #endif // _POSIX_C_SOURCE struct timeval tv; if (-1 == gettimeofday(&tv, NULL)) throw CSyscallException(errno, __FILE__, __LINE__); abstime.tv_sec = tv.tv_sec; abstime.tv_nsec = tv.tv_usec * 1000; abstime.tv_sec += millisecond / 1000; abstime.tv_nsec += (millisecond % 1000) * 1000000; retval = pthread_mutex_timedlock(&_mutex, &abstime); } if (0 == retval) return true; if (ETIMEDOUT == retval) return false; throw CSyscallException(retval, __FILE__, __LINE__); }
SYS_NAMESPACE_BEGIN CLock::CLock(bool recursive) { int retval = 0; if (recursive) { #if defined(__linux) && !defined(__USE_UNIX98) const pthread_mutexattr_t attr = { PTHREAD_MUTEX_RECURSIVE_NP }; #else retval = pthread_mutexattr_init(&_attr); if (retval != 0) { throw CSyscallException(retval, __FILE__, __LINE__); } pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE); if (retval != 0) { pthread_mutexattr_destroy(&_attr); throw CSyscallException(retval, __FILE__, __LINE__); } #endif retval = pthread_mutex_init(&_mutex, &_attr); } else { retval = pthread_mutex_init(&_mutex, NULL); } if (retval != 0) { pthread_mutexattr_destroy(&_attr); throw CSyscallException(retval, __FILE__, __LINE__); } }
void CMMap::async_flush(mmap_t* ptr, size_t offset, size_t length, bool invalid) { // 无效参数 if (offset >= ptr->len) throw CSyscallException(EINVAL, __FILE__, __LINE__); int flags = invalid? MS_ASYNC|MS_INVALIDATE: MS_ASYNC; if (-1 == msync(((char*)(ptr->addr))+offset, (offset+length > ptr->len)? ptr->len-offset: length, flags)) throw CSyscallException(errno, __FILE__, __LINE__); }
mmap_t* CMMap::map_both(const char* filename, size_t size_max) { int fd = open(filename, O_RDONLY|O_WRONLY); if (-1 == fd) throw CSyscallException(errno, __FILE__, __LINE__); return do_map(PROT_READ|PROT_WRITE, fd, 0, 0, size_max, false); }
bool CLock::try_lock() { int retval = pthread_mutex_trylock(&_mutex); if (0 == retval) return true; if (EBUSY == retval) return false; throw CSyscallException(retval, __FILE__, __LINE__); }
SYS_NAMESPACE_BEGIN mmap_t* CMMap::map_read(const char* filename, size_t size_max) { int fd = open(filename, O_RDONLY); if (-1 == fd) throw CSyscallException(errno, __FILE__, __LINE__); return do_map(PROT_READ, fd, 0, 0, size_max, false); }
mmap_t* CMMap::do_map(int prot, int fd, size_t size, size_t offset, size_t size_max, bool byfd) { mmap_t* ptr = new mmap_t; try { struct stat st; if (-1 == fstat(fd, &st)) throw CSyscallException(errno, __FILE__, __LINE__); ptr->fd = byfd? -fd: fd; ptr->len = (0 == size)? ((size_t)st.st_size-offset): (size+offset > (size_t)st.st_size)? (size_t)st.st_size: (size+offset); ptr->addr = NULL; if ((0 == size_max) || (ptr->len < size_max)) { void* addr = mmap(NULL, ptr->len, prot, MAP_SHARED, fd, offset); if (MAP_FAILED == addr) throw CSyscallException(errno, __FILE__, __LINE__); ptr->addr = addr; } return ptr; } catch (CSyscallException& ex) { // 谁打开谁关闭 if (ptr->fd > -1) { close(ptr->fd); ptr->fd = -1; } delete ptr; throw; } }
void CMMap::unmap(mmap_t* ptr) { if (ptr->addr != NULL) { if (-1 == munmap(ptr->addr, ptr->len)) throw CSyscallException(errno, __FILE__, __LINE__); } // 谁打开谁关闭 if (ptr->fd > -1) { close(ptr->fd); ptr->fd = -1; } delete ptr; }
void CLock::unlock() { int retval = pthread_mutex_unlock(&_mutex); if (retval != 0) throw CSyscallException(retval, __FILE__, __LINE__); }