Name

global.Mutex

Description

API to Acquire a database-based, system-wide, named mutex & Release the mutex after use This is appropriate for a Mutex that protects a resource with a predictable, regular name. (cf. SelfCleaningMutex, which is more appropriate for a Mutex that locks an arbitrary resource with an unpredictable name.) Caveats The mutex is stored system-wide, in the database, so there is a performance cost to using it. therefore do not acquire and release inside a tight loop! The Mutex Name is the scope of the mutex, and can be anything appropriate, though there are conventions in use in some parts of the system, e.g. the table name . Status of Interface Evolving, subject to change. // Example usage var MY_MUTEX = <<<--My Mutex Name-->>> ; ... // Easiest, if you have a single function or method that needs to be restricted to one execution at a time // call myFunction(), in this scope, with arguments (myFunctionArgument1, myFunctionArgument2, ...) // myFunction can also be an anonymous function defined inline. var returnValue = Mutex.enterCriticalSection( MY_MUTEX, this, myFunction, myFunctionArgument1, myFunctionArgument2, ... ); // Alternate more complex way, manually create the mutex object var myMutex = new Mutex(MY_MUTEX); // optional myMutex.setSpinWait(200); // time to wait between attempts, in ms myMutex.setMaxSpins(125); // maximum number of times to try // get the mutex, and then enter the critical section // use finally , to make sure that the mutex is always released. if (myMutex.get()) try { // enter critical section ... } finally { myMutex.release(); }

Script

var Mutex = Class.create();

/*
* Enter the Critical section, as identified by the mutexName
* and execute the specified criticalFunction() with the given arguments
*/
Mutex.enterCriticalSection = function(mutexName, scope, criticalFunction /*, optional arguments to criticalFunction() */) {
 var mutex = new Mutex('<<<--' + mutexName + '-->>>');
 return mutex.enterCriticalSection.apply(mutex, arguments);
};

/*
* Enter the Critical section, as identified by the mutexName and metricName
* and execute the specified criticalFunction() with the given arguments
*/
Mutex.enterCriticalSectionRecordInStats = function(mutexName, metricName, scope, criticalFunction /*, optional arguments to criticalFunction() */) {
 var mutex = new Mutex('<<<--' + mutexName + '-->>>', metricName);
 return mutex.enterCriticalSectionRecordInStats.apply(mutex, arguments);
};

Mutex.prototype = {
 initialize : function(mutexId, metricName) {
    var uniqueIdentifier = metricName;
    if (typeof metricName === 'undefined') 
  	  uniqueIdentifier = '';
    this._mutex = new GlideMutex(mutexId, uniqueIdentifier);
    // limit our attempt to get a mutex
    this.setSpinWait(this._getScriptSpinWaitSetting());
    this.setMaxSpins(this._getScriptMaxSpinsSetting());
 },
 
 // 100ms, 100 times == 10 seconds
 DEFAULT_SPINWAIT_MS: 100,
 DEFAULT_MAXSPINS:    100, 
 
 // properties to override the above default values, for Mutex
 MUTEX_SPINWAIT_MS: 'com.glide.mutex.script.spinwait',
 MUTEX_MAXSPINS: 'com.glide.mutex.script.maxspins',

 get: function() {
    return this._mutex.get();
 },

 release: function() {
    return this._mutex.release();
 },

 // how long, in ms, to wait between lock attempts
 setSpinWait: function(waitMS) {
    return this._mutex.setSpinWait(waitMS);
 },

 // how many times get() will try to acquire a lock.
 setMaxSpins: function(n) {
    return this._mutex.setMaxSpins(n);
 },
 
 // after acquiring mutexName, execute criticalFunction, in the Script scope
 enterCriticalSection: function(mutexName, scope, criticalFunction /*, optional arguments to criticalFunction() */) {
    // Arrange our remaining arguments, for calling the criticalFunction
    // arguments[0]   - mutexName
    // arguments[1]   - scope to execute criticalFunction() in, usually 'this'
    // arguments[2]   - criticalFunction()
    // arguments[3..] - arguments to criticalFunction()
    var args = [];
    var func = arguments[2];
    for (var i=3; i< arguments.length; i++)
       args.push(arguments[i]);

    var rval;
    if (this.get()) {
       try {
          rval = func.apply(scope, args);
       }
       finally {
          this.release();
       }
    }
    
    return rval;
 },
  
 // after acquiring mutexName, execute criticalFunction, in the Script scope
 enterCriticalSectionRecordInStats: function(mutexName, metricName, scope, criticalFunction /*, optional arguments to criticalFunction() */) {
    // Arrange our remaining arguments, for calling the criticalFunction
    // arguments[0]   - mutexName
    // arguments[1]   - metricName (this is tracked in the performance graphs)
    // arguments[2]   - scope to execute criticalFunction() in, usually 'this'
    // arguments[3]   - criticalFunction()
    // arguments[4..] - arguments to criticalFunction()
    var args = [];
    var func = arguments[3];
    for (var i=4; i< arguments.length; i++)
       args.push(arguments[i]);

    var rval;
    if (this.get()) {
       try {
          rval = func.apply(scope, args);
       }
       finally {
          this.release();
       }
    }
    
    return rval;
 }, 	 
 
 // 100 ms, if not overridden by the (com.glide.mutex.script.spinwait) property value
 _getScriptSpinWaitSetting: function() {
    return gs.getProperty(this.MUTEX_SPINWAIT_MS, this.DEFAULT_SPINWAIT_MS);
 },
 
 // 100 times, if not overriden by the (com.glide.mutex.script.maxspins) property value
 _getScriptMaxSpinsSetting: function() {
    return gs.getProperty(this.MUTEX_MAXSPINS, this.DEFAULT_MAXSPINS);
 },

 type: 'Mutex'
};

Sys ID

c1bc1dc90a0a2c391faa7cf7cc1cb267

Offical Documentation

Official Docs: