Пример #1
0
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;
}
Пример #2
0
/*----------------------------------------------------------------------------*/
static void shf_ipi_receive_handler(int id, void* data, uint size)
{
    if (id == IPI_SHF) {
        //shf_print_bytes(data, size);
        SHF_LOG("IPI_SHF\n");
        ring_buffer_push(&trigger_buffer, data, size);
        notify();
    }
}
Пример #3
0
static void
test_push_to_full_buffer()
{
  RingBuffer rb;

  _ringbuffer_init(&rb);
  _ringbuffer_fill(&rb, capacity, 1, TRUE);
  assert_true(ring_buffer_push(&rb) == NULL, "cannot push to a full buffer");

  ring_buffer_free(&rb);
}
Пример #4
0
static void
_ringbuffer_fill(RingBuffer *rb, size_t n, int start_idx, gboolean ack)
{
  TestData *td;
  int i;

  for (i = 0; i < n; i++)
    {
      td = ring_buffer_push(rb);
      td->idx = start_idx + i;
      td->ack = ack;
    }
}
Пример #5
0
static void
_ringbuffer_fill2(RingBuffer *rb, size_t n, int start_idx, gboolean ack)
{
  TestData *td;
  int i;

  for (i = 0; i < n; i++)
    {
      td = ring_buffer_tail(rb);
      td->idx = start_idx + i;
      td->ack = ack;
      assert_true(ring_buffer_push(rb) == td, "Push should return last tail.");
    }
}
Пример #6
0
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);
}
Пример #7
0
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;
}
Пример #8
0
static void
test_ring_buffer_is_full()
{
  RingBuffer rb;
  int i;
  TestData *last = NULL;

  _ringbuffer_init(&rb);

  for (i = 1; !ring_buffer_is_full(&rb); i++)
    {
      TestData *td = ring_buffer_push(&rb);
      assert_true(td != NULL, "ring_buffer_push failed");
      td->idx = i;
      last = td;
    }

  assert_true(ring_buffer_count(&rb) == capacity, "buffer count(%d) is not equal to capacity(%d)", ring_buffer_count(&rb), capacity);
  assert_true(last->idx == capacity, "buffer is not full, number of inserted items: %d, capacity: %d", last->idx, capacity);

  ring_buffer_free(&rb);
}
Пример #9
0
static void
late_ack_tracker_track_msg(AckTracker *s, LogMessage *msg)
{
  LateAckTracker *self = (LateAckTracker *)s;
  LogSource *source = self->super.source;

  g_assert(self->pending_ack_record != NULL);

  log_pipe_ref((LogPipe *)source);

  msg->ack_record = (AckRecord *)self->pending_ack_record;

  _late_tracker_lock(self);
    {
      LateAckRecord *ack_rec;
      ack_rec = (LateAckRecord *)ring_buffer_push(&self->ack_record_storage);
      g_assert(ack_rec == self->pending_ack_record);
    }
  _late_tracker_unlock(self);

  self->pending_ack_record = NULL;
}
/** add to end of queue */
void push(struct buffer *buffer, int x)
/*@ requires
  [?f]buffer(buffer, ?id_text, ?id_progress_read, ?id_progress_write)
  &*& token(id_progress_write, ?t1)
  &*& op(id_text, id_progress_write, t1, x, ?t2);
@*/
/*@ ensures
  [f]buffer(buffer, id_text, id_progress_read, id_progress_write)
  &*& token(id_progress_write, t2);

@*/
{
  //@ 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_write, ?n_write);
  //@ assert [_]ghost_cell<list<int> >(id_text, ?alltext);
  while (ring_buffer_is_full(buffer->ring_buffer))
  /*@ invariant
      buffer->ring_buffer |-> ?ring_buffer
      &*& [f]buffer->mutex |-> mutex
      &*& ring_buffer(ring_buffer, ?size, ?contents)
      &*& [f]buffer->cond_can_push |-> ?cond_can_push
      &*& [f]mutex_cond(cond_can_push, 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_read, ?n_read)
      &*& [1/2]ghost_cell<int>(id_progress_write, n_write)
      &*& [1/2]ghost_cell<int>(id_progress_write, n_write)
      &*& 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_push, buffer->mutex);
    //@ open buffer_protected(buffer, id_text, id_progress_read, id_progress_write)();
  }
  
  bool was_empty = ring_buffer_is_empty(buffer->ring_buffer);

  ring_buffer_push(buffer->ring_buffer, x);

  if (was_empty){
    mutex_cond_signal(buffer->cond_can_pop);
  }
  
  
  //@ ghost_cell_mutate(id_progress_write, n_write + 1);
  //@ open op(_, _, _, _, _);
  //@ assert t2 == n_write + 1;
  
  //@ close token(id_progress_write, n_write + 1);
  
  //@ assert take(n_write - n_read, drop(n_read, alltext)) == contents;
  //@ assume (take(n_write+1 - n_read, drop(n_read, alltext)) == append(contents, cons(nth(n_write, alltext), nil)));
  
  //@ 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);
}
Пример #11
0
/* PUSH PUMP
 *
 * This is used to push data out to a blocking file descriptor. It pulls
 * data from a non-blocking pipe (pullfd) and pushes to STDOUT_FILENO
 * (pushfd).
 * When the pipe is closed, then the rest of the data is pushed out and then
 * STDOUT_FILENO is closed.
 *
 * The algorithm looks roughly like this:
 *
 *  while (true) {
 *    r = read(pipe) // nonblocking
 *
 *    while (!ring.empty) {
 *      write(STDOUT_FILENO) // blocking
 *    }
 *
 *    select(pipe, readable);
 *  }
 */
static void
push_pump (int pullfd, int pushfd)
{
    int r;
    ring_buffer ring;

    fd_set readfds, exceptfds;
    FD_ZERO(&exceptfds);
    FD_ZERO(&readfds);
    FD_SET(pullfd, &exceptfds);
    FD_SET(pullfd, &readfds);

    ring_buffer_init(&ring);

    /* The pipe is open or there is data left to be pushed out
     * NOTE: if pushfd (STDOUT_FILENO) ever errors out, then we just exit the
     * loop.
     */
    while (pullfd >= 0 || !ring_buffer_empty_p(&ring)) {

        /* Pull from the non-blocking pipe */
        r = ring_buffer_pull(&ring, pullfd);

        if (r == 0) {
            /* eof */
            close(pullfd);
            pullfd = -1;
        } else if (r < 0 && errno != EINTR && errno != EAGAIN) {
            perror("push_pump read()");
            close(pullfd);
            pullfd = -1;
            return;
        }

        /* Push everything out to STDOUT */
        while (!ring_buffer_empty_p(&ring)) {
            /* Blocking write() to pushfd (STDOUT_FILENO) */
            r = ring_buffer_push(&ring, pushfd);

            /* If there was a problem, just exit the entire function */

            if (r < 0 && errno != EINTR) {
                close(pushfd);
                close(pullfd);
                pushfd = pullfd = -1;
                return;
            }
        }

        if (pullfd >= 0) {
            /* select for readability on the pullfd */
            r = select(pullfd+1, &readfds, NULL, &exceptfds, NULL);

            if (r < 0 || FD_ISSET(pullfd, &exceptfds)) {
                close(pushfd);
                close(pullfd);
                pushfd = pullfd = -1;
                return;
            }
        }
    }
    /* If we got here then we got eof on pullfd and pushed all the data out.
     * so now just close pushfd */
    assert(pullfd < 0);
    assert(ring_buffer_empty_p(&ring));
    close(pushfd);
}
Пример #12
0
/* PULL PUMP
 *
 * This is used to read data from a blocking file descriptor and pump it into
 * a non-blocking pipe (or other non-blocking fd). The algorithm is this:
 *
 *   while (true) {
 *     read(STDIN_FILENO) // blocking
 *
 *     while (!ring.empty) {
 *       write(pipe) // non-blocking
 *       select(pipe, writable)
 *     }
 *   }
 *
 */
static void
pull_pump (int pullfd, int pushfd)
{
    int r;
    ring_buffer ring;

    fd_set writefds, exceptfds;
    FD_ZERO(&exceptfds);
    FD_ZERO(&writefds);
    FD_SET(pushfd, &exceptfds);
    FD_SET(pushfd, &writefds);

    ring_buffer_init(&ring);

    while (pullfd >= 0) {
        /* Blocking read from STDIN_FILENO */
        r = ring_buffer_pull(&ring, pullfd);

        if (r == 0) {
            /* eof */
            close(pullfd);
            pullfd = -1;
        } else if (r < 0 && errno != EINTR && errno != EAGAIN) {
            /* error */
            perror("pull_pump read()");
            close(pullfd);
            pullfd = -1;
        }

        /* Push all of the data in the ring buffer out. */
        while (!ring_buffer_empty_p(&ring)) {
            /* non-blocking write() to the pipe */
            r = ring_buffer_push(&ring, pushfd);

            if (r < 0 && errno != EAGAIN && errno != EINTR) {
                if (errno == EPIPE) {
                    /* This happens if someone closes the other end of the pipe.  This
                     * is a normal forced close of STDIN. Hopefully there wasn't data
                     * in the ring buffer. Just close both ends and exit.
                     */
                    close(pushfd);
                    close(pullfd);
                    pushfd = pullfd = -1;
                } else {
                    perror("pull_pump write()");
                    close(pushfd);
                    close(pullfd);
                }
                return;
            }

            /* Select for writablity on the pipe end.
             * Very rarely will this stick.
             */
            r = select(pushfd+1, NULL, &writefds, &exceptfds, NULL);

            if (r < 0 || FD_ISSET(pushfd, &exceptfds)) {
                close(pushfd);
                close(pullfd);
                pushfd = pullfd = -1;
                return;
            }
        }
    }
    assert(pullfd < 0);
    assert(ring_buffer_empty_p(&ring));
    close(pushfd);
}