|
- #include "../thread-link.h"
-
- namespace rtosc {
- #ifdef off_t
- #undef off_t
- #endif
- #define off_t signed long
-
-
- //Ringbuffer internal structure
- //XXX possible undefined behavior depending on future semantics of volatile
- struct internal_ringbuffer_t {
- char *buffer;
- volatile off_t write;
- volatile off_t read;
- size_t size;
- };
-
- typedef internal_ringbuffer_t ringbuffer_t;
-
- static size_t ring_read_size(ringbuffer_t *ring)
- {
- const size_t w = ring->write;
- const size_t r = ring->read;
-
- return (w-r+ring->size) % ring->size;
- }
- static size_t ring_write_size(ringbuffer_t *ring)
- {
- //leave one forbidden element
- const size_t w = ring->write;
- const size_t r = ring->read;
- if(r == w)
- return ring->size - 1;
- return ((r - w + ring->size) % ring->size) - 1;
- }
- static void ring_write(ringbuffer_t *ring, const char *data, size_t len)
- {
- assert(ring_write_size(ring) >= len);
- const off_t next_write = (ring->write + len)%ring->size;
-
- //discontinuous write
- if(next_write < ring->write) {
- const size_t w1 = ring->size - ring->write - 1;
- const size_t w2 = len - w1;
- memcpy(ring->buffer+ring->write, data, w1);
- memcpy(ring->buffer, data+w1, w2);
- } else { //contiguous
- memcpy(ring->buffer+ring->write, data, len);
- }
- ring->write = next_write;
- }
- static void ring_read(ringbuffer_t *ring, char *data, size_t len)
- {
- assert(ring_read_size(ring) >= len);
- const off_t next_read = (ring->read + len)%ring->size;
-
- //discontinuous read
- if(next_read < ring->read) {
- const size_t r1 = ring->size - ring->read - 1;
- const size_t r2 = len - r1;
- memcpy(data, ring->buffer+ring->read, r1);
- memcpy(data+r1, ring->buffer, r2);
- } else { //contiguous
- memcpy(data, ring->buffer+ring->read, len);
- }
- ring->read = next_read;
- }
- static void ring_read_vector(ringbuffer_t *ring, ring_t *r)
- {
- assert(r);
- size_t read_size = ring_read_size(ring);
- off_t read = ring->read;
- r[0].data = ring->buffer+ring->read;
- if(read_size+read > ring->size) { //discontinuous
- size_t r2 = (read_size+1+read)%ring->size;
- size_t r1 = read_size - r2;
- r[0].len = r1;
- r[1].data = ring->buffer;
- r[1].len = r2;
- } else {
- r[0].len = read_size;
- r[1].data = NULL;
- r[1].len = 0;
- }
- }
-
- ThreadLink::ThreadLink(size_t max_message_length, size_t max_messages)
- :MaxMsg(max_message_length),
- BufferSize(MaxMsg*max_messages),
- write_buffer(new char[MaxMsg]),
- read_buffer(new char[MaxMsg]),
- ring(new ringbuffer_t)
- {
- ring->buffer = new char[BufferSize];
- ring->size = BufferSize;
- ring->read = 0;
- ring->write = 0;
- memset(write_buffer, 0, MaxMsg);
- memset(read_buffer, 0, MaxMsg);
- }
-
- ThreadLink::~ThreadLink(void)
- {
- delete[] ring->buffer;
- delete ring;
- delete[] write_buffer;
- delete[] read_buffer;
- }
-
- void ThreadLink::write(const char *dest, const char *args, ...)
- {
- va_list va;
- va_start(va,args);
- const size_t len =
- rtosc_vmessage(write_buffer,MaxMsg,dest,args,va);
- va_end(va);
- if(ring_write_size(ring) >= len)
- ring_write(ring,write_buffer,len);
- }
-
- void ThreadLink::writeArray(const char *dest, const char *args, const rtosc_arg_t *aargs)
- {
- const size_t len =
- rtosc_amessage(write_buffer, MaxMsg, dest, args, aargs);
- if(ring_write_size(ring) >= len)
- ring_write(ring,write_buffer,len);
- }
-
- /**
- * Directly write message to ringbuffer
- */
- void ThreadLink::raw_write(const char *msg)
- {
- const size_t len = rtosc_message_length(msg, -1);//assumed valid
- if(ring_write_size(ring) >= len)
- ring_write(ring,msg,len);
- }
-
- /**
- * @returns true iff there is another message to be read in the buffer
- */
- bool ThreadLink::hasNext(void) const
- {
- return ring_read_size(ring);
- }
-
- /**
- * Read a new message from the ringbuffer
- */
- msg_t ThreadLink::read(void) {
- ring_t r[2];
- ring_read_vector(ring,r);
- const size_t len =
- rtosc_message_ring_length(r);
- assert(ring_read_size(ring) >= len);
- assert(len <= MaxMsg);
- ring_read(ring, read_buffer, len);
- return read_buffer;
- }
-
- /**
- * Peak at last message read without reading another
- */
- msg_t ThreadLink::peak(void) const
- {
- return read_buffer;
- }
-
- /**
- * Raw write buffer access for more complicated task
- */
- char *ThreadLink::buffer(void) {return write_buffer;}
- /**
- * Access to write buffer length
- */
- size_t ThreadLink::buffer_size(void) const {return BufferSize;}
-
- };
|