移植可能な方法でこれを行うことは実際には不可能です。
ただし、さまざまなコンパイラ組み込み関数を使用して実装できます。
例として、x86(-64) およびおそらく少なくとも ARM 上の gcc の場合:
static int queued_work;
static void inc_queued_work()
{
(void)__sync_add_and_fetch( &queued_work, 1 );
}
/*
Decrement queued_work if > 0.
Returns 1 if queued_work was non-equal to 0 before
this function was called.
*/
static int dec_queued_work()
{
/* Read current value and subtract 1.
If the result is equal to -1, add 1 back and return 0.
*/
if( __sync_sub_and_fetch( &queued_work, 1 ) == -1 )
{
__sync_fetch_and_add( &queued_work, 1 );
return 0;
}
return 1;
}
一部の CPU: は、compare_and_swap のみをサポートします。その組み込み関数を使用してこれを実装することもできます。
/* Alternative solution using compare_and_swap */
void inc_queued_work()
{
do {
int queued = queued_work;
/* Try to write queued-1 to the variable. */
if( __sync_bool_compare_and_swap( &queued_work,
queued, queued+1 ) )
return;
} while( 1 );
}
int dec_queued_work()
{
do {
int queued = queued_work;
if( !queued ) return 0;
/* Try to write queued-1 to the variable. */
if( __sync_bool_compare_and_swap( &queued_work,
queued, queued-1 ) )
return queued;
} while( 1 );
}
これらの関数は、ライターとリーダーが複数ある場合でも機能するはずです。友達と「sync_add_and_fetch」にグーグルを適用すると、多くの参考資料が得られます