void *reader(void *prm) { char *entry; int num = (int) prm; int total = 0; int rc; cp_mutex_lock(&start_mutex); while (!running) cp_cond_wait(&start_cond, &start_mutex); rc = cp_mutex_unlock(&start_mutex); if (rc == 0) write_err("reader"); while (running || cp_hashtable_count(t[num]) > 0) { cp_mutex_lock(&lock[num]); while (running && cp_list_is_empty(tl[num])) cp_cond_wait(&cond[num], &lock[num]); while ((entry = (char *) cp_list_remove_head(tl[num]))) { cp_hashtable_remove(t[num], entry); if (!silent) printf("[%d]: (%ld) entry: %s\n", num, cp_hashtable_count(t[num]), entry); total++; free(entry); } cp_mutex_unlock(&lock[num]); } printf("\n (-) reader %d: processed %d entries\n", num, total); return NULL; }
void *writer(void *prm) { int i, num; long count = (long) prm; char kbuf[30]; char *entry; cp_mutex_lock(&start_mutex); while (!running) cp_cond_wait(&start_cond, &start_mutex); cp_mutex_unlock(&start_mutex); for (i = 0; i < count; i++) { sprintf(kbuf, "ENTRY %d", i); entry = strdup(kbuf); num = i % COUNT; if (!silent) printf("writing (%d): %s\n", num, entry); cp_mutex_lock(&lock[i % COUNT]); cp_hashtable_put(t[num], entry, entry); cp_list_append(tl[num], entry); cp_cond_broadcast(&cond[i % COUNT]); cp_mutex_unlock(&lock[i % COUNT]); } return NULL; }
int cp_pooled_thread_run_task(cp_pooled_thread *pt, cp_thread_action action, void *prm) { #ifdef __TRACE__ DEBUGMSG("cp_pooled_thread_run_task: action %lx, prm %lx\n", (long) action, (long) prm); #endif pt->action = action; pt->action_prm = prm; if (action == NULL) { cp_error(CP_INVALID_FUNCTION_POINTER, "missing thread function"); return CP_INVALID_FUNCTION_POINTER; } /* signal thread to run */ cp_mutex_lock(pt->suspend_lock); pt->wait = 0; cp_cond_signal(pt->suspend_cond); cp_mutex_unlock(pt->suspend_lock); return 0; }
cp_thread *cp_thread_pool_get_impl(cp_thread_pool *pool, cp_thread_action action, void *action_prm, cp_thread_stop_fn stop_fn, void *stop_prm, int block) { cp_pooled_thread *pt = NULL; cp_mutex_lock(pool->pool_lock); #ifdef __TRACE__ DEBUGMSG("cp_thread_pool_get_impl (%d) pool size = %d max size = %d\n", block, pool->size, pool->max_size); #endif pt = cp_list_remove_head(pool->free_pool); if (pt == NULL) { if (pool->size < pool->max_size) { pt = cp_pooled_thread_create(pool); if (pt) pool->size++; } if (pt == NULL) /* no thread available and poolsize == max */ { if (!block) /* asked not to block, return NULL */ { cp_mutex_unlock(pool->pool_lock); return NULL; } /* wait for a thread to be released to the pool */ #ifdef _WINDOWS cp_mutex_unlock(pool->pool_lock); #endif while (pool->running && cp_list_is_empty(pool->free_pool)) cp_cond_wait(pool->pool_cond, pool->pool_lock); if (pool->running) pt = cp_list_remove_head(pool->free_pool); if (pt == NULL) /* shouldn't be happening except for shutdown */ { cp_mutex_unlock(pool->pool_lock); return NULL; } } } cp_hashlist_append(pool->in_use, &pt->id, pt); cp_mutex_unlock(pool->pool_lock); cp_pooled_thread_run_stoppable_task(pt, action, action_prm, stop_fn, stop_prm); return pt->worker; }
int cp_heap_lock(cp_heap *heap) { int rc; if ((heap->mode & COLLECTION_MODE_NOSYNC)) return EINVAL; if ((rc = cp_mutex_lock(heap->lock))) return rc; heap->txowner = cp_thread_self(); heap->mode |= COLLECTION_MODE_IN_TRANSACTION; return 0; }
int cp_heap_txlock(cp_heap *heap) { if (heap->mode & COLLECTION_MODE_NOSYNC) return 0; if (heap->mode & COLLECTION_MODE_IN_TRANSACTION) { cp_thread self = cp_thread_self(); if (cp_thread_equal(self, heap->txowner)) return 0; } errno = 0; return cp_mutex_lock(heap->lock); }
static int cp_thread_pool_set_available(cp_thread_pool *pool, cp_pooled_thread *thread) { cp_mutex_lock(pool->pool_lock); cp_hashlist_remove(pool->in_use, &thread->id); cp_list_append(pool->free_pool, thread); // pool->size--; cp_cond_signal(pool->pool_cond); cp_mutex_unlock(pool->pool_lock); return 0; }
int cp_thread_pool_wait(cp_thread_pool *pool) { while (cp_hashlist_item_count(pool->in_use) && pool->running) { cp_mutex_lock(pool->pool_lock); cp_cond_wait(pool->pool_cond, pool->pool_lock); if (pool->running && cp_hashlist_item_count(pool->in_use)) /* wake up someone else */ cp_cond_signal(pool->pool_cond); cp_mutex_unlock(pool->pool_lock); } return 0; }
void *cp_pooled_thread_run(void *prm) { cp_pooled_thread *pt = (cp_pooled_thread *) prm; #ifdef __TRACE__ DEBUGMSG("cp_pooled_thread (%lx) starts", (long) pt); #endif while (!pt->done && pt->owner->running) { cp_mutex_lock(pt->suspend_lock); while (pt->wait && (!pt->done) && pt->owner->running) cp_cond_wait(pt->suspend_cond, pt->suspend_lock); cp_mutex_unlock(pt->suspend_lock); if (pt->done || !pt->owner->running) break; #ifdef __TRACE__ DEBUGMSG("cp_pooled_thread_run: action is %lX, action_prm is %lX", pt->action, pt->action_prm); #endif if (pt->action) /* run user defined function if set */ { #ifdef __TRACE__ DEBUGMSG("pooled thread (%lX) handles action (%lX)", (long) pt, (long) pt->action); #endif (*pt->action)(pt->action_prm); } if (pt->done || !pt->owner->running) break; pt->wait = 1; /* performed work, notify pool */ cp_thread_pool_set_available(pt->owner, pt); } #ifdef __TRACE__ DEBUGMSG("cp_pooled_thread (%lx) exits", (long) pt); #endif cp_pooled_thread_destroy(pt); return NULL; }
int cp_pooled_thread_stop(cp_pooled_thread *pt) { int rc = 0; cp_mutex_lock(pt->suspend_lock); pt->action = NULL; if (pt->stop_fn) { rc = pt->stop_prm ? (*pt->stop_fn)(pt->stop_prm) : (*pt->stop_fn)(pt->action_prm); } pt->done = 1; pt->wait = 0; cp_cond_signal(pt->suspend_cond); cp_mutex_unlock(pt->suspend_lock); // cp_thread_join(*pt->worker, NULL); //~~ rc return rc; }
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; }