I know I am going to have alot of questions but can someone check to see if I am starting this out correctly...

Programming assignment two will demonstrate your understanding and mastery of multi-threaded application concepts in a Windows environment using Visual C++ .NET 2005. In this programming assignment you will create a multithreaded application that computes the greatest common divisor using Euclid’s algorithm. Your program is to create multiple threads. Thread one must pick two random numbers between 1 and 100, display the value of the random numbers selected (along with a thread identifier), and place them into shared global variables. Thread one then must wait for thread two to act on the values. Once thread two has completed operating on the variables, thread one must repeat, then thread two, and so on, until ten sets of random numbers have been picked, greatest common divisor found, displayed, and placed in the shared global variables. The two random numbers picked by thread one become the two input values for Euclid’s algorithm. Thread two must act in a cooperative manner with thread one. Thread two’s task is to find the greatest common divisor for the two random numbers selected. Once the greatest common divisor is found, it should be displayed (along with a thread identifier). Thread two should then wait for another set of values to be placed in the shared global variables. Thread two should act upon each set of random numbers selected by thread one. Your program must use two threads You may choose managed or unmanaged code for this programming assignment. Your program may use any of the available libraries (such as the ATL or the STL). The random number generator should be seeded in some manner. During program development and testing, using a static number to seed the random number generator will result in the same numbers being picked each time the program is run. For production, seeding with the current time is preferred. Using the current time insures that different numbers will be generated each time the program is run. Your program must use some method of synchronization for the cooperating threads. You may use any synchronization object (semaphore, mutex, ATL object, etc) that is available in Visual C++ .NET. Your program must not use busy-waiting. Your program’s threads must not access the shared global variables in any manner unless they do so in a way that assures that the other thread has been blocked from accessing the variables and that any operation can occur in a mutually exclusive manner. Failure to access the shared global variables in a mutually exclusive manner will be considered a major design flaw. Turn in a printed copy of your program source as well as including the source on floppy disk (no executable files) or email the program source, by pasting it into the email (no attachments), to the instructor. Insure your name is on all materials. Programs will be graded based upon program correctness, good programming techniques, style, and user interface. Ten points of extra credit will be awarded to programs that correctly implement mutual exclusion using a binary semaphore. This is alll I have found so far and do not think it is right..

#include <process.h>
#include <windows.h>
#include <stdio.h>
unsigned Counter;
unsigned __stdcall SecondThreadFunc( void* pArguments ) {
printf( "In second thread...\n" );
while ( Counter < 1000000 )
Counter++;
_endthreadex( 0 );
return 0;
}
void main()
{
HANDLE hThread;
unsigned threadID;
printf( "Creating second thread...\n" );
// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0,
&threadID );
// Wait until second thread has terminated. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 1000000 yet.
WaitForSingleObject( hThread, INFINITE );
printf( "Counter should be 1000000; it is-> %d\n", Counter );
// Destroy the thread object.
CloseHandle( hThread );
}

Recommended Answers

All 14 Replies

It looks fine so far, but you may want to create a semaphore or look into using CriticalSections.

At the moment you're waiting for a thread to exit. You need to wait for a thread to signal. Using a mutex is one way, but I wouldn't go that way. Using CriticalSections or Creating Semaphores is another way which I think would be more applicable to you.

Here's a bunch of Synchronisation Functions that are available in the Windows API

Two important ones are Here and Here

commented: :) +1

>>Wrong thread
Was there a pun intended?

>>This is alll I have found so far and do not think it is right..
This is straight from MSDN, what makes you think otherwise?

During multi-threading you have virtually no control so as which thread finishes first, provided they were all launched in consecutive calls.
Since you're using the WaitFor method, you are pretty much only demonstrating the swift processing of the threads rather than parallel processing using Multiple threads. What exactly is your objective (in brief).

@nbaztec: I posted a reply to another thread in here so I edited it out. Also, seeing as I'd already made a post, I thought I may as well help, so I edited it again with some advice.

@OP: Look into some of the functions I've linked you to and if you still need help, post up your new attempt and I'll see what you're struggling with.

I think the OP should make use of WaitForMultipleObjectsEx() for different parts with bWaitAll set to true. I've used that in past & it works like a charm.

Only for when he is waiting for the application to finish. His original query is to synch up two threads operating separate to the main thread.

Both of the new operation threads, in my opinion, would make a good use of the CriticalSection. Or, for his extra credit, he could use manual reset event.

The CriticalSection will ensure his process will execute the code in the methods one after the other. However, this is effectively a quick method for using mutexes.

For his extra credit he should create a semaphore and use that. Personally, I don't see the point for this exercise but I'm not the one taking the course ^^

Well I was suggesting a way to unleashing say 5 threads to do 5 mutually exclusive tasks of a job & Waiting all of them to finish inside the job thread. All 5 "child" threads will certainly have access to the global heap & wont be blocking one-another, while contributing to the same job, hence emulating parallel processing. Don't know about the extra credits though, it's hard to please lecturer's from where I come from - I score a meager 70% in a stupid old-skool C(non-standard) written exam :-/.

Ideally, your solution is correct, but it doesn't particularly solve the problem given in the simplest way and there's not point adding more complexity if the OP is struggling already ;)

In summary, you're not wrong, but there's an easier way ;)

>>In summary, you're not wrong, but there's an easier way
Sure, there can be 100 different paths leading to the Alps. I'll bow out.

I think I am making some progress but have two questions. First if you run my code it returns 21 counters instead of 20 so if someone could show me what I am doing wrong. Second I know to code two random numbers is something like...

{

srand((unsigned)time(0));

int random_integer;

int lowest=1, highest=100;


for(int counter=0; counter<20; counter++)

{

random_integer = lowest+int(rand()/(RAND_MAX + 1.0));

cout << random_integer << endl;

} 

Here is my current code...

#include <windows.h>
#include <stdio.h>
#include <process.h>

unsigned counter;
HANDLE hMutex;
unsigned __stdcall SecondThreadFunc( void* pArguments ) 
{

    DWORD dwWaitResult;
    while (counter < 20)
{
    // Request ownership of mutex.
    dwWaitResult = WaitForSingleObject
    (hMutex, 5000L);

    switch (dwWaitResult)
{
    // The thread got mutex ownership.
    case WAIT_OBJECT_0:
    __try
{
    if (counter % 2)
    {
        counter++;
        printf( "Thread Two Counter is-> %d\n", counter );
    }
}
__finally
{
    // Release ownership of the mutex object.
    if (! ReleaseMutex(hMutex))
    {
        // Deal with error.
    }
    break;
}
// Cannot get mutex ownership due to time-out.
case WAIT_TIMEOUT:
{
    // Got ownership of the abandoned mutex object.
    return false;
}

case WAIT_ABANDONED:
{
    return false;
}
}
}
_endthreadex( 0 );
return 0;
}
int main()
{
HANDLE hThread;
unsigned threadID;
counter = 0;
hMutex = CreateMutex(
NULL, // no security attributes
FALSE, // initially not owned
(LPCWSTR) "MutexToProtectDatabase"); // name of mutex
if (hMutex == NULL)
{
// Check for error.
}

// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0,
&threadID );
DWORD dwWaitResult;
while (counter < 20)
{
// Request ownership of mutex.
dwWaitResult = WaitForSingleObject(
hMutex, // handle to mutex
5000L); // five-second time-out interval
switch (dwWaitResult)
{
// The thread got mutex ownership.
case WAIT_OBJECT_0:
__try
{
if (!(counter % 2))
{
counter++;
printf( "Primary Thread Counter is-> %d\n", counter );
}
}
__finally
{
// Release ownership of the mutex object.
if (! ReleaseMutex(hMutex))
{
// Deal with error.
}
break;
}
// Cannot get mutex ownership due to time-out.
case WAIT_TIMEOUT:
{
// Got ownership of the abandoned mutex object.
return false;
}
case WAIT_ABANDONED:
{
return false;
}
}
}


WaitForSingleObject( hThread, INFINITE );
printf( "Counter should be 20; it is-> %d\n", counter );
// Destroy the thread object.
CloseHandle( hThread );
return 0;
}

for the second part of the question can someone show me the correct way to enter this

Or you can just use for random:
randInt = lLimit + rand() % (uLimit - lLimit +1);

EDIT:
Can you show the sample output you're getting with counter?

dumb question but would I put this in int main() after counter = 0

>>dumb question but would I put this in int main() after counter = 0
Just about where you need to get the random value. Just make a function int getRandom(int lLimit, int uLimit) & call it wherever necessary.

while(counter < 200)
{
   dwWaitResult = WaitForSingleObject(hMutex, 5000L);
   .  //Check for counter first
   .  //Do stuff
   .  //More stuff
}

In both threads Wait is inside the loop, so when the respective thread is signaled A-OK, it resumes from that position. So, basically, you need to check to end loop(break) at that position.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.