static void swRingBuffer_collect(swRingBuffer *object) { swRingBuffer_item *item; sw_atomic_t *free_count = &object->free_count; int count = object->free_count; int i; uint32_t n_size; for (i = 0; i < count; i++) { item = (swRingBuffer_item *) ((char *) object->memory + object->collect_offset); if (item->lock == 0) { n_size = item->length + sizeof(swRingBuffer_item); object->collect_offset += n_size; if (object->collect_offset + sizeof(swRingBuffer_item) > object->size || object->collect_offset >= object->size) { object->collect_offset = 0; object->status = 0; } sw_atomic_fetch_sub(free_count, 1); } else { break; } } }
PHP_METHOD(swoole_atomic, sub) { long sub_value = 1; sw_atomic_t *atomic = swoole_get_object(getThis()); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &sub_value) == FAILURE) { RETURN_FALSE; } RETURN_LONG(sw_atomic_fetch_sub(atomic, (uint32_t) sub_value)); }
int swRingQueue_pop(swRingQueue *queue, void **ele) { if (!(queue->num > 0)) return -1; int cur_head_index = queue->head; char * cur_head_flag_index = queue->flags + cur_head_index; while (!sw_atomic_cmp_set(cur_head_flag_index, 2, 3)) { cur_head_index = queue->head; cur_head_flag_index = queue->flags + cur_head_index; } //TODO 取模操作可以优化 int update_head_index = (cur_head_index + 1) % queue->size; sw_atomic_cmp_set(&queue->head, cur_head_index, update_head_index); *ele = *(queue->data + cur_head_index); sw_atomic_fetch_sub(cur_head_flag_index, 3); sw_atomic_fetch_sub(&queue->num, 1); return 0; }
static void* swThreadPool_loop(void *arg) { swThreadParam *param = arg; swThreadPool *pool = param->object; int id = param->pti; int ret; void *task; if (pool->onStart) { pool->onStart(pool, id); } while (SwooleG.running) { pool->cond.lock(&pool->cond); if (pool->shutdown) { pool->cond.unlock(&pool->cond); swTrace("thread [%d] will exit\n", id); pthread_exit(NULL); } if (pool->task_num == 0) { pool->cond.wait(&pool->cond); } swTrace("thread [%d] is starting to work\n", id); ret = swRingQueue_pop(&pool->queue, &task); pool->cond.unlock(&pool->cond); if (ret >= 0) { sw_atomic_t *task_num = &pool->task_num; sw_atomic_fetch_sub(task_num, 1); pool->onTask(pool, (void *) task, ret); } } if (pool->onStop) { pool->onStop(pool, id); } pthread_exit(NULL); return NULL; }
int swTableRow_del(swTable *table, char *key, int keylen) { swTableRow *row = swTable_hash(table, key, keylen); uint32_t crc32 = swoole_crc32(key, keylen); sw_atomic_t *lock = &row->lock; //no exists if (!row->active) { return SW_ERR; } sw_spinlock(lock); if (row->next == NULL) { if (row->crc32 == crc32) { table->rows_list[row->list_index] = NULL; if (table->iterator->skip_count > table->compress_threshold) { swTable_compress_list(table); } bzero(row, sizeof(swTableRow)); goto delete_element; } else { goto not_exists; } } else { swTableRow *tmp = row; swTableRow *prev = NULL; while (tmp) { if (tmp->crc32 == crc32) { break; } prev = tmp; tmp = tmp->next; } if (tmp == NULL) { not_exists: sw_spinlock_release(lock); return SW_ERR; } //when the deleting element is root, we should move the first element's data to root, //and remove the element from the collision list. if (tmp == row) { tmp = tmp->next; row->next = tmp->next; if (table->iterator->skip_count > table->compress_threshold) { swTable_compress_list(table); } memcpy(row->data, tmp->data, table->item_size); } if (prev) { prev->next = tmp->next; } table->lock.lock(&table->lock); bzero(tmp, sizeof(swTableRow)); table->pool->free(table->pool, tmp); table->lock.unlock(&table->lock); } delete_element: sw_atomic_fetch_sub(&(table->row_num), 1); sw_spinlock_release(lock); return SW_OK; }
int swTableRow_del(swTable *table, char *key, int keylen) { if (keylen > SW_TABLE_KEY_SIZE) { keylen = SW_TABLE_KEY_SIZE; } swTableRow *row = swTable_hash(table, key, keylen); //no exists if (!row->active) { return SW_ERR; } swTableRow_lock(row); if (row->next == NULL) { if (strncmp(row->key, key, keylen) == 0) { bzero(row, sizeof(swTableRow) + table->item_size); goto delete_element; } else { goto not_exists; } } else { swTableRow *tmp = row; swTableRow *prev = NULL; while (tmp) { if ((strncmp(tmp->key, key, keylen) == 0)) { break; } prev = tmp; tmp = tmp->next; } if (tmp == NULL) { not_exists: swTableRow_unlock(row); return SW_ERR; } //when the deleting element is root, we should move the first element's data to root, //and remove the element from the collision list. if (tmp == row) { tmp = tmp->next; row->next = tmp->next; memcpy(row->key, tmp->key, strlen(tmp->key)); memcpy(row->data, tmp->data, table->item_size); } if (prev) { prev->next = tmp->next; } table->lock.lock(&table->lock); bzero(tmp, sizeof(swTableRow) + table->item_size); table->pool->free(table->pool, tmp); table->lock.unlock(&table->lock); } delete_element: sw_atomic_fetch_sub(&(table->row_num), 1); swTableRow_unlock(row); return SW_OK; }
int swTableRow_del(swTable *table, char *key, int keylen) { swTableRow *row = swTable_hash(table, key, keylen); uint32_t crc32 = swoole_crc32(key, keylen); sw_atomic_t *lock = &row->lock; int i = 0; sw_spinlock(lock); if (row->active) { for (;; i++) { if (row->crc32 == crc32) { if (i > 0) { table->lock.lock(&table->lock); table->pool->free(table->pool, row); table->lock.unlock(&table->lock); } break; } else if (row->next == NULL) { sw_spinlock_release(lock); return SW_ERR; } else { row = row->next; } } #ifdef SW_TABLE_USE_LINKED_LIST if (row->list_prev != NULL) { row->list_prev->list_next = row->list_next; } else { table->head = row->list_next; } if (row->list_next != NULL) { row->list_next->list_prev = row->list_prev; } else { table->tail = row->list_prev; } if (table->iterator->tmp_row == row) { table->iterator->tmp_row = row->list_next; } #endif } if (row->active) { sw_atomic_fetch_sub(&(table->row_num), 1); } row->active = 0; sw_spinlock_release(lock); return SW_OK; }