size() { return write - read; }
[EDIT] Changed constant to reflect use of unsigned integers, which I forgot to specify initially.
What I find interesting are the trade-offs: machine vs explicit integer wrap-around and buffers with maximum ~size(int)/2 vs ~size(int).
(0 - (2^32 - 1)) % 2^32 = 1
PS. No wrap-around either, for different reasons.
You'll have to explain that to me, since I can't assign `x = 2^32` without wraparound when x is an unsigned 32 bit integer.
[EDIT] Changed constant to reflect use of unsigned integers, which I forgot to specify initially.