Board index » delphi » Threads Synchronizing Problem

Threads Synchronizing Problem

Hi,

I write some code as following:

procedure ThreadDone(sender:TObject);
begin
  ...
end;

procedure CreateThread;
begin
...
ThreadsRunning := 2;
with TMyThread.Create(.....) do
  OnTerminate := ThreadDone;
with TMyThread.Create(-----) do
  OnTerminate := ThreadDone;
end;

I wonder how i can know that both threads are done in the
procedure CreateThread. Of course i can know that in procedure
ThreadDone.

Any helps are appreciated.

Mike,

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading

 

Re:Threads Synchronizing Problem


Hi,

I write some code as following:

procedure ThreadDone(sender:TObject);
begin
  ...
end;

procedure createthread;
begin
...
ThreadsRunning := 2;
with TMyThread.Create(.....) do
  OnTerminate := ThreadDone;
with TMyThread.Create(-----) do
  OnTerminate := ThreadDone;
end;

I wonder how i can know that both threads are done in the
procedure createthread.

Any helps are appreciated.

Mike,

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading

Re:Threads Synchronizing Problem


o...@graduate.org heeft geschreven in bericht
<6clnad$27...@nnrp2.dejanews.com>...
|Hi,

|I write some code as following:
|
|procedure ThreadDone(sender:TObject);
|begin
|  ...
|end;
|
|procedure createthread;
|begin
|...
|ThreadsRunning := 2;
|with TMyThread.Create(.....) do
|  OnTerminate := ThreadDone;
|with TMyThread.Create(-----) do
|  OnTerminate := ThreadDone;
|end;
|
|I wonder how i can know that both threads are done in the
|procedure createthread.

It depends on what you want to do. Do you want to restrict the
number of threads? Each call of CreateThread will unconditionally
create 2 new threads in your code example.

TMyThread.OnTerminate will call the ThreadDone procedure when a thread
terminates. There you could do:

procedure ThreadDone(sender:TObject);
begin
   Dec(ThreadsRunning);
   if ThreadsRunning =0 then
      <do something; All threads are done now>
end;

You might do :

procedure createthread;
begin
if ThreadsRunning < MaxThreadsAllowed then begin
  .....
  .....

  with TMyThread.Create(.....) do
     OnTerminate := ThreadDone;
  inc(ThreadsRunning);
end
  else <is up to you >
end;

Re:Threads Synchronizing Problem


In article <6cmbio$lv...@xenon.inbe.net>,
  "Dirk Claessens" <Dirk.Claess...@village.uunet.be> wrote:

Quote

> o...@graduate.org heeft geschreven in bericht
> <6clnad$27...@nnrp2.dejanews.com>...
> |Hi,

> |I write some code as following:
> |
> |procedure ThreadDone(sender:TObject);
> |begin
> |  ...
> |end;
> |
> |procedure createthread;
> |begin
> |...
> |ThreadsRunning := 2;
> |with TMyThread.Create(.....) do
> |  OnTerminate := ThreadDone;
> |with TMyThread.Create(-----) do
> |  OnTerminate := ThreadDone;
> |end;
> |
> |I wonder how i can know that both threads are done in the
> |procedure createthread.

> It depends on what you want to do. Do you want to restrict the
> number of threads? Each call of CreateThread will unconditionally
> create 2 new threads in your code example.

> TMyThread.OnTerminate will call the ThreadDone procedure when a thread
> terminates. There you could do:

> procedure ThreadDone(sender:TObject);
> begin
>    Dec(ThreadsRunning);
>    if ThreadsRunning =0 then
>       <do something; All threads are done now>
> end;

> You might do :

> procedure createthread;
> begin
> if ThreadsRunning < MaxThreadsAllowed then begin
>   .....
>   .....

>   with TMyThread.Create(.....) do
>      OnTerminate := ThreadDone;
>   inc(ThreadsRunning);
> end
>   else <is up to you >
> end;

Maybe I didn't expree what i want clearly.
I want "createthread" can wait for all child threads exiting and then
exit itself.
I tried using CriticalSection and Mutex to do that, but both method
seem not to work. It can be:

procedure createthread;
...
  EnterCriticalSection(sect1);
  then create threads i want.
  EnterCriticalSection(sect1);
  do what i need.
...

procedure ThreadDone;
  ...
  if ThreadsRunning=0 then
     LeaveCriticalSection(sect1);
  ...

It doesn't work because the owner of sect1 is the main thread and it
can enter again without blocking itself.

Can you give me any suggestions? Thanks a lot.

Mike

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading

Re:Threads Synchronizing Problem


o...@graduate.org heeft geschreven in bericht
<6co0rf$8s...@nnrp2.dejanews.com>...
|In article <6cmbio$lv...@xenon.inbe.net>,
|  "Dirk Claessens" <Dirk.Claess...@village.uunet.be> wrote:
|>
|>
|> o...@graduate.org heeft geschreven in bericht
|> <6clnad$27...@nnrp2.dejanews.com>...

[large snip]

|> |I wonder how i can know that both threads are done in the
|> |procedure createthread.
|>
|> It depends on what you want to do. Do you want to restrict the
|> number of threads? Each call of CreateThread will unconditionally
|> create 2 new threads in your code example.
|>
|> TMyThread.OnTerminate will call the ThreadDone procedure when a
thread
|> terminates. There you could do:
|>
|> procedure ThreadDone(sender:TObject);
|> begin
|>    Dec(ThreadsRunning);
|>    if ThreadsRunning =0 then
|>       <do something; All threads are done now>
|> end;
|>
|> You might do :
|>
|> procedure createthread;
|> begin
|> if ThreadsRunning < MaxThreadsAllowed then begin
|>   .....
|>   .....
|>
|>   with TMyThread.Create(.....) do
|>      OnTerminate := ThreadDone;
|>   inc(ThreadsRunning);
|> end
|>   else <is up to you >
|> end;
|>
|>
|
|Maybe I didn't expree what i want clearly.
|I want "createthread" can wait for all child threads exiting and then
|exit itself.

Assuming you know beforehand how many child threads you want to start,
you could create a "mainthread", and in its execute method do the
following:

procedure TMainThread.Execute;
begin
   Child1 := TChildThread.Create;
   Child2 := TChildThread.Create;
   ChildThreadsRunning := 2;
   repeat
   until (ChildThreadsRunning=0) or Terminated;
end;

Each child should dec() ChildThreadsRunning when it terminates.
The ChildThreadsRunning variable should be accessible to both threads,
i.e. be declared in the same unit.

Hope this puts you on track...

Regards,
Dirk Claessens
______________________________________________
Home   : <dirk.claess...@village.uunet.be>
Office : <dirk.claessens...@belgium.agfa.com>
A man's life is what his thoughts make of it.
 (Marcus Aurelius)
______________________________________________

Re:Threads Synchronizing Problem


Quote
In article <6cq3f9$oo...@xenon.inbe.net> "Dirk Claessens" <Dirk.Claess...@village.uunet.be> writes:
>|Maybe I didn't expree what i want clearly.
>|I want "createthread" can wait for all child threads exiting and then
>|exit itself.
>Assuming you know beforehand how many child threads you want to start,
>you could create a "mainthread", and in its execute method do the
>following:
>procedure TMainThread.Execute;
>begin
>   Child1 := TChildThread.Create;
>   Child2 := TChildThread.Create;
>   ChildThreadsRunning := 2;
>   repeat
>   until (ChildThreadsRunning=0) or Terminated;
>end;
>Each child should dec() ChildThreadsRunning when it terminates.
>The ChildThreadsRunning variable should be accessible to both threads,
>i.e. be declared in the same unit.
>Hope this puts you on track...

This might work just fine, Dirk, or it might have serious problems depending
on thread execution behaviors.

(1)  If "Dec" is not an atomic operation, then there is a miniscule
timing-hole -- the classic textbook case -- if the two threads attempt to do
it at the same instant.

(2)  The main-thread is busy-waiting on the other threads, which is burning up
a full time-slice they could profitably use.

(3)  A better strategy here would be to use the WaitForMultipleObjects or
WaitForMultipleObjectsEx function to wait on a list of process-handles using
the WaitAll parameter.  This will suspend the parent thread until all of the
specified processes have terminated, without wasting CPU time.  A semaphore
can be used to pause all of the newly-created threads until the main thread is
ready to suspend.

Re:Threads Synchronizing Problem


In article <6cq3f9$oo...@xenon.inbe.net>,
  "Dirk Claessens" <Dirk.Claess...@village.uunet.be> wrote:

Quote

> o...@graduate.org heeft geschreven in bericht
> <6co0rf$8s...@nnrp2.dejanews.com>...
> |In article <6cmbio$lv...@xenon.inbe.net>,
> |  "Dirk Claessens" <Dirk.Claess...@village.uunet.be> wrote:
> |>
> |>
> |> o...@graduate.org heeft geschreven in bericht
> |> <6clnad$27...@nnrp2.dejanews.com>...

> [large snip]

> |> |I wonder how i can know that both threads are done in the
> |> |procedure createthread.
> |>
> |> It depends on what you want to do. Do you want to restrict the
> |> number of threads? Each call of CreateThread will unconditionally
> |> create 2 new threads in your code example.
> |>
> |> TMyThread.OnTerminate will call the ThreadDone procedure when a
> thread
> |> terminates. There you could do:
> |>
> |> procedure ThreadDone(sender:TObject);
> |> begin
> |>    Dec(ThreadsRunning);
> |>    if ThreadsRunning =0 then
> |>       <do something; All threads are done now>
> |> end;
> |>
> |> You might do :
> |>
> |> procedure createthread;
> |> begin
> |> if ThreadsRunning < MaxThreadsAllowed then begin
> |>   .....
> |>   .....
> |>
> |>   with TMyThread.Create(.....) do
> |>      OnTerminate := ThreadDone;
> |>   inc(ThreadsRunning);
> |> end
> |>   else <is up to you >
> |> end;
> |>
> |>
> |
> |Maybe I didn't expree what i want clearly.
> |I want "createthread" can wait for all child threads exiting and then
> |exit itself.

> Assuming you know beforehand how many child threads you want to start,
> you could create a "mainthread", and in its execute method do the
> following:

> procedure TMainThread.Execute;
> begin
>    Child1 := TChildThread.Create;
>    Child2 := TChildThread.Create;
>    ChildThreadsRunning := 2;
>    repeat
>    until (ChildThreadsRunning=0) or Terminated;
> end;

> Each child should dec() ChildThreadsRunning when it terminates.
> The ChildThreadsRunning variable should be accessible to both threads,
> i.e. be declared in the same unit.

> Hope this puts you on track...

I have tried doing the same as you said. It will work if there are no
SYNCHRONIZE() calls in child thread, or else it cause dead lock.
BUT I have to synchronize some operation in child thread.

And I tried using CriticalSection, Mutex and Semophore, all these have
the same dead lock problem.

Any additional suggestion? Thanks.

Mike

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading

Re:Threads Synchronizing Problem


Quote
In article <6cqlo0$5b...@nnrp2.dejanews.com> o...@graduate.org writes:
>I have tried doing the same as you said. It will work if there are no
>SYNCHRONIZE() calls in child thread, or else it cause dead lock.
>BUT I have to synchronize some operation in child thread.
>And I tried using CriticalSection, Mutex and Semophore, all these have
>the same dead lock problem.

I think your deadlock problem is separate from the issue you are discussing
here.  It sounds like one of the threads is not releasing the synchronization
resource, or the absence of normal message-processing by the main thread is
causing a deadlock.  Anyway, this is the fundamental problem you have now.

Don't overlook the possibility of using a user-defined message, which is
posted to the main-thread (which remains alive and processing messages) by
each thread when it is about to terminate itself.

Re:Threads Synchronizing Problem


Sundial Services heeft geschreven in bericht ...
|In article <6cq3f9$oo...@xenon.inbe.net> "Dirk Claessens"

Quote
<Dirk.Claess...@village.uunet.be> writes:

|
.|>Hope this puts you on track...
|
|
|This might work just fine, Dirk, or it might have serious problems
depending
|on thread execution behaviors.
|
|(1)  If "Dec" is not an atomic operation, then there is a miniscule
|timing-hole -- the classic textbook case -- if the two threads
attempt to do
|it at the same instant.
|

I considered Dec() operations to be atomic, being compiled directly
into one
80x86 dec() instruction... If that's not the case, then I must review
some of
my code here & there. Any comments ??

|(2)  The main-thread is busy-waiting on the other threads, which is
burning up
|a full time-slice they could profitably use.
|

agree...

|(3)  A better strategy here would be to use the
WaitForMultipleObjects or
|WaitForMultipleObjectsEx function to wait on a list of
process-handles using
|the WaitAll parameter.  This will suspend the parent thread until all
of the
|specified processes have terminated, without wasting CPU time.  A
semaphore
|can be used to pause all of the newly-created threads until the main
thread is
|ready to suspend.
|

Agree again. But I just wanted to keep things simple. :o) It wasn't
clear to me
what the general purpose of the question was.

Bye,

Dirk.

Re:Threads Synchronizing Problem


On Tue, 24 Feb 1998 19:58:58 +0100, "Dirk Claessens"

Quote
<Dirk.Claess...@village.uunet.be> wrote:
>I considered Dec() operations to be atomic, being compiled directly
>into one
>80x86 dec() instruction... If that's not the case, then I must review
>some of
>my code here & there. Any comments ??

The DEC instruction is not atomic. A page fault can occur when fetching the
operand, for example.
--
Ray Lischner (http://www.tempest-sw.com/)
Author of "Hidden Paths of Delphi 3: Experts, Wizards, and the Open Tools API"

Re:Threads Synchronizing Problem


Quote
n...@junk.mail (Ray Lischner) wrote:
>On Tue, 24 Feb 1998 19:58:58 +0100, "Dirk Claessens"
><Dirk.Claess...@village.uunet.be> wrote:

>>I considered Dec() operations to be atomic, being compiled directly
>>into one
>>80x86 dec() instruction... If that's not the case, then I must review
>>some of
>>my code here & there. Any comments ??

>The DEC instruction is not atomic. A page fault can occur when fetching the
>operand, for example.

Surely the DEC instruction must be monatomic (at least on a single
processor system, and probably on a multiple processor system). If a
page fault occurs during the instruction or the operand fetch, the
instruction will not have been executed. A page fault cannot occur
during the memory read-modify-write sequence necessary to perform the
DEC operation. I would also suspect that a well-designed multi-processor
system would not allow other processors to change a memory location
during a read-modify-write operation.

Am I being dumb and missing something?

(This method worked very well when I was implementing semaphores on a
PDP-11 - with core memory - in assembler.)

--
Chris Isbell
Southampton, England
ch...@isbell.demon.co.uk
+44 1703 465367
http://www.isbell.demon.co.uk

Re:Threads Synchronizing Problem


Quote
ch...@isbell.demon.co.uk (Chris Isbell) wrote:
>>>I considered Dec() operations to be atomic, [...]
>>The DEC instruction is not atomic. A page fault can occur when fetching the
>>operand, for example.
>Surely the DEC instruction must be monatomic [...]

Must?

Use InterlockedDecrement() and InterlockedIncrement() instead. That's
what they are there for.

Quote
>(This method worked very well when I was implementing semaphores on a
>PDP-11 - with core memory - in assembler.)

AFAIR, PDP was (is) a single processor system.

Thank you for flying Air Melander.

+--------------------from usenet----------------------+
|  Anders Bo Melander    | Phone: (+45) 31 87 91 26   |
|  Finsensvej 79, 2. tv. | mailto:and...@melander.dk  |
|  DK-2000 Frederiksberg | http://www.melander.dk     |
|  Denmark               | flameto:bi...@microsoft.com|
+------------------------+----------------------------+

Other Threads