void *pe_workers_fetch_flow(void *arg) { static char mod[] = "pe_workers_fetch_flow"; pe_worker_t *this_worker = (pe_worker_t *) arg; void *work_item = NULL; DBUG_ENTER(mod); VLOG_INFO("Thread %i (%p) going to work.\n",this_worker->index, &this_worker->thread); /* infinite loop to process work items */ for(;;) { DBUG_PRINT("\nDEBUG ",("Thread %i (%d) calling ring_buffer_pop\n", this_worker->index, &this_worker->thread)); work_item = ring_buffer_pop(); DBUG_PRINT("\nDEBUG ",("Thread %i (%d) popped %p\n", this_worker->index, &this_worker->thread, work_item)); if (pe_get_crew_quit_status() == true) { VLOG_INFO("Thread %i got quit\n",this_worker->index); break; } pe_translate(work_item); } VLOG_INFO("Thread %i (%p) leaving work.\n",this_worker->index, this_worker->thread); DBUG_LEAVE; pthread_exit((void *) NULL); }
int main(int argc, const char *argv[]) { t_ring_buffer *r = NULL; int elem1 = 4; int elem2 = 6; int elem3 = 2; int elem4 = 3; gpointer oldelem = NULL; gpointer popelem = NULL; g_message("Test RingBuffer"); r = ring_buffer_new(2); g_assert(NULL != r); oldelem = ring_buffer_push(r, &elem1); g_assert(NULL == oldelem); g_assert(1 == ring_buffer_stored_elements(r)); oldelem = ring_buffer_push(r, &elem2); g_assert(NULL == oldelem); g_assert(2 == ring_buffer_stored_elements(r)); oldelem = ring_buffer_push(r, &elem3); g_assert(NULL != oldelem && *((int *)oldelem) == elem1); g_assert(2 == ring_buffer_stored_elements(r)); oldelem = ring_buffer_push(r, &elem4); g_assert(NULL != oldelem && *((int *)oldelem) == elem2); popelem = ring_buffer_pop(r); g_assert(NULL != popelem && *((int *)popelem) == elem4); popelem = ring_buffer_pop(r); g_assert(NULL != popelem && *((int *)popelem) == elem3); popelem = ring_buffer_pop(r); g_assert(NULL == popelem); g_assert(0 == ring_buffer_stored_elements(r)); r = ring_buffer_free(r); g_assert(NULL == r); g_message("Test RingBuffer complete"); return 0; }
static void test_pop_from_empty_buffer() { RingBuffer rb; _ringbuffer_init(&rb); assert_true(ring_buffer_pop(&rb) == NULL, "cannot pop from empty buffer"); ring_buffer_free(&rb); }
static void test_tail() { RingBuffer rb; TestData *td_tail; ring_buffer_alloc(&rb, sizeof(TestData), 103); _ringbuffer_fill2(&rb, 103, 0, TRUE); ring_buffer_pop(&rb); td_tail = ring_buffer_tail(&rb); td_tail->idx = 103; assert_true(ring_buffer_push(&rb) == td_tail, "Push should return last tail."); assert_test_data_idx_range_in(&rb, 1, 103); ring_buffer_free(&rb); }
static void test_elements_ordering() { RingBuffer rb; TestData *td; int start_from = 10; int cnt = 0; _ringbuffer_init(&rb); _ringbuffer_fill(&rb, capacity, start_from, TRUE); while ( (td = ring_buffer_pop(&rb)) ) { assert_true((cnt + start_from) == td->idx, "wrong order; %d != %d", cnt, td->idx); ++cnt; } ring_buffer_free(&rb); }
int main (int argc, const char* argv[]) { ring_buffer_t ring; ring_buffer_init(&ring, buf, sizeof(buf)); while (1) { printf("av: %d/%d\nhead=%ld, tail=%ld\n\n> ", ring_buffer_av_data(&ring), ring_buffer_av_space(&ring), ring.head - ring.buffer, ring.tail - ring.buffer ); size_t sz = 128; char* str = malloc(sz); int bytes = getline(&str, &sz, stdin); bytes--; // remove '\n' if (bytes > 0) { uint32_t pushed = ring_buffer_push(&ring, str, bytes); printf("push(%d) %d\n", bytes, pushed); } else if (bytes == 0) { uint32_t to_pop = 10; uint32_t popped = ring_buffer_pop(&ring, str, to_pop); printf("pop(%d) %d\n", to_pop, popped); if (popped > 0) { for (int i = 0; i < popped; i++) { printf("%c", str[i]); } printf("\n"); } } else if (bytes < 0) { return -1; } } return 0; }
static void test_pop_all_pushed_element_in_correct_order() { RingBuffer rb; int cnt = 0; const int start_from = 1; TestData *td = NULL; _ringbuffer_init(&rb); _ringbuffer_fill(&rb, capacity, 1, TRUE); while ((td = ring_buffer_pop(&rb))) { assert_true((cnt+start_from) == td->idx, "wrong order; %d != %d", td->idx, cnt); ++cnt; } assert_true(cnt == capacity, "cannot read all element, %d < %d", cnt, capacity); ring_buffer_free(&rb); }
/** read from beginning of queue (and remove that element) */ int pop(struct buffer *buffer) /*@ requires [?f]buffer(buffer, ?id_text, ?id_progress_read, ?id_progress_write) &*& token(id_progress_read, ?t1) &*& op(id_text, id_progress_read, t1, ?c, ?t2); @*/ /*@ ensures [f]buffer(buffer, id_text, id_progress_read, id_progress_write) &*& token(id_progress_read, t2) &*& result == c; @*/ { //@ open buffer(buffer, _, _, _); //@ assert [f]buffer->mutex |-> ?mutex; mutex_acquire(buffer->mutex); //@ open buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); //@ open token(id_progress_read, ?n_read); //@ assert [_]ghost_cell<list<int> >(id_text, ?alltext); while (ring_buffer_is_empty(buffer->ring_buffer)) /*@ invariant buffer->ring_buffer |-> ?ring_buffer &*& [f]buffer->mutex |-> mutex &*& ring_buffer(ring_buffer, ?size, ?contents) &*& [f]buffer->cond_can_pop |-> ?cond_can_pop &*& [f]mutex_cond(cond_can_pop, mutex) &*& mutex_held(mutex, (buffer_protected)(buffer, id_text, id_progress_read, id_progress_write), currentThread, f) &*& [_]ghost_cell<list<int> >(id_text, alltext) &*& [1/2]ghost_cell<int>(id_progress_write, ?n_write) &*& [1/2]ghost_cell<int>(id_progress_read, n_read) &*& [1/2]ghost_cell<int>(id_progress_read, n_read) &*& take(n_write - n_read, drop(n_read, alltext)) == contents ; @*/ { //@ close buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); mutex_cond_wait(buffer->cond_can_pop, buffer->mutex); //@ open buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); } bool was_full = ring_buffer_is_full(buffer->ring_buffer); int x = ring_buffer_pop(buffer->ring_buffer); if (was_full){ mutex_cond_signal(buffer->cond_can_push); } //@ ghost_cell_mutate(id_progress_read, t2); //@ close token(id_progress_read, t2); //@ open op(_, _, _, c, _); //@ assert c == nth(t1, alltext); //@ assert x == head(contents); //@ assert x == head(take(n_write - n_read, drop(n_read, alltext))); //@ assume (x == nth(n_read, alltext)); //@ assert c == x; //@ assert take(n_write - n_read, drop(n_read, alltext)) == contents; //@ assume (take(n_write - (n_read + 1), drop((n_read+1), alltext)) == tail(contents)); //@ close buffer_protected(buffer, id_text, id_progress_read, id_progress_write)(); mutex_release(buffer->mutex); //@ close [f]buffer(buffer, id_text, id_progress_read, id_progress_write); return x; }
/** * Reads one integer from the given queue. * * This is blocking. If the queue is empty, this function waits until the queue is not empty anymore. */ int getchar/*@<u> @*/(struct queue *queue, struct proph_tree *tree) //@ requires [?f_queue]queue(?queue_id, queue) &*& getchar_io<u>(queue_id, ?t1, ?c, ?t2, tree) &*& token(t1); //@ ensures [f_queue]queue(queue_id, queue) &*& token(t2) &*& result == c; { //@ open [f_queue]queue(_,_); //@ assert [f_queue]queue->mutex |-> ?mutex; // bind mutex so we know it won't change. mutex_acquire(queue->mutex); //@ open queue_invariant(queue_id, queue)(); //@ open token(t1); while (ring_buffer_is_empty(queue->ring_buffer)) /*@ invariant // from queue: [f_queue]queue->mutex |-> mutex &*& [f_queue]queue->cond_can_pop |-> ?cond_can_pop &*& [f_queue]mutex_cond(cond_can_pop, mutex) // from the mutex: &*& queue->ring_buffer |-> ?buffer &*& ring_buffer(buffer, _, ?buffer_contents) &*& [1/2]ghost_cell<list<int> >(queue_id, buffer_contents) &*& mutex_held(mutex, (queue_invariant)(queue_id, queue), currentThread, f_queue); @*/ { //@ close queue_invariant(queue_id, queue)(); mutex_cond_wait(queue->cond_can_pop, queue->mutex); //@ open queue_invariant(queue_id, queue)(); } bool was_full = ring_buffer_is_full(queue->ring_buffer); //@ open getchar_io(queue_id, t1, c, t2, _); int ret = ring_buffer_pop(queue->ring_buffer); //@ open proph_tree(_, _, _, _, _); prophecy_assign(tree->id, ret); free(tree); if (was_full){ mutex_cond_signal(queue->cond_can_push); } /*@ { predicate pre() = [1/2]ghost_cell<list<int> >(queue_id, buffer_contents) &*& c == head(buffer_contents) &*& token_without_invar(t1) &*& is_getchar_invar_updatable(?invar_updater, queue_id, t1, c, t2); predicate post() = [1/2]ghost_cell(queue_id, tail(buffer_contents)) &*& token_without_invar(t2); close pre(); produce_lemma_function_pointer_chunk(empty_lemma) : ghost_mutex_critical_section_t(place_io_invar(t1), pre, post)() { open pre(); assert is_getchar_invar_updatable(?invar_updater, queue_id, t1, c, t2); close exists(place_io_invar(t1)); open token_without_invar(t1); invar_updater(); close token_without_invar(t2); close post(); leak is_getchar_invar_updatable(_, _, _, _, _); call(); } { ghost_mutex_use(place_mutex(t1), pre, post); } open post(); } @*/ //@ close queue_invariant(queue_id, queue)(); mutex_release(queue->mutex); //@ close [f_queue]queue(queue_id, queue); return ret; }