Reputation: 13
I am trying to use the WaitOnAddress()
function to achieve read-write synchronization.
According to MSDN, WaitOnAddress()
has the following declaration:
BOOL WaitOnAddress(
volatile VOID *Address,
PVOID CompareAddress,
SIZE_T AddressSize,
DWORD dwMilliseconds
);
and the following parameter definition:
CompareAddress
A pointer to the location of the previously observed value at
Address
. The function returns when the value atAddress
differs from the value atCompareAddress
.
According to the definition, I should store and pass the current value of the watched address, so when the watch value changes, WaitOnAddress()
will return. But this function does not work as I expected, so I wrote the following test code for WaitOnAddress()
in Visual Studio (and also included linker library Synchronization.lib
):
#include <stdio.h>
#include <stdlib.h> // atoi
#include <string.h>
// include these two files after including winsock2.h
#include <process.h>
#include <Windows.h>
#include <synchapi.h>
void* threads(void* num) {
int* number = (int*)num;
for (int i = 0; i < 10; i++) {
printf("number = %d\n", *number);
}
int catch = *number; // will be passed as CompareAddress
WaitOnAddress((int*)num, &catch, sizeof(int), INFINITE);
for (int i = 0; i < 10; i++) {
printf("number2 = %d, %d\n", catch, *(int*)num);
}
return NULL;
}
int main() {
int int_list[10];
for (int i = 0; i < 10; i++) {
int_list[i] = i;
_beginthread(threads, 0, (void*)&int_list[i]);
}
printf("hello\n");
Sleep(1000);
for (int i = 0; i < 10; i++) {
int_list[i] = 10 - i;
}
printf("changed\n");
Sleep(1000);
return 0;
}
In above code, WaitOnAddress()
never returns even though the value it watches changes. But, if I change
int catch = *number;
to:
int catch = 10 - *number;
then WaitOnAddress()
returns and the rest of the output is printed, as if it returns ONLY when the watched value matches the compared value.
But, I want to used the described behavior so my thread is released whenever the watched variable is changed.
Upvotes: 0
Views: 205
Reputation: 3890
According to the documentation:
Parameters
Address
The address on which to wait. If the value at Address differs from the value at CompareAddress, the function returns immediately. If the values are the same, the function does not return until another thread in the same process signals that the value at Address has changed by calling WakeByAddressSingle or WakeByAddressAll or the timeout elapses, whichever comes first.
Although you modify the value of the original array in the second loop, the catch
and num
are always the same when calling WaitOnAddress
in the thread, so the WaitOnAddress
function will not return.
You can try to modify it to:
#include <stdio.h>
#include <stdlib.h> // atoi
#include <string.h>
// include these two files after including winsock2.h
#include <process.h>
#include <Windows.h>
void* threads(void* num) {
int* number = (int*)num;
printf("number = %d\n", *number);
int catch = *number; // will be passed as CompareAddress
WaitOnAddress((int*)num, &catch, sizeof(int), INFINITE);
printf("number2 = %d, %d\n", catch, *(int*)num);
return NULL;
}
int main() {
int int_list[10];
for (int i = 0; i < 10; i++) {
int_list[i] = i;
_beginthread(threads, 0, (void*)&int_list[i]);
}
printf("hello\n");
Sleep(1000);
printf("changed\n");
for (int i = 0; i < 10; i++) {
int_list[i] = 10 - i;
WakeByAddressSingle(&int_list[i]);
}
Sleep(1000);
return 0;
}
And it works for me:
Upvotes: 2