rbuffer.h
Go to the documentation of this file.
1 // Specialized ring buffer. This is basically an array that wraps read/write
2 // pointers around the memory region. It should be more efficient than the old
3 // RBuffer which required memmove() calls to relocate read/write positions.
4 //
5 // The main purpose of RBuffer is simplify memory management when reading from
6 // uv_stream_t instances:
7 //
8 // - The event loop writes data to a RBuffer, advancing the write pointer
9 // - The main loop reads data, advancing the read pointer
10 // - If the buffer becomes full(size == capacity) the rstream is temporarily
11 // stopped(automatic backpressure handling)
12 //
13 // Reference: http://en.wikipedia.org/wiki/Circular_buffer
14 #ifndef NVIM_RBUFFER_H
15 #define NVIM_RBUFFER_H
16 
17 #include <stddef.h>
18 #include <stdint.h>
19 
20 // Macros that simplify working with the read/write pointers directly by hiding
21 // ring buffer wrap logic. Some examples:
22 //
23 // - Pass the write pointer to a function(write_data) that incrementally
24 // produces data, returning the number of bytes actually written to the
25 // ring buffer:
26 //
27 // RBUFFER_UNTIL_FULL(rbuf, ptr, cnt)
28 // rbuffer_produced(rbuf, write_data(state, ptr, cnt));
29 //
30 // - Pass the read pointer to a function(read_data) that incrementally
31 // consumes data, returning the number of bytes actually read from the
32 // ring buffer:
33 //
34 // RBUFFER_UNTIL_EMPTY(rbuf, ptr, cnt)
35 // rbuffer_consumed(rbuf, read_data(state, ptr, cnt));
36 //
37 // Note that the rbuffer_{produced,consumed} calls are necessary or these macros
38 // create infinite loops
39 #define RBUFFER_UNTIL_EMPTY(buf, rptr, rcnt) \
40  for (size_t rcnt = 0, _r = 1; _r; _r = 0) /* NOLINT(readability/braces) */ \
41  for ( /* NOLINT(readability/braces) */ \
42  char *rptr = rbuffer_read_ptr(buf, &rcnt); \
43  buf->size; \
44  rptr = rbuffer_read_ptr(buf, &rcnt))
45 
46 #define RBUFFER_UNTIL_FULL(buf, wptr, wcnt) \
47  for (size_t wcnt = 0, _r = 1; _r; _r = 0) /* NOLINT(readability/braces) */ \
48  for ( /* NOLINT(readability/braces) */ \
49  char *wptr = rbuffer_write_ptr(buf, &wcnt); \
50  rbuffer_space(buf); \
51  wptr = rbuffer_write_ptr(buf, &wcnt))
52 
53 
54 // Iteration
55 #define RBUFFER_EACH(buf, c, i) \
56  for (size_t i = 0; /* NOLINT(readability/braces) */ \
57  i < buf->size; \
58  i = buf->size) \
59  for (char c = 0; /* NOLINT(readability/braces) */ \
60  i < buf->size ? ((int)(c = *rbuffer_get(buf, i))) || 1 : 0; \
61  i++)
62 
63 #define RBUFFER_EACH_REVERSE(buf, c, i) \
64  for (size_t i = buf->size; /* NOLINT(readability/braces) */ \
65  i != SIZE_MAX; \
66  i = SIZE_MAX) \
67  for (char c = 0; /* NOLINT(readability/braces) */ \
68  i-- > 0 ? ((int)(c = *rbuffer_get(buf, i))) || 1 : 0; \
69  )
70 
71 typedef struct rbuffer RBuffer;
75 typedef void(*rbuffer_callback)(RBuffer *buf, void *data);
76 
77 struct rbuffer {
79  void *data;
80  size_t size;
81  // helper memory used to by rbuffer_reset if required
82  char *temp;
84  char start_ptr[];
85 };
86 
87 #ifdef INCLUDE_GENERATED_DECLARATIONS
88 # include "rbuffer.h.generated.h"
89 #endif
90 
91 #endif // NVIM_RBUFFER_H
void(* rbuffer_callback)(RBuffer *buf, void *data)
Definition: rbuffer.h:75
size_t size
Definition: rbuffer.h:80
char * read_ptr
Definition: rbuffer.h:83
Definition: rbuffer.h:77
rbuffer_callback nonfull_cb
Definition: rbuffer.h:78
char * temp
Definition: rbuffer.h:82
char * write_ptr
Definition: rbuffer.h:83
char start_ptr[]
Definition: rbuffer.h:84
char *const buf
Definition: encode.c:231
char * end_ptr
Definition: rbuffer.h:83
rbuffer_callback full_cb
Definition: rbuffer.h:78
void * data
Definition: rbuffer.h:79