EDIT 1:
FILE *fp;
pthread_mutex_t demoMutex;
unsigned short globalThreadIndex = 0;
struct serverInfo
{
unsigned int serverId;
pthread_t threadId;
std :: vector <pthread_t> queue;
};
std :: vector <serverInfo> serverInfoVector;
void * printHello (void* threadId)
{
pthread_t *my_tid = (pthread_t *)&threadId;
printf ("\nIn `printHello ()`: thread id %ld\n", pthread_self ());
***pthread_mutex_lock (&demoMutex);***
unsigned int i = 0;
char found = false;
if (serverInfoVector.size () > 0)
{
// The following code should be executed when and only when the vector isn't empty.
***pthread_cond_wait (&demoConditionVar, &demoMutex);***
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (*my_tid == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
if (found == true)
{
pthread_t writeToFile = pthread_self ();
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d %d", iterate, 4);
fprintf (fp, " %lu %lu", writeToFile, sizeof (pthread_t));
if (!serverInfoVector [i].queue.empty ())
{
fprintf (fp, " %c %u", 'A', 1);
fprintf (fp, " %lu %lu", serverInfoVector [i].queue.front (), sizeof (pthread_t));
serverInfoVector [i].queue.pop_back ();
}
fprintf (fp, "\n %lu %u", writeToFile, 1);
}
}
***pthread_mutex_unlock (&demoMutex);***
}
***pthread_exit (NULL);***
}
void checkServerExists (unsigned int serverNumber, std :: string message)
{
unsigned int i = 0;
char found = false;
if (serverInfoVector.size () > 0)
{
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (serverNumber == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
}
if (found == false)
{
pthread_t newThread [2];
int returnValue;
if ((returnValue = pthread_create (&newThread [globalThreadIndex], NULL, printHello, (void*) &newThread [globalThreadIndex])) != 0)
{
printf ("\nerror: pthread_create failed with error number %d", returnValue);
}
printf ("\nIn checkServerExists ()`: thread id %ld\n", newThread [globalThreadIndex]);
serverInfo obj;
obj.serverId = serverNumber;
obj.threadId = newThread [globalThreadIndex];
obj.queue.push_back (newThread [globalThreadIndex]);
serverInfoVector.push_back (obj);
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
***pthread_mutex_lock (&demoMutex)***;
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
if (serverInfoVector.size () > 0)
***pthread_cond_signal (&demoConditionVar);***
***pthread_mutex_unlock(&demoMutex);***
pthread_join (newThread [globalThreadIndex], NULL);
}
else
{
}
}
int main ()
{
fp = fopen ("xyz", "w");
***pthread_mutex_init (&demoMutex, NULL);
pthread_cond_t demoConditionVar = PTHREAD_COND_INITIALIZER;***
checkServerExists (1, "anisha");
globalThreadIndex++;
checkServerExists (2, "anisha");
return 0;
}
This code is improved, the problem is still there (the program hangs, second thread doesn’t get shown up).
checkServerExists function (in the current case) causes a new thread to be created, and stored in the array newThread.
checkServerExists function launches a new thread,
When the thread gets created it will immediately call its function printHello and get blocked on the condition variable.
checkServerExists function then inputs the value in the global structure’s queue, sets the signal for the thread to waken up.
Now, what’s the point that I am missing?
EDIT 2:
FILE *fp;
pthread_mutex_t demoMutex;
unsigned short globalThreadIndex = 0;
struct serverInfo
{
unsigned int serverId;
pthread_t threadId;
std :: vector <pthread_t> queue;
};
std :: vector <serverInfo> serverInfoVector;
void * printHello (void* threadId)
{
pthread_t *my_tid = (pthread_t *)&threadId;
printf ("\nIn `printHello ()`: thread id %ld\n", pthread_self ());
***pthread_mutex_lock (&demoMutex);***
unsigned int i = 0;
char found = false;
if (serverInfoVector.size () > 0)
{
// The following code should be executed when and only when the vector isn't empty.
***pthread_cond_wait (&demoConditionVar, &demoMutex);***
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (*my_tid == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
if (found == true)
{
pthread_t writeToFile = pthread_self ();
unsigned short iterate;
for (iterate = 0; iterate < 10000; iterate++)
{
fprintf (fp, " %d %d", iterate, 4);
fprintf (fp, " %lu %lu", writeToFile, sizeof (pthread_t));
if (!serverInfoVector [i].queue.empty ())
{
fprintf (fp, " %c %u", 'A', 1);
fprintf (fp, " %lu %lu", serverInfoVector [i].queue.front (), sizeof (pthread_t));
serverInfoVector [i].queue.pop_back ();
}
fprintf (fp, "\n %lu %u", writeToFile, 1);
}
}
***pthread_mutex_unlock (&demoMutex);***
}
***pthread_exit (NULL);***
}
void checkServerExists (unsigned int serverNumber, std :: string message)
{
unsigned int i = 0;
char found = false;
***pthread_mutex_lock (&demoMutex);***
if (serverInfoVector.size () > 0)
{
while ((i <= serverInfoVector.size ()) && (found == false))
{
if (serverNumber == serverInfoVector [i].threadId)
{
found = true;
break;
}
else
i++;
}
}
if (found == false)
{
pthread_t newThread [2];
int returnValue;
if ((returnValue = pthread_create (&newThread [globalThreadIndex], NULL, printHello, (void*) &newThread [globalThreadIndex])) != 0)
{
printf ("\nerror: pthread_create failed with error number %d", returnValue);
}
printf ("\nIn checkServerExists ()`: thread id %ld\n", newThread [globalThreadIndex]);
serverInfo obj;
obj.serverId = serverNumber;
obj.threadId = newThread [globalThreadIndex];
obj.queue.push_back (newThread [globalThreadIndex]);
serverInfoVector.push_back (obj);
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
// Now, since something has been pushed in the vector, it makes sense to wake up the sleeping thread.
if (serverInfoVector.size () > 0)
***pthread_cond_signal (&demoConditionVar);***
pthread_join (newThread [globalThreadIndex], NULL);
}
else
{
}
***pthread_mutex_unlock(&demoMutex);***
}
int main ()
{
fp = fopen ("xyz", "w");
***pthread_mutex_init (&demoMutex, NULL);
pthread_cond_t demoConditionVar = PTHREAD_COND_INITIALIZER;***
checkServerExists (1, "anisha");
globalThreadIndex++;
checkServerExists (2, "anisha");
return 0;
}
In this edit, I have placed the lock on the top of checkServerExists function (this function deals with the global structure serverInfoVector)
Still hanging. :doh:
This code is broken.
Firstly, you are modifying variables inside
checkServerExistswithout locking the mutex. This is undefined behaviour.If you fix that, then you are also not signalling your condition variable outside the
printHellofunction. Consequently, once the thread has blocked in thepthread_cond_waitcall, it will only wake due to spurious wakes, and when anotherprintHellothread signals it. You should callpthread_cond_signalat the point where you set theconditionflag, rather than inprintHello.A condition variable is just a notification mechanism. You need to associate a predicate with it, which is the condition being waited for (in your case,
condition!=0). You must ensure that the variables accessed when setting and testing the condition are protected by a mutex, and that this mutex is the one passed topthread_cond_waitin order to avoid potential race conditions. When you set the variables to indicate that the sleeping thread should wake, then you callpthread_cond_signal.I’ve modified your code slightly to make it work. In particular, I’ve put the loop round the
pthread_cond_waitcall, and unlocked the mutex before callingpthread_joinso that theprintHellothread can acquire the mutex and proceed. You should never hold a mutex lock across a thread join. This code could still be improved greatly — amongst other things, it is not exception safe.