buffer:array 0..N-1 of portion; head, tail: 0..N-1; count: 0..N; nonempty, nonfull: condition; procedure append(x: portion); begin if count = N then nonfull.wait; note 0 <= count < N; buffer[tail] := x; tail := tail (+) 1; count := count + 1; nonempty.signal end append; procedure remove(result x: portion) ; begin if count = 0 then nonempty.wait; note 0 < count <= N; x := buffer[head]; head := head (+) 1; count := count - 1; nonfull.signal end remove; head := 0; tail := 0; count := 0; end bounded buffer; The monitor is an object that contains variables buffer, head, tail and count to realize a circular buffer, the condition variables nonempty and nonfull for synchronization and the methods append and remove to access the bounded buffer. The monitor operation wait corresponds to the semaphore operation P or acquire, signal corresponds to V or release. The circled operation (+) are taken modulo N. The presented Pascal style pseudo code shows a Hoare monitor. A Mesa monitor uses while count instead of if count. A programming language C++ version is: class Bounded_buffer { Portion buffer[N]; // 0..N-1 unsigned head, tail; // 0..N-1 unsigned count; // 0..N std::condition_variable nonempty, nonfull; std::mutex mtx; public: void append(Portion x) { std::unique_lock<std::mutex> lck(mtx); nonfull.wait(lck, [&]{ return !(N == count); }); assert(0 <= count && count < N); buffer[tail++] = x; tail %= N; ++count; nonempty.notify_one(); } Portion remove() { std::unique_lock<std::mutex> lck(mtx); nonempty.wait(lck, [&]{ return !(0 == count); }); assert(0 < count && count <= N); Portion x = buffer[head++]; head %= N; --count; nonfull.notify_one(); return x; } Bounded_buffer() { head = 0; tail = 0; count = 0; } }; The C++ version needs an additional mutex for technical reasons. It uses assert to enforce the preconditions for the buffer add and remove operations. Using channels The very first producer-consumer solution in the Electrologica computers used 'channels'. Hoare defined channels: An alternative to explicit naming of source and destination would be to name a port through which communication is to take place. The port names would be local to the processes, and the manner in which pairs of ports are to be connected by channels could be declared in the head of a parallel command. Brinch Hansen implemented channels in the programming languages Joyce and Super Pascal. The Plan 9 operating system programming language Alef, the Inferno operating system programming language Limbo have channels. The following