A Monitor Solution to the Producer-Consumer Problem

This is an illustration of a solution to the classic producer-consumer (bounded-buffer) problem using a monitor.

CONCEPT: Producers produce items to be stored in the buffer. Consumers remove and consume items which have been stored. Mutual exclusion must be enforced on the buffer itself. Moreover, producers can store only when there is an empty slot, and consumers can remove only when there is a full slot.

The buffer and its control variables are encapsulated by a monitor. The monitor provides procedures to put an item in the buffer and to take an item out of the buffer. The monitor includes two condition variables: slot_free represents the condition that there is space for an item, and item_present represents the condition that at least one item is present in the buffer.

In this example, the buffer is implemented as an array of size MAX treated as a circular (ring) buffer. Variables in and out give the index of the next position for putting in and taking out (if any). Variable count gives the number of items in the buffer.

MONITOR:

DATA:

	condition slot_free, item_present;
	anytype buffer[MAX];
	int in, out, count;

INITIALIZATION:

	in = 0;
	out = 0;
	count = 0;

PROCEDURES:

	void put_in_buffer(anytype item) {

		/* if no space is available, wait for one */
		if (count >= MAX)slot_free.wait;

		/* store the item */
		buffer[in] = item;
		in = in + 1 mod n;
		count = count + 1;

		/* signal that the item is present */
		item_present.signal;
	}








	anytype get_from_buffer(void) {

		anytype item;

		/* if no items are present, wait for one */
		if (count <= 0) item_present.wait;

		/* get the next item */
		item = buffer[out];
		out = out + 1 mod n;
		count = count - 1;

		/* announce that a space is free */
		slot_free.signal;

		/* return the item */
		return(item);
	}

PRODUCER :

	repeat {

		/* produce an item */
		item = produce();

		/* put it in the buffer */
		put_in_buffer(item);

	} until done;

CONSUMER:

	repeat {

		/* get item from the buffer */
		item = get_from_buffer();

		/* consume it */
		consume(item);

	} until done;