How to deal with deadLock thread problem?

hello,

In MFC, thre are UIThread and workThread. if UIthread sent close command to workThread, then workThread sent "Redraw" command to UIThread as response. As far as I know,Window take message queue way, so UIThread dosen't deal with the "Redraw" command,but waiting. The same time workThread is run-loop. So two thread is deadlock.
If this case happen in apple,how to deal with it?
Thank you very much!

Mac OS X (10.3.9)

Posted on Aug 23, 2006 2:07 AM

Reply
6 replies

Aug 23, 2006 7:30 AM in response to hello_81

The MacOS X solution is the same as the MFC solution: don't mix user interfaces and threads. As much as I hate to admit it, the MFC user-interface thread architecture, if properly implmented, is a very good way to handle user interfaces in a multithreaded environment.

The thing is, in a graphical user interface program, you should only have a single thread that makes GUI function calls to the OS. There can be any number of threads making requests to do GUI operations, but a main "Controller" class should serialize all those requests and handle them one at a time. If you try it any other way, you are playing with fire.

The Message Queue architecture of MFC is designed to handle this architecture very efficiently. You just create a container of messages, protect access to that container with some mutex-guarded accessors, and your GUI thread is just a worker thread that processes those requests and acts on them.

Of course, you might be thinking that that is the way the OS works anyway, why not just post those messages? The reason is the side effects you mentioned. The OS primitives like WM_CLOSE and WM_REDRAW need to stay single-threaded in a GUI worker thread. You define a high-level set of commands that you send through the controller, who processes them as if it were single-threaded application.

If you are doing some fancy graphics stuff, and I think you are, you need to keep the human end-user in mind. If you have very rapid updates, you want to turn off screen drawing. Just keep track of areas of the screen that have changes. Then, in a timer loop, update only the changed areas. The background updating can be done very, very fast, and maybe in multiple threads. The display updating, which is very slow and resource intensive (relatively speaking) is then done only when a change occurs, and then only on a fixed interval. Depending on how frequent your updates are an how resource intensive you want your program to be, you can update the display every second to 30 times a second.

GUI programming is all about "event driven" programming, which, in turn, is closely related to "real time" programming. Do do either one well, you need to make sure you have an asynchronous architecture. It can be hard to do. But when done well, your program will really stand out compared to other architectures.

Aug 24, 2006 1:25 AM in response to etresoft

hello, etresoft

I am sorry for giving so much trouble! Thank you very much for giving me much help.I know much about it.
In window, there is MsgWaitForMultipleObjectsEx.Its function is as follow:
The MsgWaitForMultipleObjectsEx function returns when one of the following occurs:
Either any one or all of the specified objects are in the signaled state. The array of objects can include input event objects, which you specify using the dwWakeMask parameter.
An I/O completion routine or asynchronous procedure call (APC) is queued to the thread.
The time-out interval elapses.

But I can not find the same function in cocoa.would you help me please?

Aug 24, 2006 6:43 AM in response to hello_81

I am sorry for giving so much trouble! Thank you
very much for giving me much help.I know much about
it.


Don't worry! It is no trouble at all. The Apple Discussion forums are virtually my only entertainment during the day. It is a long story...

In window, there is
MsgWaitForMultipleObjectsEx.Its function is as
follow:
The MsgWaitForMultipleObjectsEx function returns
when one of the following occurs:
Either any one or all of the specified objects are
in the signaled state. The array of objects can
include input event objects, which you specify using
the dwWakeMask parameter.
An I/O completion routine or asynchronous procedure
call (APC) is queued to the thread.
The time-out interval elapses.
But I can not find the same function in cocoa.would
you help me please?


The multithreading primitives in the Win32 API are very powerful and nice to work with. They are more powerful than what is available in MacOS X. I would expect, but don't know for sure, that there are low-level, kernel functions in MacOS X that are as powerful as in the Win32 API. These are probably found somewhere in the Mach API or IOKit. This is typical of Unix-type operating systems. They will give you a basic POSIX API that is good for 95% of what you need. The other 5% is available only as a cryptic, low-level library that is different for each machine. Win32 is nice because these low-level primitives are very easy to use and much more accessible than in any other system.

But, that isn't your question. You want to know how to implement MsgWaitForMultipleObjectsEx in MacOS X. The function that comes to mind first is the POSIX select() function. I think whoever wrote MsgWaitForMultipleObjectsEx had select() in mind when they wrote it. At a high level, select() works very similarly to MsgWaitForMultipleObjectsEx - except that you wait on file descriptors instead of Events. Unfortunately, Events are much more powerful than file descriptors. If you are waiting for activity on a number of open sockets or files, you can just use select(). That is what it is for. I can honestly say that I prefer using MsgWaitForMultipleObjectsEx instead of select(). It is a cleaner way to do asynchronous I/O. I'm still trying to learn how to do that the way I want on MacOS X.

select() will not work for thread synchronization and communication. For that, you will have to use pthread conditions. They are kind of clunky and non-intuitive. You have to get a lock, then wait for a condition to happen, then release the lock. They key part is that, while your code is inside the pthread condition wait function, it unlocks the underlying mutex for you. I don't like the way that works. When I get time, I'm going to look for better asynchronous I/O and threading functions in MacOS X. I'm not happy with select() and pthreads. I definitely prefer MacOS X for just about everything. But for programming low-level asychronous I/O and multithreading, I miss Win32.

And if anyone out there is reading this, and really knows low-level MacOS X programming, and is disgusted by all the misinformation I've just published, please, please correct me. I would like to learn a better way to do it myself. I haven't had the time to look so far.

Aug 25, 2006 2:22 AM in response to etresoft

hello,etresoft

Thank you very much for answering my question carefully.

You said that I can used select() which is in pthread. I want to know how to implement MsgWaitForMultipleObjectsEx in cocoa used by cocoa thread. I am sorry for ambiguous illustrating question.

By the way, would you help me that UIthread post message to workThread asynchronously in cocoa?

Reagards,
Lily

Aug 25, 2006 6:11 PM in response to hello_81

Sorry for the misunderstanding. select() has nothing to do with pthread. select() does behave very similarly to MsgWaitForMultipleObjectsEx, but only for file descriptors. It really doesn't have anything to do with threads.

There is more out there. I just haven't had time to do adequate research. For example, I found out about libevent. Just last night. It looks like a very good replacement for select(). Still, it appears to only operate on file descriptors.

There are some examples on how to do multithreading "the Cocoa way". I haven't had time to understand them. Cocoa messaging isn't very straightforward.

So, I can't give you a very good answer right now. I do not know of any thread-specific function that is going to give you the same behavior as MsgWaitForMultipleObjectsEx. There may be something, but you'll have to look for it. In the meantime, you can still use a very basic pthread condition variable. The condition variable (and its corresponding mutex lock) can control access to a structure that contains some event identifiers. When an event occurs, you can lock that structure, add your event, then signal the condition. When the condition wait returns, you will already have the lock, you can just inspect the structure, and act on any events you find. Such an algorithm will definitely be less efficient than a primitive function like MsgWaitForMultipleObjectsEx, but it will still work. You can get your app working and look for a better signalling solution in the meantime.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

How to deal with deadLock thread problem?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.