How to replace my circular buffer

Hello all,
My requirement is to store the request coming from the device into a buffer. As of now we are using Circular buffer[ char array of size 4K bytes]. So if any request whose size is more than 4K cannot fit into this circular buffer so i'm throwing an error in the current implementation. The possible solution to overcome this is doing reallocation of the buffer.

But is it not possible to replace the circular buffer using container(I thought about using vector..) so that i don't need to worry about the size of the request.
And if possible, how to remove the request after reading it from the container. I know my each request ends with newline char.

Thanks in advance
why not make CircularBuffer an array of string ?

each string is the request, you can then handle up to 4k requests!
My problem is how to deal while reading the request from the device. The request size is unknown here. I want to avoid hardcoded char array for reading the request from the device.

In the next level( after reading from the device) i already have queue for processing this request.
Last edited on
Assuming you are running on a "normal" PC platform, and memory allocation isn't very limited, you can use strings (like mik2718 already mentioned). String has no fixed size and you can append to it as much as needed, untill it contains your entire received message.

When you receive a new message, jump to next circular buffer position, empty the containing string, and start receiving and appending chars.

The next level/layer can read the strings from the buffer. (each string contains a complete message)

Since you probably won't need a buffer for 4000 messages, you could also reduce the size of the circular buffer. But that's just my assumption.
Last edited on
i should advice you against the idea of a vector.
the re-allocation process in a vector is extensive.
well.... with the current wide spread of the Intel® Core™ i5 and Intel® Core™ i7, and the high speed of memory access, 4KB of memory re-allocation would take less than several micro seconds.
just consider you upgraded your program, and want this buffer to contain like 1GB of memory.....
a re-allocation process would be bad (although it could happen so few times).

maybe you can make the buffer a queue, it doesn't do any re-allocation ever, and it allows you serial read access starting from the beginning of the queue.
i think you wouldn't need random access to the buffer in this application.
> But is it not possible to replace the circular buffer using container(I thought about using vector..)
> so that i don't need to worry about the size of the request.

Yes. Simplest to use such an implementation from a library.
For instance, boost::circular_buffer_space_optimized<>
http://www.boost.org/doc/libs/1_54_0/libs/circular_buffer/doc/space_optimized.html


> And if possible, how to remove the request after reading it from the container.
> I know my each request ends with newline char.


Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <boost/circular_buffer.hpp>
#include <string>
#include <algorithm>
#include <iostream>

using buffer_type = boost::circular_buffer_space_optimized<char> ;
static constexpr std::size_t min_reserve = 1024 ;

buffer_type& push_back_char( buffer_type& buffer, char c )
{
    // increase capacity if required
    if( buffer.reserve() == 0 )
        buffer.rset_capacity( buffer.size() + min_reserve ) ;

    buffer.push_back(c) ;
    return buffer ;
}

buffer_type& push_back_request( buffer_type& buffer, const std::string& request )
{
    for( char c : request ) push_back_char( buffer, c ) ;
    if( request.back() != '\n' ) buffer.push_back( '\n' ) ;
    return buffer ;
}

std::string pop_front_request( buffer_type& buffer )
{
    std::string req ;
    while( !buffer.empty() )
    {
        char c = buffer.front() ;
        buffer.pop_front() ;
        req += c ;
        if( c == '\n' ) break ;
    }

    // trim excess capacity if appropriate
    if( buffer.reserve() > min_reserve*4 )
        buffer.rset_capacity( buffer.size()+min_reserve ) ;

    return req ;
}

int main()
{
    buffer_type buffer ;
    const std::string requests[] =
    {
        "But is it not possible to replace the circular buffer using container\n",
        "(I thought about using vector..) so that i don't need to worry about the size of the request",
        " And if possible, how to remove the request after reading it from the container\n",
        "I know my each request ends with newline char\n"
    };

    for( const std::string req : requests ) push_back_request( buffer, req ) ;

    std::cout << "#requests in buffer: " << std::count( buffer.begin(), buffer.end(), '\n' ) << '\n' ;

    while( !buffer.empty() )
    {
        static int req_no = 0 ;
        std::cout << ++req_no << ". " << pop_front_request(buffer) ;
    }
}

Output:
#requests in buffer: 4
1. But is it not possible to replace the circular buffer using container
2. (I thought about using vector..) so that i don't need to worry about the size of the request
3.  And if possible, how to remove the request after reading it from the container
4. I know my each request ends with newline char
Topic archived. No new replies allowed.