🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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
#1315
Author: Danny
Date: Sun, 16 Sep 2007 07:08
44 lines
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
#1316
Author: Bob Gonder
Date: Sun, 16 Sep 2007 13:15
12 lines
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
#1317
Author: Dennis Jones
Date: Sun, 16 Sep 2007 17:10
68 lines
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
#1318
Author: Danny
Date: Sun, 16 Sep 2007 18:14
26 lines
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
#1319
Author: Remy Lebeau (TeamB)
Date: Sun, 16 Sep 2007 19:11
34 lines
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
#1320
Author: Dennis Jones
Date: Sun, 16 Sep 2007 19:27
106 lines
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