int cp_heap_unset_mode(cp_heap *heap, int mode) { int rc; int nosync; if ((rc = cp_heap_txlock(heap))) return rc; nosync = heap->mode & COLLECTION_MODE_NOSYNC; /* handle the special case of unsetting NOSYNC */ if ((mode & COLLECTION_MODE_NOSYNC) && heap->lock == NULL) { if ((heap->lock = malloc(sizeof(cp_mutex))) == NULL) return -1; if ((rc = cp_mutex_init(heap->lock, NULL))) { free(heap->lock); heap->lock = NULL; return -1; } } heap->mode &= heap->mode ^ mode; if (!nosync) cp_heap_txunlock(heap); return 0; }
cp_heap *cp_heap_create_by_option(int mode, int initial_size, cp_compare_fn comp, cp_copy_fn copy, cp_destructor_fn dtr) { int rc; cp_heap *h = (cp_heap *) calloc(1, sizeof(cp_heap)); if (h == NULL) return NULL; if ((mode & COLLECTION_MODE_NOSYNC) == 0) { h->lock = malloc(sizeof(cp_mutex)); if (h->lock == NULL) { free(h); return NULL; } if ((rc = cp_mutex_init(h->lock, NULL))) { free(h->lock); free(h); return NULL; } } if (initial_size) { for (h->heap_length = 0; h->heap_length < initial_size; h->heap_height++) h->heap_length += LEVELSIZE(h->heap_height) + 1; if ((h->heap = malloc(h->heap_length * sizeof(void *))) == NULL) { cp_heap_destroy(h); return NULL; } } else { h->heap = NULL; h->heap_height = 0; h->heap_length = 0; } h->heap_end = 1; h->comp = comp; h->copy = copy; h->dtr = dtr; h->mode = mode; #ifdef __TRACE__ DEBUGMSG("cp_heap_create_by_option\n"); heap_info(h); #endif return h; }
cp_pooled_thread *cp_pooled_thread_create(cp_thread_pool *owner) { int rc; cp_pooled_thread *pt = calloc(1, sizeof(cp_pooled_thread)); if (pt == NULL) { cp_error(CP_MEMORY_ALLOCATION_FAILURE, "can\'t allocate pooled thread"); errno = ENOMEM; return NULL; } pt->worker = calloc(1, sizeof(cp_thread)); if (pt->worker == NULL) { cp_error(CP_MEMORY_ALLOCATION_FAILURE, "can\'t allocate thread"); errno = ENOMEM; return NULL; } pt->owner = owner; pt->suspend_lock = (cp_mutex *) malloc(sizeof(cp_mutex)); if (pt->suspend_lock == NULL) goto THREAD_CREATE_CANCEL; if ((rc = cp_mutex_init(pt->suspend_lock, NULL))) { cp_error(rc, "starting up pooled thread"); goto THREAD_CREATE_CANCEL; } pt->suspend_cond = (cp_cond *) malloc(sizeof(cp_cond)); if ((rc = cp_cond_init(pt->suspend_cond, NULL))) { cp_error(rc, "starting up pooled thread"); cp_mutex_destroy(pt->suspend_lock); free(pt->suspend_lock); goto THREAD_CREATE_CANCEL; } pt->done = 0; pt->wait = 1; cp_thread_create(*pt->worker, NULL, cp_pooled_thread_run, pt); pt->id = cp_pooled_thread_get_id(pt); cp_thread_detach(*pt->worker); //~~ check return pt; THREAD_CREATE_CANCEL: free(pt->worker); free(pt); return NULL; }
cp_thread_pool *cp_thread_pool_create(int min_size, int max_size) { int rc; cp_thread_pool *pool = calloc(1, sizeof(cp_thread_pool)); if (pool == NULL) cp_fatal(CP_MEMORY_ALLOCATION_FAILURE, "can\'t allocate thread pool structure"); pool->min_size = min_size; pool->max_size = max_size; pool->running = 1; pool->free_pool = cp_list_create(); if (pool->free_pool == NULL) cp_fatal(CP_MEMORY_ALLOCATION_FAILURE, "can\'t allocate thread pool list"); pool->in_use = cp_hashlist_create(10, cp_hash_long, cp_hash_compare_long); if (pool->in_use == NULL) cp_fatal(CP_MEMORY_ALLOCATION_FAILURE, "can\'t allocate thread pool running list"); pool->pool_lock = (cp_mutex *) malloc(sizeof(cp_mutex)); if (pool->pool_lock == NULL) { cp_error(CP_MEMORY_ALLOCATION_FAILURE, "can\'t create mutex"); goto THREAD_POOL_CREATE_CANCEL; } if ((rc = cp_mutex_init(pool->pool_lock, NULL))) { cp_error(rc, "can\'t create mutex"); goto THREAD_POOL_CREATE_CANCEL; } pool->pool_cond = (cp_cond *) malloc(sizeof(cp_cond)); if (pool->pool_cond == NULL) { cp_error(rc, "can\'t create condition variable"); cp_mutex_destroy(pool->pool_lock); free(pool->pool_lock); goto THREAD_POOL_CREATE_CANCEL; } if ((rc = cp_cond_init(pool->pool_cond, NULL))) { cp_error(rc, "can\'t create condition variable"); free(pool->pool_cond); cp_mutex_destroy(pool->pool_lock); free(pool->pool_lock); goto THREAD_POOL_CREATE_CANCEL; } for ( ; pool->size < pool->min_size; pool->size++) { cp_pooled_thread *pt = cp_pooled_thread_create(pool); if (pt == NULL) cp_fatal(CP_THREAD_CREATION_FAILURE, "can\'t create thread pool (created %d threads, minimum pool size is %d", pool->size, pool->min_size); cp_list_append(pool->free_pool, pt); } return pool; THREAD_POOL_CREATE_CANCEL: cp_list_destroy_custom(pool->free_pool, (cp_destructor_fn) cp_pooled_thread_destroy); cp_hashlist_destroy_custom(pool->in_use, NULL, (cp_destructor_fn) cp_pooled_thread_destroy); free(pool); return NULL; }
int main(int argc, char *argv[]) { int i; cp_thread w[COUNT]; cp_thread r[COUNT]; long total; int rc; if (argc > 1) silent = atoi(argv[1]); for (i = 0; i < COUNT; i++) { rc = cp_mutex_init(&lock[i], NULL); cp_cond_init(&cond[i], NULL); t[i] = cp_hashtable_create(10, cp_hash_string, cp_hash_compare_string); tl[i] = cp_list_create(); } rc = cp_mutex_init(&start_mutex, NULL); cp_cond_init(&start_cond, NULL); for (i = 0; i < COUNT; i++) cp_thread_create(r[i], NULL, reader, (void *) i); for (i = 0; i < COUNT; i++) cp_thread_create(w[i], NULL, writer, (void *) INSERTS); printf("press enter\n"); getchar(); cp_mutex_lock(&start_mutex); running = 1; total = time(NULL); cp_cond_broadcast(&start_cond); rc = cp_mutex_unlock(&start_mutex); if (rc == 0) write_err("MAIN"); for (i = 0; i < COUNT; i++) cp_thread_join(w[i], NULL); running = 0; for (i = 0; i < COUNT; i++) { cp_mutex_lock(&lock[i]); cp_cond_broadcast(&cond[i]); cp_mutex_unlock(&lock[i]); cp_thread_join(r[i], NULL); } total = time(NULL) - total; printf("\ndone in %ld seconds. tables should be empty now. press enter.\n", total); getchar(); for (i = 0; i < COUNT; i++) { printf("table %d: %ld items\n", i, cp_hashtable_count(t[i])); cp_hashtable_destroy(t[i]); printf("list %d: %ld items\n", i, cp_list_item_count(tl[i])); while (cp_list_item_count(tl[i])) { char *leftover = cp_list_remove_head(tl[i]); printf(" * %s\n", leftover); } cp_list_destroy(tl[i]); } printf("deleted them tables. press enter.\n"); getchar(); printf("bye.\n"); return 0; }