StaticVarCompareExchange
- atomic interlocked static variable compare-exchange operation

Miscellaneous functions
(AmiBroker 5.50)


SYNTAX StaticVarCompareExchange( ''varname'', exchange, comperand )
RETURNS NUMBER
FUNCTION Parameters:
  • "varname" - Specifies the name of the destination static variable. Static variable if exists must be scalar numeric type. If static variable is not initialized, the function assumes that it has value of zero.
  • exchange - specifies the exchange value. Scalar numeric.
  • comperand - specifies the value to compare to the destination static variable. Scalar numeric.
Return Values:
The return value is the initial value of the destination static variable. If variable did not exist, it returns zero.

The StaticVarCompareExchange function performs an atomic comparison of the "varname" static variable value with the Comperand value. If the static variable value is equal to the Comperand value, the Exchange value is stored in the static variable. Otherwise, no operation is performed.

The function StaticVarCompareExchange provides a simple mechanism for synchronizing access to static variables that are shared by multiple threads. The following examples show how to implement semaphore and critical section in AFL using StaticVarCompareExchange function. For more details see Tutorial: Efficient use of multithreading.

EXAMPLE // EXAMPLE 1 : Simple semaphore (no waiting)
if( StaticVarCompareExchange( "semaphore", 1, 0 ) == 0 ) // obtain semaphore
{
  
// protected section here
  
// Here you have exclusive access (no other threads that check for semaphore will enter simultaneously)    
  
/////////////////////////
  
StaticVarSet("semaphore", 0 ); // reset semaphore
}
else
{
  
_TRACE("Can not obtain semaphore");
}

///////////////
// EXAMPLE 2 HOW TO IMPLEMENT CRITICAL SECTION IN AFL
///////////////

function _TryEnterCS( secname )
{
  
global _cursec;
   _cursec=
"";

  
// try obtaining semaphore for 1000 ms
  
for( i = 0; i < 1000; i++ )
  
if( StaticVarCompareExchange( secname, 1, 0 ) == 0 )
   {
       _cursec = secname;
      
break;
   }
  
else ThreadSleep( 1 ); //sleep one millisecond

  
return _cursec != "";
}

// call it ONLY when _TryEnterCS returned TRUE !
function _LeaveCS()
{    
  
global _cursec;
  
if( _cursec != "" )
     {
      
StaticVarSet( _cursec, 0 );
       _cursec =
"";
     }
}

function TimeConsumingWork()
{
  
// WARNING: the Percentile is CPU hungry as it involves lots of sorting, the loop below may take > 1 second to complete
  
for( i = 0; i< 10; i++ ) Percentile( C, 100, 10 );
}

//_TRACE("Without CS Begin " + GetChartID() );
//TimeConsumingWork(); // some time consuming calculation
//_TRACE("Without CS End" + GetChartID() );

// Example usage (critical section)
if( _TryEnterCS( "mysemaphore" ) )
{
  
// you are inside critical section now
  
_TRACE("Begin CS " + GetChartID() );
   TimeConsumingWork();
// some time consuming calculation
  
_TRACE("End CS " + GetChartID() );
   _LeaveCS();
}
else
{
  
_TRACE("Unable to enter CS");
}
SEE ALSO ThreadSleep() function

References:

The StaticVarCompareExchange function is used in the following formulas in AFL on-line library:

More information:

See updated/extended version on-line.