Mutlithreading madness

I am writing a rendering program that needs to deal with a huge number of polygons, transforming them each frame and so on.

I intend to use several threads to do this:
Thread 1: This thread opens an openGL rendering window on creation which renders each model as it is processed for a frame.
Thread 2: This thread processes each model and the flags it to be drawn.
Thread 3: This postprocesses each frame and then saves it to disk.
There is also a central data-structure (a list of models) that all the thread will need to access.

The main program thread (which also handles the MFC user-interface stuff) needs to be able to communticate with each of the other threads, specifically it needs to set rendering options for the openGL window that is hidden inside thread 1. Thread 1 and 2 need easy access the the central list of models, and possibly to each other.

I guess I should use a UI thread for thread 1 and worker threads for threads 2 and 3. I have been trying to initialise thread 1 using AfxBeginThread, followed by WaitForSingleObject. WaitForSingleObject timesout, and then sending information to thread 1 doen't seem to work right. I haven't started on threads 2 or 3.

Can anyone give me any tips on how to create the underlying structure of this thread system, and how to check that threads are created right and how to comunticate between threads. I have been looking through the Visual C help, but it is all a bit dense.
Sam_BarhamAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

abdijCommented:
Hi,
 For the Thread 1 you should have to GUI window (or wherever) to display whatever you are rendering.
It should be a separate thread.

In the main thread which also calls thread1, use AfxBeginThread to create the threads 2,3.
Have Semaphore or Mutex to gaurd your Central datastructure from corruption.

Now your thread 1 needs to create all the GUI (or atleast process them) . I just assume you know how to handle MFC messages.

What i cannot understand here is why is the WaitForSinfleObject() used?? What are you waiting for?????

Need reply.

Bye
Abdij
0
VCGuruCommented:
Why do you feel WaitForSingleObject does not work right?.
WaitForSingleObejct takes two parameters one is the handle to the event or mutex and the second one is timeout.

If you are using events  be sure to use the correct kind manual or Auto-reset, If the correct kind is not used, it may hamper the operation of control flow.

You can build access to any thread from any other thread. You can use the LPVOID parameter in CreateThread API to pass any parameter you want to the created thread, You can also have global variables to communicate, if you have these variables, then you'll have to block it using mutexes.
0
Sam_BarhamAuthor Commented:
I am using WaitForSingleObject simply because someone told me to.  I am at the grasping at straws stage where anything that helps will do.  My problem is that if I create the UI thread and then call WaitForSingleObject(thread->m_hThread, 1000) then WaitForSingleObject times out and the thread doesn't seem to activate.  I have tried to do it differently, but have yet to find anything that works.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

VCGuruCommented:
What is thread->m_hThread?. Is it the handle of the thread that is returned when you create the thread?.


Now WaitForSingleObject is used only if you have to block the execution of the thread until something happens. I'll give you an example.

Somewhere in your application create an event like this(before spinning off your threads)

HANDLE hEvent; //Keep this global
hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);

thread 1
{
while(1)
{
WaitForSingleObject(hEvent,INFINITE);
MessageBox(....);

}
return 1;
}

thread 2
{
while(1)
{
.......
SetEvent(hEvent);
}
}

Now assume that thread1 and thread2 are started, thread 1 is going to wait( ie the messagebox will not be displayed) till the wait satisfies. Wait is only satsified when thread 2 says SetEvent(hEvent). The moment this happens thread 1 resumes operation.

Another possibility is that you may want thread 1 to wait for 1000ms In that case. If SetEvent does not happen for 1000ms then the operation will time out and WaitForSingleObject will return WAIT_TIMEOUT which you have to trap.

If your first parameter is the handle to the thread as you have passed in your example, then, the MessageBox(...) will appear only when the thread(the one referring to the handle) quits. This state of the event is called signalled state. I hope this is not what you want. Try and use events as above.

Remember there are two events
a) Auto reset( If the wait is satisfied then the event is automatically reset)
b) Manual.( If the wait is satisfied then you'll have to reset it using ResetEvent()

The type of the event is decided in the second parameter of CreateEvent.
Hope this helps
0
udiaCommented:
You are correct about thread 1 being a UI thread and the other being worker threads.

To check if the threads are created simply check the return value from the creation function.

Communicating with the threads is a bit more difficult, you can use event objects to stop your threads at certain points and then start them again from another thread (the UI thread for instance).

Since the main thread has an MFC window it can process messages. You can use this to send messages from the worker threads to the main thread using PostMessage or SendMessage (such as to notify the UI that data is ready).

I have used this scheme in several projects and it works very nicely.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
andymurdCommented:
In the past I have used CWinThread derived classes to perform lengthy processing tasks, but I found AfxBeginThread() to be inflexible. I prefer to pass initialisation data by over-riding the constructor or CreateThread() member then starting the thread by calling CreateThread().

That way you can pass window handles etc to be used when posting messages.

Also of note, is the MFC user interface threads can fail to receive messages sent via PostThreadMessage if they are currently managing a modal dialog or resizing window. Post your messages to the applications main window instead.
0
abdijCommented:
Hi Sam,

 You are not replying to the queries
???????????????????

Bye
Abdij
0
Sam_BarhamAuthor Commented:
Thanks for your comments.  My mind sort of slid off to other parts of the program for a while.  It looks like I will be using CMutexes and CEvents to control the thread processing.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.