swoole原始碼解析之swoole_lock的建立過程
阿新 • • 發佈:2018-12-13
swoole增加了鎖的實現,PHP程式碼中可以很方便地建立一個鎖,用來實現資料同步。swoole_lock類支援5種鎖的型別:
- 檔案鎖 SWOOLE_FILELOCK
- 讀寫鎖 SWOOLE_RWLOCK
- 訊號量 SWOOLE_SEM
- 互斥鎖 SWOOLE_MUTEX
- 自旋鎖 SWOOLE_SPINLOCK
下面我們介紹下其鎖的實現。
static PHP_METHOD(swoole_lock, __construct) { long type = SW_MUTEX; char *filelock; zend_size_t filelock_len = 0; int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ls", &type, &filelock, &filelock_len) == FAILURE) { RETURN_FALSE; } swLock *lock = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(swLock)); if (lock == NULL) { zend_throw_exception(swoole_exception_class_entry_ptr, "global memory allocation failure.", SW_ERROR_MALLOC_FAIL TSRMLS_CC); RETURN_FALSE; } switch(type) { #ifdef HAVE_RWLOCK case SW_RWLOCK: ret = swRWLock_create(lock, 1); break; #endif case SW_FILELOCK: if (filelock_len <= 0) { zend_throw_exception(swoole_exception_class_entry_ptr, "filelock requires file name of the lock.", SW_ERROR_INVALID_PARAMS TSRMLS_CC); RETURN_FALSE; } int fd; if ((fd = open(filelock, O_RDWR | O_CREAT, 0666)) < 0) { zend_throw_exception_ex(swoole_exception_class_entry_ptr, errno TSRMLS_CC, "open file[%s] failed. Error: %s [%d]", filelock, strerror(errno), errno); RETURN_FALSE; } ret = swFileLock_create(lock, fd); break; case SW_SEM: ret = swSem_create(lock, IPC_PRIVATE); break; #ifdef HAVE_SPINLOCK case SW_SPINLOCK: ret = swSpinLock_create(lock, 1); break; #endif case SW_MUTEX: default: ret = swMutex_create(lock, 1); break; } if (ret < 0) { zend_throw_exception(swoole_exception_class_entry_ptr, "failed to create lock.", errno TSRMLS_CC); RETURN_FALSE; } swoole_set_object(getThis(), lock); RETURN_TRUE; }
int swRWLock_create(swLock *lock, int use_in_process) { int ret; bzero(lock, sizeof(swLock)); lock->type = SW_RWLOCK; pthread_rwlockattr_init(&lock->object.rwlock.attr); if (use_in_process == 1) { pthread_rwlockattr_setpshared(&lock->object.rwlock.attr, PTHREAD_PROCESS_SHARED); } if ((ret = pthread_rwlock_init(&lock->object.rwlock._lock, &lock->object.rwlock.attr)) < 0) { return SW_ERR; } lock->lock_rd = swRWLock_lock_rd; lock->lock = swRWLock_lock_rw; lock->unlock = swRWLock_unlock; lock->trylock = swRWLock_trylock_rw; lock->trylock_rd = swRWLock_trylock_rd; lock->free = swRWLock_free; return SW_OK; }