Thread View: borland.public.cppbuilder.nativeapi
6 messages
6 total messages
Started by Danny
Sun, 16 Sep 2007 07:08
Differences between Semaphore and Mutex
Author: Danny
Date: Sun, 16 Sep 2007 07:08
Date: Sun, 16 Sep 2007 07:08
44 lines
1779 bytes
1779 bytes
Hi all, I must to synchronize two threads, but I've a problem with the mutex procedures. In the following code I've used the semaphores...: 1# thread HANDLE h=::CreateSemaphore(NULL,0,1,"PddSem"); ....... execute the #2 thread ....... ::WaitForSingleObject(h,INFINITE); ::CloseHandle(h); 2# thread ....... HANDLE h=::OpenSemaphore(SEMAPHORE_ALL_ACCESS,false,"PddSem"); ::ReleaseSemaphore(h,1,NULL); ::CloseHandle(h); ...ans work all fine, but if I use the mutexs...: 1# thread HANDLE h=::CreateMutex(NULL,true,"PddMut"); ....... execute the #2 thread ....... ::WaitForSingleObject(h,INFINITE); ::CloseHandle(h); 2# thread ....... HANDLE h=::OpenMutex(MUTEX_ALL_ACCESS,false,"PddMut"); ::ReleaseMutex(h); ::CloseHandle(h); ...the #1 thread don't wait the #2 thread. Currently I've solved my problem with the semaphores, but someone could explain me the differences. Thanks
Re: Differences between Semaphore and Mutex
Author: Bob Gonder
Date: Sun, 16 Sep 2007 13:15
Date: Sun, 16 Sep 2007 13:15
12 lines
1404 bytes
1404 bytes
Mutexes are "owned" Your thread 1 owns the mutext (created with True) Thread 2 Opens and attempts to Release the Mutex. It fails to do so because it does not own the mutex. Thread 2 doesn't even attempt to own the mutex. Meanwhile, thread 1 issues a WaitFor on the mutex it already owns, which succeeds instantly. Semaphores don't have "owners", just "state"
Re: Differences between Semaphore and Mutex
Author: Dennis Jones
Date: Sun, 16 Sep 2007 17:10
Date: Sun, 16 Sep 2007 17:10
68 lines
4556 bytes
4556 bytes
"Bob Gonder" <notbg@notmindspring.invalid> wrote in message news:kcaqe3d7a9ahqkl01dpp52rerc4g54o9et@4ax.com... > > Mutexes are "owned" > Your thread 1 owns the mutext (created with True) > > Thread 2 Opens and attempts to Release the Mutex. > It fails to do so because it does not own the mutex. > Thread 2 doesn't even attempt to own the mutex. > > Meanwhile, thread 1 issues a WaitFor on the mutex it > already owns, which succeeds instantly. > > Semaphores don't have "owners", just "state" To expand upon what Bob said, Semaphores are typically used to synchronize/serialize access to a limited number of resources as they have a count value associated with them. They can be used for thread synchronization if the maximum count is set to 1, but they are a pretty expensive way (in terms of CPU cycles) to do simple thread synchronization. Mutexes are typically used to synchronize access between processes, as their handle can be shared with other processes in the system. However, Bob is incorrect in his analysis of the mutex problem you are having. First, it is true that mutexes are owned, but they are not owned by threads -- they are owned by the process. Second, your mutex is created in the signalled state, so the first thread that tries to wait on it (thread #1 in this case), will immediately succeed. In your sample code, thread #2 never tries to wait on the mutex, and immediately releases the mutex (which has no effect because it is already in a signalled state, but not because it doesn't own it). The order in which the threads execute, in this case, makes no difference because the mutex was created in the signalled state (unless there is code missing from your example, which is highly likely, from what I can tell). If you change your code to create the mutex in the non-signalled state, you could see different behavior. In this case, the order in which the calls occur will affect the outcome. If thread #2 releases the mutex (setting it to the signalled state) before thread #1 tries to wait, then thread #1 will immediately succeed when it calls the wait function. However, if thread #1 attempts to wait on the mutex before thread #2 releases the mutex, then it will wait until the mutex is released, which in your code is almost immediate. So, both mutexes and semaphores can be used to synchronize threads. But a more efficient way to synchronize threads is to use critical sections. Critical sections are the simplest and most efficient synchronization mechanism -- they cannot be shared across processes like mutexes, and don't have a count associated with them like sempahores. Based on your code (which I presume is only an example), I am not sure what it is you are trying to accomplish with synchronization, so it's impossible to suggest which synchronization mechanism is best for your application. For fast, simple synchronization, use a crticial section. To synchronize threads across process boundaries, use mutexes. To synchronize access to limited resources, use a semaphore. There are also events (manual- and auto-reset), which have a slightly different purpose, but I doubt they would be useful in your current situation. I highly recommend the book, "Advanced Windows" (practially any edition) by Jeffrey Richter. He discusses, in sufficient detail, how all of the different synchronization mechanisms work, and gives very good examples of their use. - Dennis
Re: Differences between Semaphore and Mutex
Author: Danny
Date: Sun, 16 Sep 2007 18:14
Date: Sun, 16 Sep 2007 18:14
26 lines
1744 bytes
1744 bytes
Hi Dennis,
thank you for your detailed explanation.
Fundamentally I have a TThread class, and when I close my application, the
terminate event isn't come execute, and so I need to synchronization.
Currently I've:
void __fastcall TFMain::FormClose(TObject *Sender, TCloseAction &Action)
{
HANDLE h=CreateSemaphore(NULL,0,1,"PddSem");
Control->Terminate();
while(WaitForSingleObject(h,500)!=WAIT_OBJECT_0)
Application->ProcessMessages();
::CloseHandle(h);
}
void __fastcall TThreadControl::TerminateEvent(TObject *Sender)
{
.... my code .....
HANDLE h=OpenSemaphore(SEMAPHORE_ALL_ACCESS,false,"PddSem");
ReleaseSemaphore(h,1,NULL);
CloseHandle(h);
}
However I'll try with TCriticalSection class.
Thank you
Re: Differences between Semaphore and Mutex
Author: Remy Lebeau (TeamB)
Date: Sun, 16 Sep 2007 19:11
Date: Sun, 16 Sep 2007 19:11
34 lines
2012 bytes
2012 bytes
"Danny" <danny2912@libero.it> wrote in message
news:46ed7265@newsgroups.borland.com...
> Fundamentally I have a TThread class, and when I close
> my application, the terminate event isn't come execute
Yes it will, if you use it properly.
> void __fastcall TFMain::FormClose(TObject *Sender, TCloseAction &Action)
> {
> HANDLE h=CreateSemaphore(NULL,0,1,"PddSem");
> Control->Terminate();
> while(WaitForSingleObject(h,500)!=WAIT_OBJECT_0)
> Application->ProcessMessages();
> ::CloseHandle(h);
> }
You do not need a semaphore or mutex in that situation. The
TThread::WaitFor() method works just fine in a form's OnClose event, ie:
void __fastcall TFMain::FormClose(TObject *Sender, TCloseAction &Action)
{
Control->Terminate();
Control->WaitFor();
}
void __fastcall TThreadControl::TerminateEvent(TObject *Sender)
{
.... my code .....
}
Gambit
Re: Differences between Semaphore and Mutex
Author: Dennis Jones
Date: Sun, 16 Sep 2007 19:27
Date: Sun, 16 Sep 2007 19:27
106 lines
4695 bytes
4695 bytes
"Danny" <danny2912@libero.it> wrote in message
news:46ed7265@newsgroups.borland.com...
> Hi Dennis,
> thank you for your detailed explanation.
> Fundamentally I have a TThread class, and when I close my application, the
> terminate event isn't come execute, and so I need to synchronization.
> Currently I've:
>
> void __fastcall TFMain::FormClose(TObject *Sender, TCloseAction &Action)
> {
> HANDLE h=CreateSemaphore(NULL,0,1,"PddSem");
> Control->Terminate();
> while(WaitForSingleObject(h,500)!=WAIT_OBJECT_0)
> Application->ProcessMessages();
> ::CloseHandle(h);
> }
>
> void __fastcall TThreadControl::TerminateEvent(TObject *Sender)
> {
> .... my code .....
> HANDLE h=OpenSemaphore(SEMAPHORE_ALL_ACCESS,false,"PddSem");
> ReleaseSemaphore(h,1,NULL);
> CloseHandle(h);
> }
>
> However I'll try with TCriticalSection class.
It looks like you want to wait for the thread to complete before exiting the
application. However, you don't really need another synchronization object
to do that. You should be able to wait on the TThread's handle directly.
For example:
while(WaitForSingleObject(Control->Handle,500)!=WAIT_OBJECT_0)
Application->ProcessMessages();
I'm guessing you are using ProcessMessages so that the form continues to
update while the thread is shutting down. This works okay, but it's not
very efficient. By the time FormClose is called, the form is about to be
closed, and by waiting for a thread to terminate inside FormClose -- if you
want the form to update during the shutdown process -- you are forced to
find a way to update the form while the thread shuts down (because FormClose
executes within the context of the main thread, thereby preventing updates
from happening). A better solution would be to shutdown the thread before
closing the form, thereby allowing the main thread to continue updating the
form while the thread shuts down, without any special handling.
For example, when you know it is time to close the form, you could post a
message to the form that, when handled, does something like this (UNTESTED):
class TFMain : public TForm
{
MESSAGE void __fastcall WM_CloseApp(TMessage &Message);
#define WM_CLOSEAPP WM_APP+1
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_CLOSEAPP, TMessage, WM_CloseApp);
END_MESSAGE_MAP(TForm);
};
MESSAGE void __fastcall TFMain::WM_CloseApp(TMessage &Message)
{
delete FThread; // requires the destructor to terminate and wait
Close();
}
__fastcall TThreadControl::~TThreadControl()
{
Terminate();
WaitFor();
}
Note: If you don't want to write the thread's destructor that way, or if the
thread is destroyed automatically by way of a smart pointer or the
FreeOnTerminate flag, you might prefer to do something like this instead:
MESSAGE void __fastcall TFMain::WM_CloseApp(TMessage &Message)
{
FThread->Terminate();
FThread->WaitFor();
Close();
}
// Now, when you want to close the application, you post a special message
to the form so the WM_CloseApp method gets called:
PostMessage( this->Handle, WM_CLOSEAPP, 0, 0 );
Don't post the message from FormClose though, or your form will disappear
while the thread shuts down. Instead, when you could do it in
FormCloseQuery:
void __fastcall TFMain::FormCloseQuery(TObject *Sender, bool &CanClose)
{
if ( IDOK == Application->MessageBox( "Okay to close the application?",
"Confirm", MB_OK | MB_TOPMOST | MB_ICONQUESTION ) )
{
PostMessage( this->Handle, WM_CLOSEAPP, 0, 0 );
}
}
Hope this helps.
- Dennis
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads