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.

without js -- (tasks)
sequence sems = {}
constant COUNTER = 1, QUEUE = 2
 
function semaphore(integer n)
    if n>0 then
        sems = append(sems,{n,{}})
        return length(sems)
    else
        return 0
    end if
end function
 
procedure acquire(integer id)
    if sems[id][COUNTER]=0 then
        task_suspend(task_self())
        sems[id][QUEUE] &= task_self()
        task_yield()
    end if
    sems[id][COUNTER] -= 1
end procedure
 
procedure release(integer id)
    sems[id][COUNTER] += 1
    if length(sems[id][QUEUE])>0 then
        task_schedule(sems[id][QUEUE][1],1)
        sems[id][QUEUE] = sems[id][QUEUE][2..$]
    end if
end procedure
 
function count(integer id)
    return sems[id][COUNTER]
end function
 
procedure delay(atom delaytime)
    atom t = time()
    while time()-t<delaytime do
        task_yield()
    end while
end procedure
 
integer sem = semaphore(4)
 
procedure worker()
    acquire(sem)
    printf(1,"- Task %d acquired semaphore.\n",task_self())
    delay(2)
    release(sem)
    printf(1,"+ Task %d released semaphore.\n",task_self())
end procedure
 
for i=1 to 10 do
    integer task = task_create(routine_id("worker"),{})
    task_schedule(task,1)
    task_yield()
end for
 
integer sc = 0
atom t0 = time()+1
while length(task_list())>1 do
    task_yield()
    integer scnew = count(sem)
    if scnew!=sc
    or time()>t0 then
        sc = scnew
        printf(1,"Semaphore count now %d\n",{sc})
        t0 = time()+2
    end if
end while
?"done"
{} = wait_key()
