0

I have searched around on the internet and there were few document about how we use Ring Buffer to read from file or write to a file. So i wrote my own implementation here:

my ringbuffer structure

typedef struct Ringbuffer {
    char* buffer;
    int length;
    int start;
    int end;
    int fd;
    int looped;
} RingBuffer;

//to update the end of the buffer after writing
#define RingBuffer_commit_write(B, A) (B)->end += A;if((B)->end >=(B)->length){(B)->looped =1;(B)->end %= (B)->length;}
#define RingBuffer_ends_at(B) ((B)->buffer + (B)->end)

static inline int RingBuffer_available_space(RingBuffer *buffer) {
     return buffer->length- RingBuffer_available_data(buffer);
}

code snippet to read from file

void read_some(int sockfd,RingBuffer *buffer) {
    int byte_recv =0;
    check((RingBuffer_available_space(buffer) > 0),"out of space, release some data");
    if(buffer->looped == 0){
        byte_recv = recv(sockfd,buffer,buffer->length - buffer->end,0);
        if(byte_recv < buffer->length- buffer->end){
            RingBuffer_commit_write(buffer,byte_recv);
            return ;
        }else{
            RingBuffer_commit_write(buffer,byte_recv);
            byte_recv = recv(sockfd,buffer,RingBuffer_ends_at(buffer),RingBuffer_available_space(buffer),0);
            RingBuffer_commit_write(buffer,byte_recv);
        }
    }else{
        byte_recv = recv(sockfd,buffer,RingBuffer_available_space(),0);
        RingBuffer_commit_write(buffer,byte_recv)
    }
error:
    return;
}

This, however, is not efficient and overcomplicated in my opinion. Is there a better implementation of Ring buffer to read from file( since both socket and file are quite the same)? Any help,even an idea only,would be appreciated.

Morten Jensen
  • 5,818
  • 3
  • 43
  • 55
Van Teo Le
  • 164
  • 3
  • 11
  • What is going on in `read_some`? Why don't you just `recv` + `commit_write` and return? What for are those two ifs, and what does `buffer->looped` do? I like the implementation that does `RingBuffer_get_write_pnt(char **pnt, size_t *size)`, and in there you calculate the location and size of the longest available pointer that you can use to write into the ringbuffer. You would need at max call it twice. – KamilCuk Nov 26 '19 at 15:53
  • looped is used to check if buffer->end has run past the length of the buffer or not so it can warp the end back to the start. Because of that, i have to use 2 if to check whether buffer->end is behind or after buffer->start so i can push data correctly. – Van Teo Le Nov 26 '19 at 16:02
  • but where is that RingBuffer_get_write_pnt(char **pnt, size_t *size) you mentioned so i can take a look? – Van Teo Le Nov 26 '19 at 16:03
  • 1
    Why not just keep `end %= length` end smaller then length and then see if it's looped via `end < start`? Then why do you need looped anyway, can't you see if `end > length`? `but where is that` - I'm sorry, I meant, you could write such implementation. There is only one tricky place in rb, when `start == end` - then it can be full or empty, you don't know. You don't need "looped", just check if `end < start` - then you know it is "looped". – KamilCuk Nov 26 '19 at 16:04

0 Answers0