What s the Windows exact equivalent of WaitOnAddress() on Linux?

1.4k Views Asked by At

Using shared memory with the shmget() system call, the aim of my C++ program, is to fetch a bid price from the Internet through a server written in Rust so that each times the value changes, I m performing a financial transaction.

Server pseudocode

Shared_struct.price = new_price

Client pseudocode

Infinite_loop_label:
     Wait until memory address pointed by Shared_struct.price changes.
     Launch_transaction(Shared_struct.price*1.13)
Goto Infinite_loop

Since launching a transaction involve paying transaction fees, I want to create a transaction only once per buy price change.

Using a semaphore or a futex, I can do the reverse, I m meaning waiting for a variable to reachs a specific value, but how to wait until a variable is no longer equal to current value?

Whereas on Windows I can do something like this on the address of the shared segment:

ULONG g_TargetValue; // global, accessible to all process
ULONG CapturedValue;
ULONG UndesiredValue;

UndesiredValue = 0;
CapturedValue = g_TargetValue;
while (CapturedValue == UndesiredValue) {
      WaitOnAddress(&g_TargetValue, &UndesiredValue, sizeof(ULONG), INFINITE);
      CapturedValue = g_TargetValue;
}

Is there a way to do this on Linux? Or a straight equivalent?

1

There are 1 best solutions below

8
On

You can use futex. (I assumed "var" is in shm mem)

/* Client */

int prv;

while (1) {
  int prv = var;
  int ret = futex(&var, FUTEX_WAIT, prv, NULL, NULL, 0);
  /* Spurious wake-up */
  if (!ret && var == prv) continue;
  doTransaction();
}

/* Server */

int prv = NOT_CACHED;
while(1) {
  var = updateVar();
  if (var != prv || prv = NOT_CACHED)
    futex(&var, FUTEX_WAKE, 1, NULL, NULL, 0);
  prv = var;
}

It requires the server side to call futex as well to notify client(s).

Note that the same holds true for WaitOnAddress.

According to MSDN:

Any thread within the same process that changes the value at the address on which threads are waiting should call WakeByAddressSingle to wake a single waiting thread or WakeByAddressAll to wake all waiting threads.

(Added)

More high level synchronization method for this problem is to use condition variable. It is also implemented based on futex. See link