When cross-platform debugging, use Semaphore of Windows to simulate the value of blocked waiting semaphore under Linux to zero

The semaphore under Linux has an interesting feature. You can block the semaphore and wait for any desired value. Here, the value of the blocked waiting semaphore is zero.
The Linux code is as follows:
sem_buf.sem_num = 0;
sem_buf.sem_op = 0;
sem_buf.sem_flg = 0;


if (semop(mtx, &sem_buf, 1) == -1) {
if (EINTR != errno) {
return -1;
}
} else {
return 0;
}

Create a Semaphore for inter-process communication under Windows, for example:
mtx = OpenSemaphore(SEMAPHORE_ALL_ACCESS/*SEMAPHORE_MODIFY_STATE*/, FALSE, TEXT(name));
if (NULL != mtx) {
fprintf(stderr, "Open mutex[%d] %s success! \n", i, name);  
} else {
fprintf(stderr, "Open mutex[%d] %s failed! create... \n", i, name);  
mtx = CreateSemaphore( 
NULL,           // default security attributes
value, // initial count
20, // maximum count
TEXT(name));    // unnamed semaphore

}

It takes a little skill to simulate blocking waiting semaphore to zero under Windows. The following description in MSDN:
It is not possible to reduce the semaphore object count using ReleaseSemaphore, because lReleaseCount cannot be a negative number. To temporarily restrict or reduce access, create a loop in which you call the WaitForSingleObject function with a time-out interval of zero until the semaphore count has been reduced sufficiently. (Note that other threads can reduce the count while this loop is being executed.) To restore access, call ReleaseSemaphore with the release count equal to the number of times WaitForSingleObject was called in the loop. 


According to MSDN's instructions, the following processing, in fact, can not really solve the problem, it will cause an error in the order of execution between the two processes.
LONG prevCount = 0;
do {
prevCount = 0;
ReleaseSemaphore(mtx, 1, &prevCount); // Here the semaphore +1, the consumer process first grabs the CPU to run, causing the execution sequence to be wrong
WaitForSingleObject(mtx, INFINITE);
if (0 != prevCount) {
Sleep(50);
}
} while (0 != prevCount);


So, naturally, it should be possible to query the current value of Semaphore. However, executing ReleaseSemaphore(mtx, 0, &prevCount) in this way will return error number 7 (parameter error), and prevCount is 0. MSDN says this:
lReleaseCount [in] 
The amount by which the semaphore object's current count is to be increased . The value must be greater than zero. If the specified amount would cause the semaphore's count to exceed the maximum count that was specified when the semaphore was created, the count is not changed and the function returns FALSE.


[Tucao] I really don’t know MS What do you think when designing the ReleaseSemaphore function? Isn't it good that prevCount returns the current semaphore value when you call ReleaseSemaphore(handle, 0, &prevCount)? How about designing another function to query! Linuxer's design should be concise and practical. I remember that there seems to be a comment in the libevent source code saying that MS has some APIs? A shit, it's really a bit.


What should I do? Design a shared memory, save the reference count of the semaphore, then, WaitForSingleObject is reduced by 1, ReleaseSemaphore is increased by 1, and the shared memory is queried in a function that simulates blocking waiting for the semaphore.


class refermanager {
public:
typedef struct refer_t_ {
ISEM_KEY key;
INT32S refers;
}refer_t;
public:
refermanager () {
HANDLE hMap = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, name);
int size = MAX_REFERS_ITEMS * sizeof(refer_t);
if (NULL == hMap) {
hMap = ::CreateFileMapping(INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
size,
name);
}
if (NULL != hMap) {
pMemory = ::MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
} else {
pMemory = NULL;
}
}
~ refermanager () {
};
static void Set(int key, int value);
static void Inc(int key, int value);
static void Dec(int key, int value);
static int  Get(int key);
protect:
void * pMemory;
}


static refermanager g_manager_obj;


Then, after ReleaseSemaphore(mtx, n, &prevCount), execute refermanager::Inc(key, n); After WaitForSingleObject, execute refermanager::Dec(key,1). Block waiting for the function of the semaphore value to be zero, so that
for (int n = 1; n > 0; ) {
n = refermanager::Get(key);
if (n > 0) {
Sleep(50);
}
}


Furthermore, in order to prevent two processes from accessing pMemory at the same time, pMemory needs to be locked. Mutex or Semaphore can be used. There are a lot of tutorials on the Internet, so I won’t be too long-winded here. I wish Linuxers under Windows have fun. happy.











Guess you like

Origin blog.csdn.net/hylaking/article/details/79031868