Javascript Semaphore

From Yate Documentation
Revision as of 13:39, 9 September 2024 by Marian (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

General

Semaphores use an internal counter used for waiting/signal operations.
Wait (lock) decrements the counter if possible (greater than 0). If possible, returns immediately. If not, the calling thread is will wait until possible.
Signal (unlock) increments the counter. One of the waiting thread will continue processing.


All semaphores created by a script are signaled (unlocked) when the script is unloaded.


For more information on Semaphore see

  • Wikipedia: en.wikipedia.org/wiki/Semaphore_(programming)
  • Linux man pages for sem_wait(), sem_post(), sem_init()

Usage

In the following example we are handling some message, send a request to create a GTP session and wait for the response (asynchronously sent by the gtp module).
Using a semaphore allows us to wait a long period of time for the result without returning in script context to check if result was received.

globalList = {};
globalList_id = 0;

function startGtpSession()
{
    // Prepare response tracking and handling
    var id = Engine.debugName() + ++globalList_id;
    var track = {};
    track.semaphore = new Engine.Semaphore(id);
    globalList[id] = track;
    // Build and send the request
    var m = new Message("gtp.request");
    // Fill request specific parameters ...
    m.context = id;
    if (m.dispatch(true)) {
        while (!track.response) {
            // Remember: Message.dispatch(true) and Semaphore.wait() release script context mutex
            // Check Engine object existence: it will not be available if script is unloaded
            if (!Engine)
                return null;
            track.semaphore.wait(1000);
        }
    }
    delete globalList[id];
    return track.response;
}

function onGtpResponse(msg)
{
    var track = globalList[msg.context];
    if (!track)
        return false;
    delete globalList[msg.context];
    // NOTE: Set some data we may need for response processing in 'track'
    track.response = {};
    // Signal the waiting entity
    if (track.semaphore)
        track.semaphore.signal();
    return true;
}

function someMessageHandler(msg)
{
    var res = startGtpSession();
    if (!res) {
        // Create failed locally
    }
    else {
        // Process result
    }
}

Message.install(someMessageHandler,"somemessage");
Message.install(onGtpResponse,"gtp.response");

Constructor

  • new Engine.Semaphore([name[,initialCount[,maxCount]]])

Parameters:
name String. Semaphore name
initialCount Numeric. Semaphore initial count. Default: 0. Forced to value of maxCount if greater than it
maxCount Numeric. Semaphore maximum count. Default: 1

Semaphore name should always be set for debug purposes.
Yate (see command line parameters) may be started with mutex (any lockable) locking debug options.
A debug message (including semaphore name) will be put in log if wait is called with null (wait forever) but failed to lock semaphore for a globally (internal) period.

maxCount is not standard operating system implementation of semaphore. It's a Yate protection used to avoid too many semaphore signal (unlock) operations

Methods

  • wait(maxWait)

Attempt to get a lock on the semaphore and eventually wait for it.
Parameters:
maxWait Time to wait for locking. null: wait until allowed. Otherwise: interval (in milliseconds) to wait (0: don't wait). Default: 0
Return:
True on success, false otherwise (waiting time elapsed without locking the semaphore or script is unloading)


  • signal()

Unlock the semaphore.
Return:
True on success, false otherwise (no failure reason is known)

Personal tools
Namespaces

Variants
Actions
Preface
Configuration
Administrators
Developers