Demonstrate the “rendezvous” communications technique by implementing a printer monitor.

import asyncdispatch, options, strutils
type
  Printer = ref object
    inkLevel, id: int
    backup: Option[Printer]
  OutOfInkException = object of IOError
proc print(p: Printer, line: string){.async.} =
  if p.inkLevel <= 0:
    if p.backup.isNone():
      raise newException(OutOfInkException, "out of ink")
    else:
      await p.backup.get().print(line)
  else:
    p.inkLevel-=1
    stdout.writeLine("$1:$2".format(p.id, line))
    await sleepAsync(100)
proc newPrinter(inkLevel, id: int, backup: Option[Printer]): Printer =
  new(result)
  result.inkLevel = inkLevel
  result.id = id
  result.backup = backup
 
proc print(p: Printer, msg: seq[string]){.async.} =
  for line in msg:
    try:
      await p.print(line)
    except OutOfInkException as e:
      echo("out of ink")
      break
const
  humptyLines = @[
    "Humpty Dumpty sat on a wall.",
    "Humpty Dumpty had a great fall.",
    "All the king's horses and all the king's men,",
    "Couldn't put Humpty together again.",
    ]
  gooseLines = @[
        "Old Mother Goose,",
        "When she wanted to wander,",
        "Would ride through the air,",
        "On a very fine gander.",
        "Jack's mother came in,",
        "And caught the goose soon,",
        "And mounting its back,",
        "Flew up to the moon.",
    ]
proc main(){.async.} =
  var
    reservePrinter = newPrinter(5, 2, none(Printer))
    mainPrinter = newPrinter(5, 1, some(reservePrinter))
  await mainPrinter.print(gooseLines) and mainPrinter.print(humptyLines)
 
waitFor main()