“As simple as possible, but not simpler” – A.Einstein
An ABC buffer is an array of four pointers dividing a memory range into three slices: PAST, DATA and IDLE. Consumption of a slice (DATA or IDLE) enlarges the adjoined slice (PAST or DATA resp).
PAST DATA IDLE
|----------->------------->-------------------|
buf[0] buf[1] buf[2] buf[3]
Buffers imply ownership; if you hold the buffer you own the memory. Buffers can be stack-allocated, malloc-ed, memory-mapped and file-mapped. Normally, only the owner can reallocate or free a buffer. Most downstream routines consume specific slices, although some take buffers too.
aB(u32, numbers);
call(Bu32mmap, numbers, 1024);
// consume IDLE, enlarge DATA by one int
call($u32feed1, Bu32idle(numbers), 12345);
call(Bu32unmap, numbers);
Many ABC data structures are buffer-based, for a good reason. ABC C discourages small heap allocations. For that reason, pointer-heavy data structures are not used. For example, C++ STL red-black trees are seen as a horror story. The reasons are many.
malloc/free
requires pretty complicated bookkeeping, which
a regular developer rarely sees, except in benchmarks.Meanwhile, all the solid-buffer-based data structures have no such limitations. Memory allocation happens once (optimistically) or a logarithmic number of times (worst case). There are no pointers. All the data stays in one block, very cache-friendly. Finally, a buffer is always a buffer, so one can checksum or save it to disk by a generic routine.
For concrete examples of the approach see flat BIN tree, binary HEAP, LSM iterator heap or HASH set. Also, NEST is an example of using a buffer differently than the past-data-idle scheme.