Ejemplo n.º 1
0
int main()
{
	struct RingBuffer *h = NULL;
	int x;
	assert(ringbuffer_init(&h, 3, sizeof(x)) == 0);
	assert(ringbuffer_top(h, (unsigned char *)&x) == RBE_NO_SPACE_OR_DATA);
	x = 10;
	assert(ringbuffer_push(h, (unsigned char *)&x) == RBE_SUCCESS);
	x = -1;
	assert(ringbuffer_top(h, (unsigned char *)&x) == RBE_SUCCESS);
	assert(x == 10);
	x = 666;
	assert(ringbuffer_push(h, (unsigned char *)&x) == RBE_SUCCESS);
	x = -1;
	assert(ringbuffer_top(h, (unsigned char *)&x) == RBE_SUCCESS);
	assert(x == 10);
	assert(ringbuffer_push(h, (unsigned char *)&x) == RBE_NO_SPACE_OR_DATA);
	ringbuffer_destroy(&h);

	assert(ringbuffer_init(&h, 3, sizeof(x)) == 0);
	x = INT_MIN;
	assert(ringbuffer_push(h, (unsigned char *)&x) == RBE_SUCCESS);
	x = -1;
	assert(ringbuffer_top(h, (unsigned char *)&x) == RBE_SUCCESS);
	assert(x == INT_MIN);
	x = INT_MAX;
	assert(ringbuffer_push(h, (unsigned char *)&x) == RBE_SUCCESS);
	x = -1;
	assert(ringbuffer_top(h, (unsigned char *)&x) == RBE_SUCCESS);
	assert(x == INT_MIN);
	ringbuffer_destroy(&h);
	return 0;
}
Ejemplo n.º 2
0
rdpTcp* tcp_new(rdpSettings* settings)
{
	rdpTcp* tcp;

	tcp = (rdpTcp*) calloc(1, sizeof(rdpTcp));

	if (!tcp)
		return NULL;

	if (!ringbuffer_init(&tcp->xmitBuffer, 0x10000))
		goto out_free;

	tcp->sockfd = -1;
	tcp->settings = settings;

	if (0)
		goto out_ringbuffer; /* avoid unreferenced label warning on Windows */

#ifndef _WIN32
	tcp->event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, tcp->sockfd);

	if (!tcp->event || tcp->event == INVALID_HANDLE_VALUE)
		goto out_ringbuffer;
#endif

	return tcp;
out_ringbuffer:
	ringbuffer_destroy(&tcp->xmitBuffer);
out_free:
	free(tcp);
	return NULL;
}
Ejemplo n.º 3
0
int main(int argc, char *argv[])
{
    pthread_t pub, sub;
    double u = 0;

    struct ringbuffer *r = ringbuffer_create(6553600, sizeof(entry_t) + 2000);
    struct timeval t[2];

    if (argc > 1)
        MAXSEQ = atoll(argv[1]);

    gettimeofday(&t[0], NULL);
    pthread_create(&pub, NULL, write_thread, r);
    pthread_create(&sub, NULL, read_thread, r);

    pthread_join(pub, NULL);
    printf("join pub\n");

    pthread_join(sub, NULL);
    printf("join sub\n");

    gettimeofday(&t[1], NULL);

    u = (double)t[1].tv_sec + (double)t[1].tv_usec / 1000000 - (double)t[0].tv_sec -
        (double)t[0].tv_usec / 1000000;

    printf("time = %lfs, %lf/s\n", u, MAXSEQ / u);
    ringbuffer_destroy(r);

    return 0;
}
Ejemplo n.º 4
0
int map_join(lua_State *L) {
   int rc = 0;
   int err_rc = -1;
   map_t *map = (map_t *)lua_touserdata(L, 1);
   for (uint32_t i = 0; i < map->num_threads; i++) {
      if (map->threads[i].rb) {
         int ret = pthread_join(map->threads[i].thread, NULL);
         if (ret) return LUA_HANDLE_ERROR(L, ret);
         if (map->threads[i].ret) {
            err_rc = rc;
         }
         while (ringbuffer_peek(map->threads[i].rb)) {
            rb_load(L, map->threads[i].rb);
            rc++;
         }
         ringbuffer_destroy(map->threads[i].rb);
      }
   }
   free(map->threads);
   map->threads = NULL;
   map->num_threads = 0;
   if (err_rc >= 0) {
      return LUA_HANDLE_ERROR_STR(L, lua_tostring(L, err_rc - rc));
   }
   return rc;
}
Ejemplo n.º 5
0
void tcp_free(rdpTcp* tcp)
{
	if (!tcp)
		return;

	ringbuffer_destroy(&tcp->xmitBuffer);
	CloseHandle(tcp->event);
	free(tcp);
}
Ejemplo n.º 6
0
int main()
{
	struct RingBuffer *h = NULL;
	assert(ringbuffer_init(&h, 1, 100) == 0);
	assert(h != NULL);
	ringbuffer_destroy(&h);
	assert(h == NULL);
	return 0;
}
Ejemplo n.º 7
0
static int destroy_client(lua_State *L, client_t *client) {
   if (client->sock) {
      int ret = close(client->sock);
      if (ret) return LUA_HANDLE_ERROR(L, errno);
      client->sock = 0;
   }
   if (client->send_rb) {
      ringbuffer_destroy(client->send_rb);
      client->send_rb = NULL;
   }
   if (client->recv_rb) {
      ringbuffer_destroy(client->recv_rb);
      client->recv_rb = NULL;
   }
   destroy_copy_context(&client->copy_context);
   if (client->tag) {
      free(client->tag);
      client->tag = NULL;
   }
   free(client);
   return 0;
}
Ejemplo n.º 8
0
int map_check_errors(lua_State *L) {
   map_t *map = (map_t *)lua_touserdata(L, 1);
   for (uint32_t i = 0; i < map->num_threads; i++) {
      if (map->threads[i].ret) {
         pthread_join(map->threads[i].thread, NULL);
         while (ringbuffer_peek(map->threads[i].rb)) {
            rb_load(L, map->threads[i].rb);
         }
         ringbuffer_destroy(map->threads[i].rb);
         map->threads[i].rb = NULL;
         return LUA_HANDLE_ERROR_STR(L, lua_tostring(L, -1));
      }
   }
   return 0;
}
Ejemplo n.º 9
0
static int transport_bio_buffered_free(BIO* bio)
{
	WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) BIO_get_data(bio);
	BIO* next_bio = BIO_next(bio);

	if (next_bio)
	{
		BIO_free(next_bio);
		BIO_set_next(bio, NULL);
	}

	ringbuffer_destroy(&ptr->xmitBuffer);
	free(ptr);
	return 1;
}
Ejemplo n.º 10
0
static int transport_bio_buffered_free(BIO* bio)
{
	WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;

	if (bio->next_bio)
	{
		BIO_free(bio->next_bio);
		bio->next_bio = NULL;
	}

	ringbuffer_destroy(&ptr->xmitBuffer);

	free(ptr);

	return 1;
}
Ejemplo n.º 11
0
int main()
{
    struct RingBuffer *h = NULL;
    int x = 10, y = INT_MAX, z = 2863311530, m = -3333;
    int offset_remove = 2;
    int offset_insert = 3;
    int offset_data = 4;

    assert(ringbuffer_init(&h, 3, sizeof(x)) == 0);
    assert(ringbuffer_push(h, (unsigned char *)&x) == RBE_SUCCESS);
    assert(ringbuffer_push(h, (unsigned char *)&y) == RBE_SUCCESS);
    assert(ringbuffer_full(h) != 0);
    assert(ringbuffer_pop(h) == RBE_SUCCESS);
    assert(ringbuffer_push(h, (unsigned char *)&z) == RBE_SUCCESS);
    assert(ringbuffer_full(h) != 0);

    assert(ringbuffer_resize(&h, 5) == RBE_SUCCESS);
    assert(ringbuffer_full(h) == 0);
    assert(ringbuffer_empty(h) == 0);
    assert(ringbuffer_push(h, (unsigned char *)&m) == RBE_SUCCESS);
    assert(ringbuffer_push(h, (unsigned char *)&x) == RBE_SUCCESS);
    assert(ringbuffer_full(h) != 0);

    {   /* checking the data: x y z m x  */
        unsigned *off = (unsigned *) h;
        int *values = (int *) off + offset_data;
        assert(*(off + offset_remove) == 1 * sizeof(x));
        assert(*(off + offset_insert) == 0);
        assert(values[0] == x);
        assert(values[1] == y);
        assert(values[2] == z);
        assert(values[3] == m);
        assert(values[4] == x);
    }

    ringbuffer_destroy(&h);

    return 0;
}
Ejemplo n.º 12
0
int main(void)
{
	struct ringbuffer *ring_buf;
	pthread_t produce_pid, consume_pid; 

	ring_buf = ringbuffer_create(FIFO_SIZE);
	if (!ring_buf) {
		perror("ringbuffer_create()");
		exit(1);
	}

	printf("multi thread test.......\n");

	produce_pid  = producer_thread((void*)ring_buf);
	consume_pid  = consumer_thread((void*)ring_buf);

	pthread_join(produce_pid, NULL);
	pthread_join(consume_pid, NULL);

	ringbuffer_destroy(ring_buf);

	return 0;
}
Ejemplo n.º 13
0
SCM ffmpeg_destroy(SCM scm_self)
{
  struct ffmpeg_t *self = get_self_no_check(scm_self);

  if (self->header_written) {
    // Clear audio encoder pipeline
    if (self->audio_codec_ctx)
      while (encode_audio(self, NULL));

    // Clear video encoder pipeline
    if (self->video_codec_ctx)
      while (encode_video(self, NULL));
  };

  if (self->video_target_frame) {
    av_frame_unref(self->video_target_frame);
    av_frame_free(&self->video_target_frame);
    self->video_target_frame = NULL;
  };

  if (self->audio_packed_frame) {
    av_frame_unref(self->audio_packed_frame);
    av_frame_free(&self->audio_packed_frame);
    self->audio_packed_frame = NULL;
  };

  if (self->audio_target_frame) {
    av_frame_unref(self->audio_target_frame);
    av_frame_free(&self->audio_target_frame);
    self->audio_target_frame = NULL;
  };

  if (self->audio_buffer.buffer) {
    ringbuffer_destroy(&self->audio_buffer);
    self->audio_buffer.buffer = NULL;
  };

  if (self->header_written) {
    av_write_trailer(self->fmt_ctx);
    self->header_written = 0;
  };

  if (self->orig_pkt.data) {
    av_packet_unref(&self->orig_pkt);
    self->orig_pkt.data = NULL;
  };

  if (self->audio_codec_ctx) {
    avcodec_close(self->audio_codec_ctx);
    self->audio_codec_ctx = NULL;
  };

  if (self->video_codec_ctx) {
    avcodec_close(self->video_codec_ctx);
    self->video_codec_ctx = NULL;
  };

  if (self->output_file) {
    avio_close(self->fmt_ctx->pb);
    self->output_file = 0;
  };

  if (self->fmt_ctx) {
    if (is_input_context(self))
      avformat_close_input(&self->fmt_ctx);
    else
      avformat_free_context(self->fmt_ctx);
    self->fmt_ctx = NULL;
  };

  return SCM_UNSPECIFIED;
}
Ejemplo n.º 14
0
int32_t ilctts_create(
	TTSRENDER_STATE_T **component,
	uint32_t sample_rate,
	uint32_t num_channels,
	uint32_t bit_depth,
	uint32_t num_buffers,
	uint32_t buffer_size_ms,
	BUFFER_SIZE_TYPE_T buffer_size_type,
	uint32_t ringbuffer_length
)
{
	ENTER(LOGLEVEL_1, "ilctts_create");

	SHOW(LOGLEVEL_5, "Sample rate: %d", sample_rate);
	SHOW(LOGLEVEL_5, "Number of channels: %d", num_channels);
	SHOW(LOGLEVEL_5, "Bit depth: %d", bit_depth);
	SHOW(LOGLEVEL_5, "Number of buffers: %d", num_buffers);
	SHOW(LOGLEVEL_5, "Buffer size: %d", buffer_size_ms);
	SHOW(LOGLEVEL_5, "Ring buffer length: %d", ringbuffer_length);

	int32_t ret;
	uint32_t buffer_size;

		OMX_ERRORTYPE omx_err;
	TTSRENDER_STATE_T *st;

	*component = NULL;

	st = calloc(1, sizeof(TTSRENDER_STATE_T));
	OMX_PARAM_PORTDEFINITIONTYPE param;
	OMX_AUDIO_PARAM_PCMMODETYPE pcm;
	int32_t s;

	*component = st;

	// create and start up everything

	// initialise buffer list semaphore
	s = sem_init(&st->buffer_list_sema, 0, 1);
	if (s < 0) {
		ERROR("sem_init returned error initializing buffer list semaphore in ilctts_create: %d", s);
		return -1;
	}

	// initial value of ringbuffer_empty_sema is 1 because at startup there is space
	s = sem_init(&st->ringbuffer_empty_sema, 0, 1);
	if (s < 0) {
		ERROR("sem_init returned error initializing ringbuffer_empty_sema in ilctts_create: %d", s);
		return -1;
	}

	// initial value of ringbuffer_data_sema is 0 because at startup there is no data
	s = sem_init(&st->ringbuffer_data_sema, 0, 0);
	if (s < 0) {
		ERROR("sem_init returned error initializing ringbuffer_data_sema in ilctts_create: %d", s);
		return -1;
	}

	// free_buffer mutex and cv
	pthread_mutex_init(&st->free_buffer_mutex, NULL);
	pthread_cond_init(&st->free_buffer_cv, NULL);

	// ringbuffer mutex
	pthread_mutex_init(&st->ringbuffer_mutex, NULL);
	//pthread_cond_init(&st->ringbuffer_cv, NULL);

	st->sample_rate = sample_rate;
	st->num_channels = num_channels;
	st->bit_depth = bit_depth;
	st->bytes_per_sample = (bit_depth * OUT_CHANNELS(num_channels)) >> 3;

	if (buffer_size_type == BS_MILLISECONDS) {
		// supplied buffer size was in milliseconds, calculate the byte size
		// note: calc_buffer_size_from_ms returns buffer size aligned for VCHI
		buffer_size = calc_buffer_size_from_ms(sample_rate, bit_depth, num_channels, buffer_size_ms, 1);
	} else {
		// supplied buffer size was in bytes
		// buffer size must be 16 byte aligned for VCHI
		buffer_size = (buffer_size_ms + 15) & ~15;
	}

	SHOW(LOGLEVEL_5, "Bytes per sample: %d", st->bytes_per_sample);
	SHOW(LOGLEVEL_5, "Calculated buffer size: %d", buffer_size);

	st->num_buffers = num_buffers;
	st->client = ilclient_init();
	st->tts_stop = 0;
	st->tts_pause_state = TTS_PAUSE_OFF;

	st->ringbuffer = ringbuffer_init(ringbuffer_length);
	if (st->ringbuffer == NULL) {
		ERROR("ringbuffer_init failed in ilctts_create", "");
		return -1;
	}

	// set up callbacks
	ilclient_set_empty_buffer_done_callback(st->client, input_buffer_callback, st);
	//ilclient_set_configchanged_callback(st->client, config_changed_callback, st);
	//ilclient_set_port_settings_callback(st->client, port_settings_changed_callback, st);

	ret = ilclient_create_component(st->client, &st->audio_render, "audio_render", ILCLIENT_ENABLE_INPUT_BUFFERS | ILCLIENT_DISABLE_ALL_PORTS);
	if (ret == -1) {
		ERROR("ilclcient_create_component returned error in ilctts_create: %d", ret);
		return ret;
	}

	st->list[0] = st->audio_render;

	// set up the number/size of buffers
		OMX_INIT_STRUCTURE(param);
	param.nPortIndex = 100;
	omx_err = OMX_GetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, &param);
	if (omx_err != OMX_ErrorNone) {
		ERROR("OMX_GetParameter returned error in ilctts_create: %d", omx_err);
		return -1;
	}

	// set the buffer size to the requested size, or the minimum size returned, whichever is greater
	st->buffer_size = max(buffer_size, param.nBufferSize);
	SHOW(LOGLEVEL_3, "Buffer size set to: %d", st->buffer_size);
	param.nBufferSize = st->buffer_size;
	param.nBufferCountActual = max(st->buffer_count, param.nBufferCountMin);

	omx_err = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamPortDefinition, &param);
	if (omx_err != OMX_ErrorNone) {
		ERROR("OMX_SetParameter returned error in ilctts_create: %d", omx_err);
		return -1;
	}

	// set the pcm parameters
	OMX_INIT_STRUCTURE(pcm);
	pcm.nPortIndex = 100;
	pcm.nChannels = OUT_CHANNELS(num_channels);
	pcm.eNumData = OMX_NumericalDataSigned;
	pcm.eEndian = OMX_EndianLittle;
	pcm.nSamplingRate = sample_rate;
	pcm.bInterleaved = OMX_TRUE;
	pcm.nBitPerSample = bit_depth;
	pcm.ePCMMode = OMX_AUDIO_PCMModeLinear;

	switch(st->num_channels) {
		case 1:
			pcm.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
			break;
		case 3:
			pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
			pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
			pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
			break;
		case 8:
			pcm.eChannelMapping[7] = OMX_AUDIO_ChannelRS;
		case 7:
			pcm.eChannelMapping[6] = OMX_AUDIO_ChannelLS;
		case 6:
			pcm.eChannelMapping[5] = OMX_AUDIO_ChannelRR;
		case 5:
			pcm.eChannelMapping[4] = OMX_AUDIO_ChannelLR;
		case 4:
			pcm.eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
			pcm.eChannelMapping[2] = OMX_AUDIO_ChannelCF;
		case 2:
			pcm.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
		pcm.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
			break;
	}

	omx_err = OMX_SetParameter(ILC_GET_HANDLE(st->audio_render), OMX_IndexParamAudioPcm, &pcm);
	if (omx_err != OMX_ErrorNone) {
		ERROR("OMX_SetParameter returned error in ilctts_create: %d", omx_err);
		return -1;
	}

	// this function waits for the command to complete
	ret = ilclient_change_component_state(st->audio_render, OMX_StateIdle);
	if (ret < 0) {
		ERROR("ilctts_change_component_state returned error in ilctts_create: %d", ret);
		return -1;
	}

	ret = ilclient_enable_port_buffers(st->audio_render, 100, NULL, NULL, NULL);
	if (ret < 0) {
		ERROR("ilclient_enable_port_buffers returned error in ilctts_create: %d", ret);
		ilclient_change_component_state(st->audio_render, OMX_StateLoaded);
		ilclient_cleanup_components(st->list);
		omx_err = OMX_Deinit();
		ilclient_destroy(st->client);
		destroy_semaphores(st);
		destroy_mutexes(st);
		ringbuffer_destroy(st->ringbuffer);
		// need to destroy and free other stuff here?
		free(st);
		*component = NULL;
		return -1;
	}

	INFO(LOGLEVEL_1, "Setting state to executing in ilctts_create");
	return ilclient_change_component_state(st->audio_render, OMX_StateExecuting);

} // end ilctts_create
Ejemplo n.º 15
0
static void workqueue_destroy_queue(queue_t *queue) {
   pthread_mutex_destroy(&queue->mutex);
   pthread_cond_destroy(&queue->read_avail_cond);
   pthread_cond_destroy(&queue->write_avail_cond);
   ringbuffer_destroy(queue->rb);
}
Ejemplo n.º 16
0
int main(int argc, char **argv) {
    // For connect/authenticate failures
    int reconnect_delay = 1;

    // RingBuffer buffer for the writer
    char *writer_buffer = 0;

    LINFO("%s starting", APP_NAME);

    config_init(argc > 1 ? argv[1] : 0);
    pthread_create(&config.timer_thread.thread, 0, timer_thread_entry, (void *)&config.timer_thread);
    if (!config_read()) {
        return 1;
    }

    load_data();

    sighelper_sigaction(SIGHUP, reload_config);
    sighelper_sigaction(SIGUSR1, save_data);
    sighelper_sigaction(SIGTERM, terminate);
    sighelper_sigaction(SIGQUIT, terminate);
    sighelper_sigaction(SIGINT, terminate);

    LDEBUG("allocating writer buffer, size %d", config.writer.buffer);
    writer_buffer = malloc(config.writer.buffer);
    ringbuffer_init(&config.writer_thread.ringbuffer,
                    writer_buffer, config.writer.buffer);

    LDEBUG("creating reader queue, size %d", config.reader.queue);
    queue_init(&config.reader_thread.queue, config.reader.queue);

    while (running) {
        LINFO("connecting to %s:%d", config.network.host, config.network.port);

        if (net_connect(&config.socket, config.network.host, config.network.port)) {
            LINFO("opening XMPP stream to %s", config.component.hostname);
            if (!net_stream(&config.socket,
                            "xmcomp",
                            config.component.hostname,
                            config.component.password)) {
                net_disconnect(&config.socket);
            }
        }

        if (!config.socket.connected) {
            LERROR("retrying in %d second(s)", reconnect_delay);
            sleep(reconnect_delay);
            if (reconnect_delay < 60) {
                reconnect_delay <<= 1;
            }
            continue;
        }
        reconnect_delay = 1;

        LINFO("creating writer thread");
        config.writer_thread.socket = &config.socket;
        config.writer_thread.enabled = TRUE;
        pthread_create(&config.writer_thread.thread, 0, writer_thread_entry, (void *)&config.writer_thread);

        LINFO("creating reader thread");
        config.reader_thread.socket = &config.socket;
        config.reader_thread.enabled = TRUE;
        pthread_create(&config.reader_thread.thread, 0, reader_thread_entry, (void *)&config.reader_thread);

        LINFO("creating worker threads");
        config_apply();

        LINFO("started");
        LDEBUG("joining reader thread");
        pthread_join(config.reader_thread.thread, 0);
        // Switch ringbuffer to offline, indicating no more data is expected.
        // As soon as the writer finishes the job, it will terminate
        ringbuffer_offline(&config.writer_thread.ringbuffer);
        LDEBUG("joining writer thread");
        pthread_join(config.writer_thread.thread, 0);

        LINFO("clearing output buffer and disconnecting");
        ringbuffer_clear(&config.writer_thread.ringbuffer);

        net_unstream(&config.socket);
        net_disconnect(&config.socket);
    }

    LINFO("cleaning up");
    ringbuffer_destroy(&config.writer_thread.ringbuffer);
    queue_destroy(&config.reader_thread.queue);
    free(writer_buffer);
    config_destroy();

    return 0;
}
Ejemplo n.º 17
0
void bud_client_side_destroy(bud_client_side_t* side) {
  ringbuffer_destroy(&side->input);
  ringbuffer_destroy(&side->output);
}
Ejemplo n.º 18
0
Archivo: test.c Proyecto: Acconut/bud
int main() {
  int i;
  int j;
  int r;
  int after;
  ssize_t len;
  char* ptr;

  data = malloc(TEST_DATA_SIZE);
  assert(data != NULL);
  ringbuffer_init(&rb);

  /* Fill test data */
  for (i = 0; i < TEST_DATA_SIZE; i++)
    data[i] = (i * i) % 137;

  /* Fill ringbuffer */
  i = 0;
  after = 0;
  while (i < TEST_DATA_SIZE - TEST_INSERT_LEN) {
    if (after)
      len = TEST_DATA_SIZE - i - TEST_INSERT_LEN;
    else
      len = TEST_INSERT_OFF - i;

    ptr = ringbuffer_write_ptr(&rb, &len);
    ASSERT(ptr != NULL);

    /* Always make progress */
    ASSERT(len > 0);

    if (after)
      memcpy(ptr, data + i + TEST_INSERT_LEN, len);
    else
      memcpy(ptr, data + i, len);

    i += len;
    r = ringbuffer_write_append(&rb, len);
    ASSERT(r == 0);

    if (i == TEST_INSERT_OFF)
      after = 1;
  }
  ASSERT(ringbuffer_size(&rb) == TEST_DATA_SIZE - TEST_INSERT_LEN);

  /* Insert stuff */
  ringbuffer_insert(&rb,
                    TEST_INSERT_OFF,
                    data + TEST_INSERT_OFF,
                    TEST_INSERT_LEN);

  /* Read from it */
  i = 0;
  while (i < TEST_DATA_SIZE) {
    len = TEST_DATA_SIZE - i;
    ptr = ringbuffer_read_next(&rb, &len);
    ASSERT(ptr != NULL);

    /* Always make progress */
    ASSERT(len > 0);

    for (j = 0; j < len; j++)
      ASSERT(ptr[j] == data[i + j]);

    ringbuffer_read_skip(&rb, len);
    i += len;
  }

  /* Destroy it */
  ringbuffer_destroy(&rb);

  return 0;
}