Я тутМониторнаписал. В удачном случае (т.е. когда не надо ожидать) вход+выход выполняется примерно за 16 машинных инструкций. В дотнетеМониторв удачном случае срабатывает примерно за 5 инструкций, но там видимо компилятор инлайнит код.

## Код:
```
MODULE Monitor;

  IMPORT WinApi;
  
  TYPE
    Handle* = POINTER TO LIMITED RECORD
      count: INTEGER;
      enter, pulse: WinApi.HANDLE
    END;

  PROCEDURE New* (): Handle;
    VAR h: Handle;
  BEGIN NEW(h);
    h.enter := WinApi.CreateEvent(NIL, WinApi.FALSE, WinApi.TRUE, NIL);
    h.pulse := WinApi.CreateEvent(NIL, WinApi.TRUE, WinApi.FALSE, NIL);
    RETURN h
  END New;

  PROCEDURE Enter* (h: Handle);
    VAR res: INTEGER;
  BEGIN
    IF WinApi.InterlockedIncrement(h.count) # 1 THEN
      res := WinApi.WaitForSingleObject(h.enter, WinApi.INFINITE)
    END
  END Enter;

  PROCEDURE Exit* (h: Handle);
    VAR ok: WinApi.BOOL;
  BEGIN
    IF WinApi.InterlockedDecrement(h.count) # 0 THEN
      ok := WinApi.SetEvent(h.enter)
    END
  END Exit;

  PROCEDURE Wait* (h: Handle);
    VAR res: INTEGER;
  BEGIN    
    res := WinApi.SignalObjectAndWait(h.enter, h.pulse, WinApi.INFINITE, WinApi.FALSE);
    res := WinApi.InterlockedDecrement(h.count);
    Enter(h)
  END Wait;

  PROCEDURE Pulse* (h: Handle);
    VAR ok: WinApi.BOOL;
  BEGIN ok := WinApi.PulseEvent(h.pulse)
  END Pulse;

  PROCEDURE (h: Handle) FINALIZE-;
    VAR ok: WinApi.BOOL;
  BEGIN
    ok := WinApi.CloseHandle(h.pulse);
    ok := WinApi.CloseHandle(h.enter)
  END FINALIZE;

END Monitor.
```


Пример использования:
## Код:
```
IMPORT Monitor;

  TYPE
    Element* = INTEGER;

    Queue* = POINTER TO LIMITED RECORD
      synchRoot: Monitor.Handle;
      buffer: ARRAY 3 OF Element;
      begin, end, count, enqueued, dequeued: INTEGER;
    END;

  PROCEDURE NewQueue* (): Queue;
    VAR q: Queue;
  BEGIN NEW(q);
    q.synchRoot := Monitor.New();
    RETURN q
  END NewQueue;

  PROCEDURE (q: Queue) Enqueue* (e: Element), NEW;
  BEGIN
    Monitor.Enter(q.synchRoot);
    WHILE q.count >= LEN(q.buffer) DO Monitor.Wait(q.synchRoot) END;
    INC(q.count);
    INC(q.enqueued);
    q.buffer[q.end] := e;
    q.end := (q.end + 1) MOD LEN(q.buffer);
    Monitor.Pulse(q.synchRoot);
    Monitor.Exit(q.synchRoot)
  END Enqueue;

  PROCEDURE (q: Queue) Dequeue* (OUT e: Element), NEW;
  BEGIN
    Monitor.Enter(q.synchRoot);
    WHILE q.count < 1 DO Monitor.Wait(q.synchRoot) END;
    DEC(q.count);
    INC(q.dequeued);
    e := q.buffer[q.begin];
    q.begin := (q.begin + 1) MOD LEN(q.buffer);
    Monitor.Pulse(q.synchRoot);
    Monitor.Exit(q.synchRoot)
  END Dequeue;
```
