Readers Writers - Writer thread always stuck with multiple reader thread - c++

New bie here.
I have been working on readers/ writers problem solution.
It works perfectly fine with 1 reader and 1 writer.
But when I modify reader to 2; writer thread always starves. Help me!
It seems Writer thread is stuck somewhere waiting for wrt mutex.
#include <stdio.h>
#include <conio.h>
#include <windows.h>
HANDLE mutex, wrt;
int g_ReadCount = 0;
int g_GlobalData=0;
const int max = 2;
HANDLE reader[max], writer[max];
CRITICAL_SECTION rSect, wSect;
bool bTerminate = true;
DWORD Readers(LPVOID lpdwThreadParam )
{
while(bTerminate)
{
WaitForSingleObject(mutex, INFINITE);
g_ReadCount++;
if(g_ReadCount == 1)
{
WaitForSingleObject(wrt, INFINITE);
}
ReleaseMutex(mutex);
EnterCriticalSection(&wSect);
printf("ThreadId : %d --> Read data : %d ReaderCount %d\n", GetCurrentThreadId(), g_GlobalData, g_ReadCount);
LeaveCriticalSection(&wSect);
WaitForSingleObject(mutex, INFINITE);
g_ReadCount--;
if(g_ReadCount == 0)
{
ReleaseMutex(wrt);
printf("ThreadId : %d Realesed Mutex wrt\n", GetCurrentThreadId());
}
printf("ThreadId : %d ReaderCount %d\n", GetCurrentThreadId(), g_ReadCount);
ReleaseMutex(mutex);
printf("Reader ThreadId : %d Realesed Mutex mutex\n", g_ReadCount);
Sleep(0);
}
return 0;
}
DWORD Writers(LPVOID lpdwThreadParam )
{
int n = GetCurrentThreadId();
int temp = 1;
while(bTerminate)
{
printf("ThreadId : %d Waiting for WRT\n", GetCurrentThreadId());
WaitForSingleObject(wrt, INFINITE);
printf("WRITER ThreadId : %d ***Got WRT\n", GetCurrentThreadId());
++n;
temp++;
if(temp == 100)
{
//bTerminate = false;
}
EnterCriticalSection(&wSect);
printf("Write by ThreadId : %d Data : %d Temp %d\n", GetCurrentThreadId(), n, temp);
g_GlobalData = n;
LeaveCriticalSection(&wSect);
ReleaseMutex(wrt);
}
printf("***VVV***Exiting Writer Thread\n");
return 0;
}
void main()
{
mutex = CreateMutex(NULL, false, "Writer");
wrt = CreateMutex(NULL, false, "wrt");
InitializeCriticalSection(&rSect);
InitializeCriticalSection(&wSect);
DWORD dwThreadId = 0;
for(int i=0; i < max; i++)
{
reader[i] = CreateThread(NULL, //Choose default security
0, //Default stack size
(LPTHREAD_START_ROUTINE)&Readers,
//Routine to execute
(LPVOID) 0, //Thread parameter
0, //Immediately run the thread
&dwThreadId //Thread Id
);
}
for(int i=0; i < 1; i++)
{
writer[i] = CreateThread(NULL, //Choose default security
0, //Default stack size
(LPTHREAD_START_ROUTINE)&Writers,
//Routine to execute
(LPVOID) 0, //Thread parameter
0, //Immediately run the thread
&dwThreadId //Thread Id
);
}
getchar();
}

With more than 1 reader thread, it is quite likely that g_ReadCount will never get to zero, so the wrt mutex will never be released (thus starving the writer). You probably need some kind of indicator that the writer thread is waiting. Then the reader threads would need to give precedence to the writer at some point.
For example, in one implementation I wrote (not saying it is a great way, but it worked) I used a flag that was set/cleared via atomic increment/decrement operations that indicated if a writer thread was waiting for the lock. If so, the readers would hold off. Of course, in that case you also need to then be careful of the opposite situation where writer threads (if more than one) could starve readers. Read/Write locks are tricky.

While working on this problem; I found interesting issue.
During study; we told that Semaphore with max count =1 is equal to Mutex. That is not entirely true.
1) Mutex can not be released by any other thread.
2) Semaphore can be used in such situation.

Related

How to directly "assign" a process to a semaphore using windows API?

I'm using the following code from Microsoft as a template:
#include <windows.h>
#include <stdio.h>
#define MAX_SEM_COUNT 10
#define THREADCOUNT 12
HANDLE ghSemaphore;
DWORD WINAPI ThreadProc( LPVOID );
int main( void )
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
ghSemaphore = CreateSemaphore(
NULL, // default security attributes
MAX_SEM_COUNT, // initial count
MAX_SEM_COUNT, // maximum count
NULL); // unnamed semaphore
if (ghSemaphore == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
return 1;
}
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
}
// Wait for all threads to terminate
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread and semaphore handles
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghSemaphore);
return 0;
}
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
BOOL bContinue=TRUE;
while(bContinue)
{
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
ghSemaphore, // handle to semaphore
0L); // zero-second time-out interval
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
// TODO: Perform task
printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
bContinue=FALSE;
// Simulate thread spending time on task
Sleep(5);
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
ghSemaphore, // handle to semaphore
1, // increase count by one
NULL) ) // not interested in previous count
{
printf("ReleaseSemaphore error: %d\n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
}
return TRUE;
}
And I want to adapt it so instead of being the threads the ones that determine how the semaphore fills, it's done by processes, meaning that the semaphore will fill if there are processes running and/or with any of their habdles not closes, and indeed I sort of have done it by changing the working of the thread function with this new function.
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
BOOL bContinue=TRUE;
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si,0,sizeof(si));
si.cb=sizeof(si);
while(bContinue)
{
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
ghSemaphore, // handle to semaphore
0L); // zero-second time-out interval
CreateProcess("arbol.exe",NULL,NULL,NULL,0,0,NULL,NULL,&si,&pi);
WaitForSingleObject(pi.hProcess,INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
// TODO: Perform task
printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
bContinue=FALSE;
// Simulate thread spending time on task
Sleep(5);
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
ghSemaphore, // handle to semaphore
1, // increase count by one
NULL) ) // not interested in previous count
{
printf("ReleaseSemaphore error: %d\n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
}
return TRUE;
}
With that, although what determines the filling of the semaphore is the thread, in a practical sense it is determined by the complete execution and closing of the handles of the process.
But this looks as a lame way to solve this problem and I bet doing it this way is likely to give problems in the future if extra things are needed from those processes.
How can I create a semaphore so what would really determine the filling of the semaphore would be the processes? To clarify, this would be one possible solution that I don't think it is possible anyhow.
Let's consider that you could Create a Process by something like this:
aThread[i] = CreateProcess(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
Then LPTHREAD_START_ROUTINE would be equivalent in its working but for processes.
Semaphores are supposed to support Interprocess Synchronization in Windows API, but I cannot find any example that specifically uses processes, and I don't get the idea of how could it be done.
Any idea on how to achieve what I want?
Regards.
You want a named semaphore. Where each process shares the semaphore by creating it with the same name.
Create a named semaphore. Same as you have before, but that last parameter gets a string passed to it:
HANDLE hSemaphore = CreateSemaphore(NULL,
MAX_SEM_COUNT,
MAX_SEM_COUNT,
L"TheSemaphoreForMyApp");
Child processes, upon being started, can attach to that same semaphore and get a handle to it by using OpenSemaphore.
HANDLE hSemaphore = OpenSemaphore(EVENT_ALL_ACCESS,
FALSE,
L"TheSemaphoreForMyApp");
You don't have to hardcode a string as the semaphore name. The parent process can create a unique name each time, and then passes that name (e.g. command line parameter) to the child process. That will allow for multiple instances of your program with child processes to cooperate.

Why semaphore is released but WaitForSingleObject() still stuck?

UPDATE: I found that the semaphore they are releasing is not the semaphore the monitor thread is waiting! I used cout<<ready to find the semaphore the threads are releasing is 00000394, which is not the handle of the semaphore the monitor thread is waiting for. What is the possible reason for this problem? Thank you!
I am new to multithread programming in Windows. Today when I'm writing my online game server, I try to use semaphores in Windows. It is written based on IOCP so that every message is handled in a separate thread. A game consists 4 players.
What I expect it to do is: when receiving a message, a new thread starts and release a ready. There is a monitor thread waiting for 4 ready, and then releases 4 all_ready. Each thread waits one all_ready and goes on.
The code is here:
CGameHost is a manager for a 4-player game.
CGameHost::CGameHost(void)
{
init_times=0;
ready = CreateSemaphore(NULL, 0, 4, NULL);
read = CreateSemaphore(NULL, 0, 4, NULL);
all_ready = CreateSemaphore(NULL, 0, 4, NULL);
all_read = CreateSemaphore(NULL, 0, 4, NULL);
monitor_thread = (HANDLE)_beginthreadex(NULL, 0, Monitor, (LPVOID)this, NULL, 0);
}
unsigned __stdcall CGameHost::Monitor( LPVOID p ) // a static function
{
CGameHost *nowp = (CGameHost *)p;
while(true)
{
int i;
for(i=1;i<=MAX_PLAYER;i++)
{
WaitForSingleObject(nowp->ready, INFINITE);//stuck here
cout<<"Get Ready!"<<endl; // This is not outputed, which means it stucks in the last row.
}
for(i=1;i<=MAX_PLAYER;i++)
{
ReleaseSemaphore(nowp->all_ready, 1, NULL);
}
for(i=1; i<=MAX_PLAYER; i++)
{
WaitForSingleObject(nowp->read, INFINITE);
}
for(i=1; i<=MAX_PLAYER;i++)
{
ReleaseSemaphore(nowp->all_read, 1, NULL);
}
}
return 0;
}
void CGameHost::ReleaseReady()
{
ReleaseSemaphore(ready, 1, NULL);
}
void CGameHost::WaitAllReady()
{
WaitForSingleObject(all_ready, INFINITE);
}
void CGameHost::ReleaseRead()
{
ReleaseSemaphore(read, 1, NULL);
}
void CGameHost::WaitAllRead()
{
WaitForSingleObject(all_read, INFINITE);
}
DataProcess::Game is the message handler for incoming game messages.
CMessage Dataprocess::Game( CMessage* recv_msg )
{
CMessage ret;
int now_roomnum = recv_msg->para1;
int now_playernum = recv_msg->para2;
if(true)
{
cout<<"Received Game Message: "<<endl;
cout<<"type2 = "<<recv_msg->type2;
cout<<" player_num = "<<now_playernum<<" msg= "<<recv_msg->msg<<endl;
}
if(recv_msg->type2 == MSG_GAME_OPERATION)
{
ret.type1 = MSG_GAME;
ret.type2 = MSG_GAME_OPERATION;
cout<<"Entered from "<<now_playernum<<endl;
game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg);
game_host[now_roomnum].ReleaseReady();
cout<<"Released Ready from "<<now_playernum<<endl;//this is shown
game_host[now_roomnum].WaitAllReady();//stuck here
cout<<"AllReady from"<<now_playernum<<endl;//not shown
}
return ret;
}
Your reply will be of great help for a beginner of Windows multithread programmer like me! Thank you!
If I understood your needs, you should probably have something like this..
HANDLE hPlayersReady[4];
HANDLE hAllPlayed;
Create these 5 events, and then on your monitor thread,
do something like this...
while(true)
{
// Wait for all players to move
WaitForMultipleObjects(4, &hPlayersReady, true, INFINITE);
// Process move
...
// Advise players the move was processed...
SetEvent(hAllPlayed);
}
And on your player thread X
while(true)
{
// Make my move
...
// Advise monitor I'm ready
SetEvent(hPlayersReady[X]);
// Wait for ready to do another move
WaitForSingleObject(hAllPlayed);
}
Well, I solved it myself. The reason is that I used CreateSemaphore again after creating the thread, making the player thread visiting different semaphores as the monitor thread... Sorry for my stupidness, and thank you for telling me so much!

is recursive mutex lock?

I have a question about mutex_lock. My code does the following:
RIL_startEventLoop lock the mutex by pthread_mutex_lock(&s_startupMutex);
Call the thread eventLoop;
eventLoop locks the mutex by pthread_mutex_lock(&s_startupMutex);
eventLoop unlocks the mutex by pthread_mutex_unlock(&s_startupMutex);
RIL_startEventLoop unlocks the mutex by pthread_mutex_unlock(&s_startupMutex);
My understanding is the following (correct me if wrong):
Lock the mutex exclusively for this task. If the mutex is not available right now, it will sleep until it can get it.
The mutex must later on be released by the same task that acquired it. Recursive locking is not allowed.
Why can eventLoop lock same mutex that is not released by RIL_startEventLoop?
These 2 functions are in Ril.cpp:
RIL_startEventLoop(void) {
int ret;
pthread_attr_t attr;
#ifdef MTK_RIL
RIL_startRILProxys();
#endif /* MTK_RIL */
/* spin up eventLoop thread and wait for it to get started */
s_started = 0;
**pthread_mutex_lock(&s_startupMutex);**
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_dispatch, &attr, **eventLoop**, NULL);
while (s_started == 0) {
pthread_cond_wait(&s_startupCond, &s_startupMutex);
}
**pthread_mutex_unlock(&s_startupMutex);**
if (ret < 0) {
LOGE("Failed to create dispatch thread errno:%d", errno);
return;
}
}
static void *
**eventLoop(void *param)** {
int ret;
int filedes[2];
ril_event_init();
**pthread_mutex_lock(&s_startupMutex);**
s_started = 1;
pthread_cond_broadcast(&s_startupCond);
**pthread_mutex_unlock(&s_startupMutex);**
ret = pipe(filedes);
if (ret < 0) {
LOGE("Error in pipe() errno:%d", errno);
return NULL;
}
s_fdWakeupRead = filedes[0];
s_fdWakeupWrite = filedes[1];
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
processWakeupCallback, NULL);
rilEventAddWakeup (&s_wakeupfd_event);
// Only returns on error
ril_event_loop();
LOGE ("error in event_loop_base errno:%d", errno);
return NULL;
}
Because the call to pthread_cond_wait() releases the mutex.
pthread_cond_wait() does this in an atomic fashion.
Release the mutex (It must already be acquired)
Suspend the thread until the condition is signalled
Acquires the mutex

Why isn't the mutex being aquired?

I have been looking into all of the different syncronization primitives available in the WinAPI, but have been struggling with what should have been something simple. Why doesn't the following code work?
class MultiThreadedCounter
{
private:
int count; HANDLE hMutex;
public:
void IncrementCounter()
{
if (count == 0)
hMutex = CreateMutex(NULL, TRUE, NULL);
count++;
}
void DecrementCounter()
{
count--;
if (count == 0)
ReleaseMutex(hMutex);
}
void WaitForCounterToReachZero()
{
WaitForSingleObject(hMutex, INFINITE);
CloseHandle(hMutex);
}
};
MultiThreadedCounter extractionsInProgressCounter;
It's definitely getting called in the right order. First, IncrementCounter() is called by the main thread before the async task (here, a thread sleep). Then the main thread calls WaitForCounterToReachZero(). Finally, the background thread calls DecrementCounter() when it has completed its work, which should allow the main thread to proceed.
However, WaitForSingleObject is not waiting. It returns immediately, with WAIT_OBJECT_0. Why is it doing that? It's almost like the mutex was never initially aquired. However, in the call to CreateMutex, I set bInitialOwner to TRUE, which is why I don't understand why it doesn't seem to have been aquired. I guess I have misunderstood something.
Thank you.
EDIT 1:
OK, so to test, I changed IncrementCounter() to:
void IncrementCounter()
{
if (count == 0)
{
hMutex = CreateMutex(NULL, TRUE, NULL);
DWORD var1 = WaitForSingleObject(hMutex, INFINITE);
DWORD var2 = WaitForSingleObject(hMutex, INFINITE);
}
count++;
}
That really, really should have deadlocked it, but no, both calls to WaitForSingleObject returned immediately with var1 and var2 both equal to 0 (which according to the headers is WAIT_OBJECT_0).
The call to CreateMutex can't be working, can it? Yet hMutex gets set to a sensible value and GetLastError() remains at 0. So confused...
EDIT 2: Thank you all for your help. I never got this to work, however, I now realise that I was doing this the wrong way anyway. So I switched everything over to an Event, at which point it worked, then added a few conditionals to deal with out of order increments & decrements, then a critical section to protect the count variable. And it works :)
class MultiThreadedCounter
{
private:
int count; HANDLE hEvent; CRITICAL_SECTION criticalSection;
public:
void IncrementCounter()
{
EnterCriticalSection(&criticalSection);
if (count == 0)
ResetEvent(hEvent);
count++;
LeaveCriticalSection(&criticalSection);
}
void DecrementCounter()
{
EnterCriticalSection(&criticalSection);
if (count > 0)
count--;
if (count == 0)
SetEvent(hEvent);
LeaveCriticalSection(&criticalSection);
}
void WaitForCounterToReachZero()
{
WaitForSingleObject(hEvent, INFINITE);
}
MultiThreadedCounter()
{
hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
InitializeCriticalSection(&criticalSection);
count = 0;
}
~MultiThreadedCounter()
{
CloseHandle(hEvent);
DeleteCriticalSection(&criticalSection);
}
};
You don't show a constructor for MultiThreadedCounter. Without this, there is no place to initialise count to 0, meaning that the first call to IncrementCounter almost certainly won't call CreateMutex
Your constructor should look something like
MultiThreadedCounter()
: count(0)
, hMutex(NULL)
{
}
As an aside, if you need a lock that is used between threads in a single process, you could consider using a critical section instead.

Why does the thread synchronization not work?

I have written a multithreaded program, in which three threads are trying to save the text to the same file. I applied the critical section. And under windows 7 works perfectly but in CE 6.0 does not sync, ie, each thread is trying at the same time to save:
It works now!!! Thanks Everyone for help!
Critical section:
InitializeCriticalSection(&CriticalSection);
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) WriteToFile, NULL, 0, &ThreadID);
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
}
// Wait for all threads to terminate
for( i=0; i < THREADCOUNT; i++ )
{
WaitResult = WaitForSingleObject(aThread[i], INFINITE);
switch(WaitResult)
{
case WAIT_OBJECT_0:
printf("Thread %d has terminated...\n", i);
break;
// Time out
case WAIT_TIMEOUT:
printf("The waiting is timed out...\n");
break;
// Return value is invalid.
default:
printf("Waiting failed, error %d...\n", GetLastError());
ExitProcess(0);
}
}
// Close thread handles
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
// Release resources used by the critical section object.
DeleteCriticalSection(&CriticalSection);
Function called by a thread:
DWORD WINAPI WriteToFile( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwCount=1, dwWaitResult;
HANDLE hFile;
char DataBuffer[30];
DWORD dwBytesToWrite;
DWORD dwBytesWritten;
// Request ownership of the critical section.
EnterCriticalSection(&CriticalSection);
// Write to the file
printf("Thread %d writing to file...\n", GetCurrentThreadId());
hFile = CreateFile(TEXT("file.txt"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
SetFilePointer(hFile, 0, NULL, FILE_END);
while( dwCount <= 3 )
{
sprintf(DataBuffer, "Theard %d writing %d\n", GetCurrentThreadId(), dwCount);
dwBytesToWrite = (DWORD)strlen(DataBuffer);
WriteFile( hFile, DataBuffer, dwBytesToWrite, &dwBytesWritten, NULL);
printf("Theard %d wrote %d successfully.\n", GetCurrentThreadId(), dwCount);
}
}
dwCount++;
}
CloseHandle(hFile);
// Release ownership of the critical section.
LeaveCriticalSection(&CriticalSection);
return TRUE;
}
The problem is that you are passing TRUE to the fWaitAll flag for WaitForMultipleObjects. On Windows CE, this is not supported: the documentation on MSDN says that this flag must be FALSE. WaitForMultipleObjects is thus not waiting, but returning an error instead, but you are not checking the return code. The main thread thus goes straight through, closes the handles and deletes the critical section whilst the "worker" threads are still running. Once DeleteCriticalSection has been called, the critical section "can no longer be used for synchronization", so the EnterCriticalSection calls probably no longer block, and you end up with the scenario you have here.
On Windows 7, everything works because the WaitForMultipleObjects call does indeed wait for all the threads to finish.
Rather than using WaitForMultipleObjects, just use WaitForSingleObject in a loop to wait for each thread in turn.