Solution (source code)

= Solution

A <counting semaphore> holds a nonnegative number of permits. `down` waits until a permit is available and consumes one; `up` returns a permit and can release a waiting caller. A <binary semaphore> restricts the number available to zero or one. Unlike a <mutex>, a <semaphore> need not be released by the same <software thread> that acquired it; this permits producer-to-consumer signalling.

Interpret `maxCount` as the initial number of permits and, for this bounded implementation, the maximum permitted number of unmatched releases. An `up` beyond that capacity is a programming error, rather than a blocking operation. Clients obey this release discipline. If an unbounded <counting semaphore> is desired instead, remove the upper-bound requirement and use a sufficiently wide counter; a capacity-one instance is binary only under the corresponding balanced-use discipline.

``
class CountingSemaphore(maxCount: Int) extends Semaphore {
  require(maxCount > 0)
  private var count = maxCount
  def down: Unit = synchronized {
    while (count == 0) wait()
    count -= 1
  }
  def up: Unit = synchronized {
    require(count < maxCount, "unmatched semaphore release")
    count += 1
    notify()
  }
}
``

All accesses to `count` occur under the same <monitor>. `wait` atomically releases that <monitor> while sleeping, then reacquires it before returning. The `while` is needed because of <spurious wakeups> and because another caller can consume the returned permit before the notified caller reacquires the <monitor>. Only `down` callers wait here, and they all wait on the same predicate; hence waking one with `notify` is sufficient. A later `up` notifies another waiter if necessary. This use of `notify` will not be safe for the mixed predicates in the next part.<Java 8 Object API documentation>[notify and wait: arbitrary notification choice, monitor reacquisition and spurious wakeups]{ref}

A <binary semaphore> initially available is `new CountingSemaphore(1)`. To initialize it unavailable, call its `down` once during construction, before publishing it to other <software threads>. Its state obeys
$$
\boxed{0\leq\mathrm{count}\leq\mathrm{maxCount};\quad\mathrm{down}:c\mapsto c-1\ (c>0),\quad\mathrm{up}:c\mapsto c+1.}
$$
This implementation provides no first-come-first-served guarantee: a new caller can acquire the <monitor> before a notified waiter. The following examples assume ordinary successful execution without cancellation or interruption of a partially completed buffer operation.