The goal of this task is to create a counting semaphore used to control the execution of a set of concurrent units. This task intends to demonstrate coordination of active concurrent units through the use of a passive concurrent unit. The operations for a counting semaphore are acquire, release, and count. Each active concurrent unit should attempt to acquire the counting semaphore before executing its assigned duties. In this case the active concurrent unit should report that it has acquired the semaphore. It should sleep for 2 seconds and then release the semaphore.

declare
  fun {NewSemaphore N}
     sem(max:N count:{NewCell 0} 'lock':{NewLock} sync:{NewCell _})
  end
 
  proc {Acquire Sem=sem(max:N count:C 'lock':L sync:S)}
     Sync
     Acquired
  in
     lock L then
        if @C < N then
         C := @C + 1
         Acquired = true
        else
         Sync = @S
         Acquired = false
        end
     end
     if {Not Acquired} then
        {Wait Sync}
        {Acquire Sem}
     end
  end
 
  proc {Release sem(count:C 'lock':L sync:S ...)}
     lock L then
        C := @C - 1
        @S = unit %% wake up waiting threads
        S := _ %% prepare for new waiters
     end
  end
 
  proc {WithSemaphore Sem Proc}
     {Acquire Sem}
     try
        {Proc}
     finally
        {Release Sem}
     end
  end
 
  S = {NewSemaphore 4}
 
  proc {StartWorker Name}
     thread
	for do
	   {WithSemaphore S
	    proc {$}
	       {System.showInfo Name#" acquired semaphore"}
	       {Delay 2000}
	    end
	   }
	   {Delay 100}
	end
     end
  end
in
  for I in 1..10 do
     {StartWorker I}
  end