Asynchronous semaphore
Asynchronous Semaphore is a structure that is used in asynchronous programming models. Its goal is to lock an action, allowing the action to run only after a group of other, asynchronous actions have been executed.
The asynchronous semaphore is a specific use of the abstract structure semaphore in the world of asynchronous programming.
The semaphore concept was invented by Dutch computer scientist Edsger Dijkstra.
Structure of an asynchronous semaphore
Upon creation, an asynchronous semaphore receives a function as an argument: this argument is usually called the "fire-function". The fire-function will be executed after all the asynchronous actions are completed.
The asynchronous semaphore also has a lock variable: a counter which holds the number of asynchronous actions in the queue to be completed. When this counter is zero, all asynchronous actions have been completed and fire function can be called.
The asynchronous semaphore has two additional functions:
The v() function: When this function is called, the internal semaphore lock variable is increased. This increase represents the fact that one of the asynchronous actions has been called and added to the queue of asynchronous actions waiting to complete.
The p() function: When an asynchronous action completes, the p() function is called. The p() function decreases the internal lock variable, representing the fact that an asynchronous action has completed and been removed from the queue. The p() function is called from within the completed asynchronous action's callback function. The p() function also checks if the lock variable, which counts the number of queued asynchronous actions, is zero. If it is, all actions have been completed and the fire function can be called.
Use of an asynchronous semaphore
Whenever the programmer calls one of the asynchronous actions (which will actually be invoked sometime later), the programmer also calls the async semaphore's v() function in order to increase the internal semaphore lock variable which represents the fact that this asynchronous action has been added to the queue.
When the callback of that asynchronous function is done running, the programmer calls the p() function, which decreases the internal lock variable. This represents the fact that the asynchronous action is done.
The p() function also checks if the lock variable equals 0. If it does it means that all the async actions have been completed hence the "fire-function" is allowed to be invoked.
An asynchronous semaphore is efficient when the asynchronous actions are independent.
Example implementation
The following examples are written in JavaScript:
function asem(fireFunc,initLock){
if(initLock)
this.lock=initLock;
else
this.lock=0;
this.func = fireFunc;
}
asem.prototype.v = function(){
this.lock++;
}
asem.prototype.p = function(){
this.lock--;
if(this.lock==0 && this.func)
this.func();
}
In order to enable the programmer to call v() and p() easily, sometimes the asem includes a wrapping functionality
asem.prototype.wrap = function(func){
var self = this;
self.v();
return function(){
if(func)
func.apply(this,arguments);
self.p();
}
}