Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Quick Review of TThread...(plus a little TEvent)...

259 views
Skip to first unread message

Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 2, 2006, 3:17:16 PM9/2/06
to
Bear with me, as I am a dinosaur from D4 days, and I've finally upgraded to
2006.
And wasn't it a shock that my old components I wrote, (TTrayIcon, TZLipComp,
TBrowseTreeView)
are pretty much obsolete now, as Borland has included their concepts in the
new vcl/rtl.

Anyway, I had a few quick questions about TThread that I need to clear up
before my Top Down
went bottoms up, if you catch my drift.

1st: TThread
The Constructor is Contained within the Calling Threads execution, not
the new thread's execution. So,
If I were to want to Pass initialization values to the new thread, I could
do it via the constructor, and and not worry
about synchronization, correct?
(Note: I Will most likely be running a multi-thread situation, where One
thread will be sort of a manager of 3 or 4 other threads,
so it is key that I know where the contructor/onterminate is contained for
the child threads. If they are all VCL thread, that's cool,
but if vcl spawns thread 1 and thread 1 spawns thread 2, where does
T2.Create and T2.OnTerminate reside).

2nd: TThreadList
Populating a List (naturally i'd use a TThreadList) would require some
elements of synchronization. The question, is whether
or not the TThreadList requires me to Lock/Unlock to "Add" items to it.
eg: I'm searching for something, and using two threads to populate the
results.
Thread 1
Prcocesses items, and If Result Criteria met, adds to list.
If Item is Secondary Processing Item,
Spawn Thread 2.
Thread 2
Processess items, and If Result Criteria met, adds to list.


In the above situation, using a Global TThreadList, would T1.AddToList and
T2.AddToList need to call ThreadList.Lock/ThreadList.UnLock
around their individual Threadlist.Add() calls, or is the Locking/Unlocking
only necessary when Retrieving the final List?

3rd: TEvent
TEvent seems to be a rather new cool way to communicate between threads.
However, It seems based, somewhat upon timing.
Is it equitable for me to Utilize the TEvent design to track multiple events
not exactly based on time?
eg:

While Okay Do
begin
WaitResult = Event1.WaitFor(1);
if WaitResult = wrSignaled then ProcessEvent(Event1)
else if WaitResult = wrError then ProcessError(Event1);
end;

In this, the process loop of my Thread Manager is just listening for
multiple events, to react WHEN they occur, not IF they occur. Is that Okay
to Do?

4th: Named Events (TEvent)
Now this "appears" to be a way for my Main Thread to create an Event and
Naming it "Job1", then subsequently within a child thread
that is executed, creates a TEvent with the same name "Job1", and thus if
Thread2 were to use it's locally declared, Thread2EventJob.SetEvent, then
the Thread1.EventJob would receive the signal. Is this accurate?

5th: Windows Messaging.
A long time ago (D4 era) I had begun the designs of a ThreadManager
class, that was based upon Windows Messaging as a form of communication,
which would allow the Individual Threads to signal the Manager which could
in turn create VCL Events, based upon the individual Threads' Messages.
However, now I am not sure this is an entirely accurate thought process.
Looking at the PostThreadMessage, and GetMessage Calls, as well as the
MsgWaitForMultipleObjects(Ex) functions, I am wondering exactly how I might
work this scenario, and if my original logic is still sound:

ThreadManager
List of ThreadContainerClasses

ThreadContainerClass
containerHWND = CreateWindowEx, WS_EX_TOOLWINDOW
childHWND //is set upon the creation of the actual child thread
execution
fieldObj = ChildThread //set via VCL event

ChildThread
Create(containerHWND)
threadHandle = BeginThread() //At This point i might create the
thread automatically, and if Create Suspended, manuall suspend it after the
initial
//Execute->PostMessage(MSG_INIT)
call
execute //Thread code
threadHWND = CreateWindowEx, WS_EX_TOOLWINDOW //to create the
Thread's own Callback Message Queue
PostMessage(containerHWND, MSG_INIT, lparam = threadHWND) //to
inform the container class what the HWND of the thread's message queue is.
//Load Internal Thread Processing Object or thread code, etc. This
is the user/programmer specific code that actually does the thread code, i
just find it cleaner
//to contain it in an object myself.

Given this hierarchy, my intent, was that the ThreadManager, existing in the
main VCL thread, would receive a call to instantiate a new thread. It would
then create a
ThreadContinerClass which upon creation woudl signal a VCL event for the
Instantiation of the ChildThread class. This ChildThread class is a class
inherited
from my own ThreadBaseClass which is in all intents and purposes a TThread
class, just containing all my added event based code (Though I make the
call to BeginThread myself, instead of using the dereived TThread version, i
inherited for ease of compatibility).
(Note: The programmer would have to create a derived class, since my
BaseClass is partially abstract, like the TThread class, and when the
ContainerClass event is called, return the instance pointer of this new
thread class for the thread container to execute).

Now all this is supposed to add functionality that provides for the
ChildThread being able to Post a message (via windows messaging)
back to the ContainerClass, which of course, would have VCL events to signal
the manager, and subsequently the programmers main vcl thread, as well as
allow the container class to safely post a message to the individual thread.
This would, hopefully, simplify some of the thread processing in Win32,
allowing the programmer to listen to specific events, be able to
suspend/resume/kill threads based upon an internal thread ID, as well allow
each thread an internal SelfChecking methodology, based upon internal
WM_TIMER messages, part of my SelfCheck interval design to determine if any
child thread has hung in its execution.

My final curiosity is basically, is this accurate? PostThreadMessage
indicates that the threadID must refer to a thread that has its own message
queue, which is created via a call to a GDI function, and i'm curious if
CreateWindowEx suffices. Since the ContainerClass is of the main thread,
can the ChildThread just post a message to the parent HWND without incident,
or do i need to do some other TEvent based communication?
Finally, should such messages to the ChildThread be sent via
PostThreadMessage instead of PostMessage?

Thanks for the review help,
Regards

Jaeden "Sifo Dyas" al'Raec Ruiner
aka Fluffy
htttp://www.wayoftheleaf.net/


Rob Kennedy

unread,
Sep 2, 2006, 4:08:55 PM9/2/06
to
Jaeden "Sifo Dyas" al'Raec Ruiner wrote:
> 1st: TThread
> The Constructor is Contained within the Calling Threads execution, not
> the new thread's execution. So,
> If I were to want to Pass initialization values to the new thread, I could
> do it via the constructor, and and not worry
> about synchronization, correct?

Yes. Many people don't realize that the constructor runs in the context
of the calling thread. In fact, the new thread doesn't start running at
all until after the constructor has finished. Note that this latter
point is a *change* from Delphi 4. In Delphi 4, the new thread started
running as soon as you called "inherited Create(False);" (See
TThread.AfterConstruction to see how it works now.)

> (Note: I Will most likely be running a multi-thread situation, where One
> thread will be sort of a manager of 3 or 4 other threads,
> so it is key that I know where the contructor/onterminate is contained for
> the child threads. If they are all VCL thread, that's cool,
> but if vcl spawns thread 1 and thread 1 spawns thread 2, where does
> T2.Create and T2.OnTerminate reside).

The constructor runs in the calling thread's context. The OnTerminate
handler runs in the main VCL thread's context; it's executing using the
Synchronize method.

> 2nd: TThreadList
> Populating a List (naturally i'd use a TThreadList) would require some
> elements of synchronization. The question, is whether
> or not the TThreadList requires me to Lock/Unlock to "Add" items to it.

It does not. TThreadList.Add calls LockList and UnlockList. If you need
to add multiple items without interruption, then you'll need to lock the
list yourself.

Remember that all versions of Delphi come with the VCL source code now.
For simple questions like that, you can often answer it yourself with a
quick look at the source.

> In the above situation, using a Global TThreadList, would T1.AddToList and
> T2.AddToList need to call ThreadList.Lock/ThreadList.UnLock
> around their individual Threadlist.Add() calls, or is the Locking/Unlocking
> only necessary when Retrieving the final List?

Locking is only necessary if you don't want the contents of the list to
change while you're working with it, and you're OK with blocking any
other threads that want to change the list.

> 3rd: TEvent
> TEvent seems to be a rather new cool way to communicate between threads.
> However, It seems based, somewhat upon timing.

Somewhat. But then, so is all other inter-thread communication.

> Is it equitable for me to Utilize the TEvent design to track multiple events
> not exactly based on time?
> eg:
>
> While Okay Do
> begin
> WaitResult = Event1.WaitFor(1);
> if WaitResult = wrSignaled then ProcessEvent(Event1)
> else if WaitResult = wrError then ProcessError(Event1);
> end;

That's a very bad way to use events (or any other synchronization tool).
It's a spin-wait loop, and it will eat up all your CPU time. It will
only wait for one millisecond before timing out. Upon timing out, it
will simply go back to waiting again. To make that efficient, you need
to wait for longer periods -- infinitely, ideally.

> In this, the process loop of my Thread Manager is just listening for
> multiple events, to react WHEN they occur, not IF they occur. Is that Okay
> to Do?

If the threads that need to trigger the events will know the ID of the
thread that will act on the events, then you might find a simple message
loop to be easier to work with. Use PostThreadMessage to notify the
thread that something has happened. Use GetMessage in a loop to receive
the messages.

If you will have multiple threads available for handling events, and you
only want one thread to handle any given event, then you might be better
off with a producer-consumer queue. Martin James will probably be along
soon with more information on that.

> 4th: Named Events (TEvent)
> Now this "appears" to be a way for my Main Thread to create an Event and
> Naming it "Job1", then subsequently within a child thread
> that is executed, creates a TEvent with the same name "Job1", and thus if
> Thread2 were to use it's locally declared, Thread2EventJob.SetEvent, then
> the Thread1.EventJob would receive the signal. Is this accurate?

Yes. Named events are most useful for inter-process communication, where
passing a handle from one process to another can be complicated. If both
ends already know what the event will be called, simply asking the OS to
fetch a handle to it is much easier. When both threads are in the same
process and being developed by the same person or group, named events
aren't so big a deal.

> 5th: Windows Messaging.
> A long time ago (D4 era) I had begun the designs of a ThreadManager
> class, that was based upon Windows Messaging as a form of communication,
> which would allow the Individual Threads to signal the Manager which could
> in turn create VCL Events, based upon the individual Threads' Messages.
> However, now I am not sure this is an entirely accurate thought process.
> Looking at the PostThreadMessage, and GetMessage Calls, as well as the
> MsgWaitForMultipleObjects(Ex) functions, I am wondering exactly how I might
> work this scenario, and if my original logic is still sound:
>
> ThreadManager
> List of ThreadContainerClasses
>
> ThreadContainerClass
> containerHWND = CreateWindowEx, WS_EX_TOOLWINDOW
> childHWND //is set upon the creation of the actual child thread
> execution
> fieldObj = ChildThread //set via VCL event

Since you have PostThreadMessage, you don't strictly need a window
handle. You can post messages directly to the thread's message queue
instead of addressing them to a dummy window. The only thing to be
careful of is that new threads don't automatically have message queues.
If someone posts a message to a thread that has no message queue, then
that message is lost. A thread can create a message queue by calling
GetMessage or PeekMessage. (I use PeekMessage once to create a message
queue immediately, and then GetMessage in a loop later on, when I'm
actually ready to start handling messages.)

Your thread-manager plan sounds much more complicated than it needs to
be. Nearly anything with "manager" in its name probably deserves some
more thought regarding how it will work, what its responsibilities will
be, and whether it's actually necessary at all.

> My final curiosity is basically, is this accurate? PostThreadMessage
> indicates that the threadID must refer to a thread that has its own message
> queue, which is created via a call to a GDI function,

I think you misread something. GDI has nothing to do with it.

> and i'm curious if
> CreateWindowEx suffices. Since the ContainerClass is of the main thread,
> can the ChildThread just post a message to the parent HWND without incident,
> or do i need to do some other TEvent based communication?
> Finally, should such messages to the ChildThread be sent via
> PostThreadMessage instead of PostMessage?

Well, that simply depends on whether you care to handle the message in
the thread itself, or in one of the thread's windows.

--
Rob

Remy Lebeau (TeamB)

unread,
Sep 2, 2006, 5:36:19 PM9/2/06
to

"Jaeden "Sifo Dyas" al'Raec Ruiner" <Jaeden...@wayoftheleaf.net> wrote in
message news:44f9d8c0$1...@newsgroups.borland.com...

> The Constructor is Contained within the Calling Threads execution,
> not the new thread's execution.

Correct.

> If I were to want to Pass initialization values to the new thread,
> I could do it via the constructor, and and not worry about
> synchronization, correct?

Yes. This is especially true in D6 onwards. Prior to D6, it was possible
for the thread to begin running before the constructor had finished
executing, even before the constructor had begun executing. Borland finally
fixed that in D6.

> I Will most likely be running a multi-thread situation, where One
> thread will be sort of a manager of 3 or 4 other threads, so it is key
> that I know where the contructor/onterminate is contained for the
> child threads.

The OnTerminate event is run in the context of the main thread, not in the
context of the thread that is terminating, or in the thread that created it
(your manager thread). If you need more control over where the OnTerminate
code runs, then you have to override the virtual DoTerminate() method, which
runs in the context of the thread that is terminating.

> if vcl spawns thread 1 and thread 1 spawns thread 2, where does
> T2.Create and T2.OnTerminate reside

T2.Create will run in the context of T1, and T2.OnTerminate will run in the
context of the VCL thread.

> Populating a List (naturally i'd use a TThreadList) would require
> some elements of synchronization.

TThreadList uses a critical section internally.

> The question, is whether or not the TThreadList requires me to
> Lock/Unlock to "Add" items to it.

Yes. However, Add() already does that internally for you. You do not need
to Lock/Unlock the list manually when adding items, unless you want to add
multiple items at one time while maintaining a single lock until all items
have been added.

> In the above situation, using a Global TThreadList, would T1.AddToList
> and T2.AddToList need to call ThreadList.Lock/ThreadList.UnLock

Add() does that internally for you.

> is the Locking/Unlocking only necessary when Retrieving the final List?

You have to lock the list whenever you want to access the items for any
reason. That includes adding items, removing items, retrieving the number
of items available, and iterating through the existing items. TThreadList
handles the locking internally for simple operations, or you can lock the
list manually so you can perform multiple operations withing a single lock.

> TEvent seems to be a rather new cool way to communicate between
threads.

There is nothing "new" about it. TEvent has been around for years (going
back to at least D3), and the underlying Win32 Event object that it wraps
has been around for a lot longer.

> However, It seems based, somewhat upon timing.

So? Most synchronization objects are.

> In this, the process loop of my Thread Manager is just listening for
> multiple events, to react WHEN they occur, not IF they occur.

If you want to keep track of multiple events at a time, then you should be
using the Win32 API WaitForMultipleObjects() function instead. Pass it an
array of event handles, and it will return when any or all of them have
become signaled. That is much more efficient then looping through them one
at a time.

> Now this "appears" to be a way for my Main Thread to create
> an Event and Naming it "Job1", then subsequently within a child
> thread that is executed, creates a TEvent with the same name "Job1"

Naming is meant for sharing objects across threads (and processes), yes.
However, an easier way (within a single process, at least) would be to
simply create the TEvent once and then pass its pointer to the thread
instead. You don't need a second TEvent object.

> if Thread2 were to use it's locally declared, Thread2EventJob.SetEvent,
> then the Thread1.EventJob would receive the signal. Is this accurate?

Yes. The same thing is possible if you use a single TEvent object that is
shared between the threads, where the child thread calls SetEvent() and the
main thread calls WaitFor(). Either way is fine.

> A long time ago (D4 era) I had begun the designs of a ThreadManager
> class, that was based upon Windows Messaging as a form of communication

That is still a viable approach today. My company has software that still
does that today.

> ThreadContainerClass
> containerHWND = CreateWindowEx, WS_EX_TOOLWINDOW
> childHWND //is set upon the creation of the actual child thread
execution
> fieldObj = ChildThread //set via VCL event

Why are you using HWNDs in threads? You don't need to do that. Use
PostThreadMessage() with thread IDs instead. First, it takes up fewer
resources, and second, thread messages work exactly the same with
Get/PeekMessage() as window messages do.

In fact, you don't even need to use messages to communicate the child thread
IDs to the manager or the container class. ThreadID is a property of
TThread, and it available as soon as the TThread object is constructed.
When the manager creates a container, the container can create its child
thread immediately (suspended or not) and thus immediately have access to
the child's ThreadID for communications, even before the child thread has
begun running. Since the container would have a pointer to the child thread
from the very beginning, and does not need to wait for the child thread to
announce itself, the container (and manager) can use the child's ThreadID
whenever it wants to.

> Given this hierarchy, my intent, was that the ThreadManager, existing
> in the main VCL thread, would receive a call to instantiate a new thread.
> It would then create a ThreadContinerClass which upon creation woudl
> signal a VCL event for the Instantiation of the ChildThread class.

Why would you use events for that? You already know that you need a new
thread, so just create it immediately and move on.

> This ChildThread class is a class inherited from my own ThreadBaseClass
> which is in all intents and purposes a TThread class

Why are you not using TThread itself?

> I make the call to BeginThread myself, instead of using the dereived
> TThread version, i inherited for ease of compatibility

What compatibility? In any case, you can still have the container class
call BeginThread() immediately upon its own creation instead of using an
event. BeginThread() will return the new thread's ID immediately, and you
can start the thread initially suspended or not.

> The programmer would have to create a derived class, since my
> BaseClass is partially abstract, like the TThread class, and when the
> ContainerClass event is called, return the instance pointer of this new
> thread class for the thread container to execute).

Rather than using a synchronized event to get the thread instance pointer,
why not instead trigger an unsynchronized event that allows the programmer
to specify the thread class type instead? The manager could then create the
actual thread object instance from that. Even better, give the manager
thread a property or constructor parameter that specifies the class type
(like TCollection's constructor does), then you don't need an event at all.

> Now all this is supposed to add functionality that provides for the
> ChildThread being able to Post a message (via windows messaging)
> back to the ContainerClass, which of course, would have VCL events
> to signal the manager, and subsequently the programmers main vcl
> thread, as well as allow the container class to safely post a message
> to the individual thread.

You don't need messages and events for that. You are essentially delegating
everything back to the main thread, which is going to slow down perfomance
of your entire thread management system, not to mention introduce potential
deadlock oppurtunities along the way.

> PostThreadMessage indicates that the threadID must refer to a thread
> that has its own message queue, which is created via a call to a GDI
> function, and i'm curious if CreateWindowEx suffices.

I would not recommend that approach. Don't create a window inside the
threads at all. To initially create the queue, use PeekMessage() when
Execute() begins running, and then use GetMessage() or PeekMessage()
afterwards to process the queue during the thread's lifetime.

> Since the ContainerClass is of the main thread, can the ChildThread just
post
> a message to the parent HWND without incident

That depends on how the container is obtaining the parent HWND in the first
place, and how the child thread is obtaining that HWND afterwards. As long
as the VCL thread does not destroy-and-recreate the HWND while the child
thread is trying to use it, then you will be fine. However, the VCL does
have a habit of doing exactly that to VCL windows. So I would suggest not
relying on HWNDs at all for your system. You should have the manager obtain
the ID of the thread it belongs to (via a call to GetCurrentThreadID()) and
then pass that along to the child threads. In the case of the manager
running inside the main thread, you can then use the TApplication.OnMessage
event to catch the messages.

The reason I suggest using thread IDs exclusively instead of HWNDs is so
that you can then move the manager into its own thread later on if you wish
without effecting the rest of your design, since the manager is ultimately
the one who decides where the messages are to be posted to.

> do i need to do some other TEvent based communication?

Not for the design you have shown so far, no.

> Finally, should such messages to the ChildThread be sent via
> PostThreadMessage instead of PostMessage?

If you get rid of the HWNDs, then you would have to use PostThreadMessage(),
as that would be the only way to get the messages to a thread without a
window.


Gambit


Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 2, 2006, 6:00:33 PM9/2/06
to

"Rob Kennedy" <m...@privacy.net> wrote in message
news:44f9...@newsgroups.borland.com...

> Jaeden "Sifo Dyas" al'Raec Ruiner wrote:
>> 1st: TThread
>> The Constructor is Contained within the Calling Threads
execution, not
>> the new thread's execution. So,
>> If I were to want to Pass initialization values to the new thread, I
could
>> do it via the constructor, and and not worry
>> about synchronization, correct?
>
> Yes. Many people don't realize that the constructor runs in the
context
> of the calling thread. In fact, the new thread doesn't start running
at
> all until after the constructor has finished. Note that this latter
> point is a *change* from Delphi 4. In Delphi 4, the new thread started
> running as soon as you called "inherited Create(False);" (See
> TThread.AfterConstruction to see how it works now.)

So, whenever you call TThread.Create(False), Once you are done with your own
initializations, you have you have to follow it up with
TThread.AfterConstruction?

> If the threads that need to trigger the events will know the ID of the
> thread that will act on the events, then you might find a simple message
> loop to be easier to work with. Use PostThreadMessage to notify the thread
> that something has happened. Use GetMessage in a loop to receive the
> messages.

This sounds like the thread already has a message queue handle, just in the
Execute Method of TThread,
i would call a function that runs a loop of just for messages, and based
SOLELY upon the messages, my derived TThread class would
do what it was designed to do, because from then on it seems trapped in a
message loop for processing messages.

Am I right on that interpretation?

> If you will have multiple threads available for handling events, and you
> only want one thread to handle any given event, then you might be better
> off with a producer-consumer queue. Martin James will probably be along
> soon with more information on that.
>

>> 5th: Windows Messaging.


>> A long time ago (D4 era) I had begun the designs of a ThreadManager
>> class, that was based upon Windows Messaging as a form of communication,
>> which would allow the Individual Threads to signal the Manager which
>> could in turn create VCL Events, based upon the individual Threads'
>> Messages. However, now I am not sure this is an entirely accurate thought
>> process. Looking at the PostThreadMessage, and GetMessage Calls, as well
>> as the MsgWaitForMultipleObjects(Ex) functions, I am wondering exactly
>> how I might work this scenario, and if my original logic is still sound:
>>
>> ThreadManager
>> List of ThreadContainerClasses
>>
>> ThreadContainerClass
>> containerHWND = CreateWindowEx, WS_EX_TOOLWINDOW
>> childHWND //is set upon the creation of the actual child thread
>> execution
>> fieldObj = ChildThread //set via VCL event
>
> Since you have PostThreadMessage, you don't strictly need a window handle.
> You can post messages directly to the thread's message queue instead of
> addressing them to a dummy window. The only thing to be careful of is that
> new threads don't automatically have message queues.

I'm beginning to see what you mean about the message queues, It just not
exactly my plan, so i will try to clarify below.

> If someone posts a message to a thread that has no message queue, then
> that message is lost. A thread can create a message queue by calling
> GetMessage or PeekMessage. (I use PeekMessage once to create a message
> queue immediately, and then GetMessage in a loop later on, when I'm
> actually ready to start handling messages.)
>
> Your thread-manager plan sounds much more complicated than it needs to be.
> Nearly anything with "manager" in its name probably deserves some more
> thought regarding how it will work, what its responsibilities will be, and
> whether it's actually necessary at all.

I've got the idea, and the plan, i'm just trying to organize the how and
what.

>
>> My final curiosity is basically, is this accurate? PostThreadMessage
>> indicates that the threadID must refer to a thread that has its own
>> message queue, which is created via a call to a GDI function,
>
> I think you misread something. GDI has nothing to do with it.

That was the help mentioning GDI. It meant what you said about the
PeekMessage/GetMessage loop to initialize the message queue
for the Thread.

>> and i'm curious if CreateWindowEx suffices. Since the ContainerClass is
>> of the main thread, can the ChildThread just post a message to the parent
>> HWND without incident, or do i need to do some other TEvent based
>> communication?
>> Finally, should such messages to the ChildThread be sent via
>> PostThreadMessage instead of PostMessage?
>
> Well, that simply depends on whether you care to handle the message in the
> thread itself, or in one of the thread's windows.

I think that's my confusion about the 'handling of messages' with Threads,
and the thread Intercommuniation.

The Thread Handling messages description appears to look like this:

TMyThread(TThread).Execute; //overridden;
begin
//Do initialization code, some pre-set functions that need to be called,
or objects initialized.

peekmessage(msg);
//do other code here
TMyThread.StartMessageLoop();
end;

TMyThread.StartMessageLoop;
begin
while GetMessage(Msg) != 0 do
begin
//handle messages here
end;
end;

So that means to me, that the TThread object in this instance is solely for
interpreting messages, and within that message handler, it spawns other
threads/operations. It can only be a message handler, and would thus
respond to a message and do some code, which could be contained within its
own TThread that actually does whatever it does, thus the message handler
thread would be free to await another PostThreadMessage, which could of
course come from the TThread it just spawned.

That's not exactly my idea, since I want each thread to have a CallBack
functionality. When you create a window, it stores a callback function that
is called independently of any other methods. Thus with the TThread class
the execute method can move along its happy way occaisionally checking
within its main loop, or process, for message flags, meanwhile the callback
is listing to posted/sent messages which may do some side functionality
within the thread that affects the main loop, or other such data requests,
etc. This makes the thread itself possible of being it's own message
handler, while not interrupting it's direct code.
The idea is to have a repository class that calls events in the main
application. Standard events that exist in every object, like:
TButton.OnClick:=MyForm.Button1OnClick();

The repository could then be called upon to send commands, or the
forementioned receiving of events, that are all controlled by a message
based communication between itself and all the child threads of the
application.
Like, instead of the main form of an application needing to call some loop,
or constantly check to determine if a thread is finished, it can just have
an event procedure that will inform it when the moment arises. Instead of
checking TThread.WaitFor() or TEvent.WaitFor() (for specific task oriented
events within a thread), i can just have an event triggered by a callback
message.

Or, say a Thread is doing certain things that shouldn't be directly
interrupted by a TThread.Suspend call. Thus following this idea:

Manager:

Mgr.SuspendThread(index);
begin
Mgr.MesageToThread(CanSuspend, Index); //This just posts the Message to
the Created HWND of the child thread, not waiting for a result
end;

... meanwhile ...
Mgr.CallBack(Msg) //this is the hwnd window call back of the manager
begin
if Msg = ReadyToSuspend then
ListThreads[lParam].Suspend;
end

ChildThread

Thread.CallBack(Msg)
begin
if msg = CanSuspend then
SuspensionRequest:=True;
end;

Thread.Execute;
begin
Initialize;
StartLoop
do sensitive process
if SuspensionRequest then
WaitResume();
repeatloop
end;

Thread.WaitResum()
begin
SendMessage(Mgr.HWND, ReadyToSuspend);
//Do an Idle process that waits for the "Msg_Resume", such as a
MsgWaitForMultipleObjects() or something that would put the childthread
//into an Idle state, waiting for any events or messages to awake it.
end;

Mgr.Resume(Index)
begin
listThreads[Index].Resume;
Mgr.MessageToThread(ResumeThread, Index);
//This of course as before sends a message to the
waiting thread's CallBack window. This time telling the thread
//it can resume. Since the thread's internal idle is
inplace, it hears the postmessage via the MsgWaitForMultipleObjects() idle
//alertable state and would respond to the posted
message, coming out of sleep,
end;

Maybe I'm not seeing this in the light of how threads were designed, which
is why i'm going over a few things here to help hone my concept into what it
should be.

Thanks for the help,

Rob Kennedy

unread,
Sep 2, 2006, 7:37:13 PM9/2/06
to
Jaeden "Sifo Dyas" al'Raec Ruiner wrote:
> "Rob Kennedy" <m...@privacy.net> wrote in message
> news:44f9...@newsgroups.borland.com...
>> Many people don't realize that the constructor runs in the context
>> of the calling thread. In fact, the new thread doesn't start running at
>> all until after the constructor has finished. Note that this latter
>> point is a *change* from Delphi 4. In Delphi 4, the new thread started
>> running as soon as you called "inherited Create(False);" (See
>> TThread.AfterConstruction to see how it works now.)
>
> So, whenever you call TThread.Create(False), Once you are done with your own
> initializations, you have you have to follow it up with
> TThread.AfterConstruction?

No. AfterConstruction is a method of TObject that gets called when the
constructor and all inherited constructors finish. It's built in. You
don't need to do anything. I was referring you to the source code to see
*how* TThread activates itself.

>> If the threads that need to trigger the events will know the ID of the
>> thread that will act on the events, then you might find a simple message
>> loop to be easier to work with. Use PostThreadMessage to notify the thread
>> that something has happened. Use GetMessage in a loop to receive the
>> messages.
>
> This sounds like the thread already has a message queue handle, just in the
> Execute Method of TThread,
> i would call a function that runs a loop of just for messages, and based
> SOLELY upon the messages, my derived TThread class would
> do what it was designed to do, because from then on it seems trapped in a
> message loop for processing messages.
>
> Am I right on that interpretation?

A thread does not automatically have a message queue. (There's no such
thing as a "message queue handle.") The OS will create a message queue
for a thread when the thread calls GetMessage or PeekMessage.

You don't have to use *only* messages. You can use events, mutex
objects, and other kernel objects, too. The MsgWaitForMultipleObjects
function lets you suspend execution of a thread until one of those
objects becomes signalled or until a message arrives. You can tailor
your thread's actions based on the result of that function. If you're
not using any other kernel objects, then a simple call to GetMessage is
probably enough.

If you're going to use messages, then you need a message loop. You won't
be "trapped" in that loop, though. You can exit it however you want. If
your thread receives a wm_Quit message, that would be a good time to
exit the loop. (GetMessage will return 0 in that case.)

> The Thread Handling messages description appears to look like this:
>
> TMyThread(TThread).Execute; //overridden;
> begin
> //Do initialization code, some pre-set functions that need to be called,
> or objects initialized.
>
> peekmessage(msg);
> //do other code here
> TMyThread.StartMessageLoop();
> end;
>
> TMyThread.StartMessageLoop;
> begin
> while GetMessage(Msg) != 0 do
> begin
> //handle messages here
> end;
> end;
>
> So that means to me, that the TThread object in this instance is solely for
> interpreting messages, and within that message handler, it spawns other
> threads/operations. It can only be a message handler, and would thus
> respond to a message and do some code, which could be contained within its
> own TThread that actually does whatever it does, thus the message handler
> thread would be free to await another PostThreadMessage, which could of
> course come from the TThread it just spawned.

It doesn't have to be like that. The loop could be structured like this
instead:

repeat
x := MsgWaitForMultipleObjects(Handles, cHandles, ...);
if x < cHandles then begin
// Handles[x] became signalled.
end else if x = cHandles then begin
// At least one message has arrived in the queue since the
// last time the queue was checked. Empty the queue.
while PeekMessage(msg, ..., pm_Remove) do begin
// Handle the message.
if Msg.Message = wm_Quit then
exit;
end;
end else begin
// Read in MSDN for other possible return values
end;
until False;

> That's not exactly my idea, since I want each thread to have a CallBack
> functionality. When you create a window, it stores a callback function that
> is called independently of any other methods.

Only in the Win32 model. In the Delphi model, you override a method of
TForm. Win32 isn't object-oriented, so the only way to extend the
functionality of anything is to provide callback functions. Delphi
doesn't require that since it has virtual methods that you can override.
They're two ways of accomplishing the same thing.

Furthermore, a window's callback function isn't called independently.
It's called by the GetMessage function and the DispatchMessage function.
It's not called asynchronously.

> Thus with the TThread class
> the execute method can move along its happy way occaisionally checking
> within its main loop, or process, for message flags, meanwhile the callback
> is listing to posted/sent messages which may do some side functionality
> within the thread that affects the main loop, or other such data requests,
> etc.

If you need the thread to be doing two things simultaneously, then you
need two threads. One will just handle messages, and one will just
listen for posted messages. But expressed that way, the threads are
really both doing the same things and should just be in one thread. So
what's the callback function really for?

> This makes the thread itself possible of being it's own message
> handler, while not interrupting it's direct code.
> The idea is to have a repository class that calls events in the main
> application. Standard events that exist in every object, like:
> TButton.OnClick:=MyForm.Button1OnClick();

If the only thing the thread will do is listen for messages and then
trigger operations in the main thread, then you don't need another
thread at all. The main thread already listens for messages.

> The repository could then be called upon to send commands, or the
> forementioned receiving of events, that are all controlled by a message
> based communication between itself and all the child threads of the
> application.
> Like, instead of the main form of an application needing to call some loop,
> or constantly check to determine if a thread is finished, it can just have
> an event procedure that will inform it when the moment arises. Instead of
> checking TThread.WaitFor() or TEvent.WaitFor() (for specific task oriented
> events within a thread), i can just have an event triggered by a callback
> message.
>
> Or, say a Thread is doing certain things that shouldn't be directly
> interrupted by a TThread.Suspend call. Thus following this idea:

Good. There's no reason to call Suspend.

> Maybe I'm not seeing this in the light of how threads were designed, which
> is why i'm going over a few things here to help hone my concept into what it
> should be.

I think you're re-inventing the operating system's inter-thread
communications. Functions like GetMessage and MsgWaitForMultipleObjects
already put the calling thread into an efficient wait state. If the
message queue is empty, GetMessage will wait forever until a message
arrives. There's no need to explicitly suspend the thread. As I see it,
you don't need this "manager" class at all. The OS already does all the
management you need.

--
Rob

Remy Lebeau (TeamB)

unread,
Sep 2, 2006, 8:31:07 PM9/2/06
to

"Jaeden "Sifo Dyas" al'Raec Ruiner" <Jaeden...@wayoftheleaf.net> wrote in
message news:44f9...@newsgroups.borland.com...

> So, whenever you call TThread.Create(False), Once you are done


> with your own initializations, you have you have to follow it up with
> TThread.AfterConstruction?

No. AfterConstruction() is called automatically by the VCL runtime after
all constructors have exited. In versions of the VCL prior to D6,
TThread.Create(False) would begin running the thread object immediately,
before the derived constructors had a chance to run. This lead to problems
with the thread trying to access data in its Execute() method before they
had been initialized. The workaround was to always call Create(True) and
then manually Resume() the thread after the initializations were finished.
In D6, Borland finally fixed this by always creating a thread object
suspended, and then have TThread override the AfterConstruction() method to
call Resume() if the user had called Create(False). This way, all derived
constructors have a change to initialize their data before the thread begins
running.

> This sounds like the thread already has a message queue handle,
> just in the Execute Method of TThread,

Threads do not have a message queue by default. The first call to a GDI
function will create the queue. In a main thread, a message queue is
implemented by the VCL for you, and there are hooks available for processing
messages that are received by that queue. In worker threads, however, you
have to implement your own queuing code yourself. The thread would have to
use Peek/GetMessage() to create the queue, and then call Peek/GetMessage()
again in a loop to actually process messages. For each message receives, do
the operations needed for just that message, and then let the loop return to
call Peek/GetMessage() again for the next message.

> The Thread Handling messages description appears to look like this:

Something like that, yes. Since you are doing additional initializations
before creating the queue, you should have the thread create an Event object
that it can signal after the queue is created. This way, when another
thread wants to post a message to the queue, it can check if the event has
been signaled (and wait for the event if it has not been signaled yet).
This way, you won't lose messages that would have been posted before the
queue is created.

> So that means to me, that the TThread object in this instance is solely
> for interpreting messages, and within that message handler, it spawns
> other threads/operations.

Yes, the individual messages would drive which operations the receiving
thread performs.

> It can only be a message handler, and would thus respond to a message
> and do some code, which could be contained within its own TThread that
> actually does whatever it does, thus the message handler thread would be
> free to await another PostThreadMessage, which could of course come
> from the TThread it just spawned.

If you need to perform multiple operations in parallel, then yes, you would
have to spawn new threads for each message received. That can get very
complex, and use up a lot of resources. On the other hand, if you don't
really care when the operations are performed, only that they get executed
in the order that they are posted, then you can perform the operations
directly in the thread that is receiving the messages, without having to use
additional threads.

> That's not exactly my idea, since I want each thread to have a CallBack
> functionality. When you create a window, it stores a callback function
> that is called independently of any other methods.

All that happens when you post a message to a window is that the OS looks up
the thread that owns the window and then puts the message into that thread's
message queue. The MSG structure that is returned by Peek/GetMessage()
specifies the window that the message was posted to, so that when the thread
calls DispatchMessage() after receiving the message, it can pass the message
to the current callback procedure for the window. It essentially works like
the following (translated to Delphi for clearity, and irrelevant details
omitted):

// OS translated functions ...

function PostMessage(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam:
LPARAM): BOOL; stdcall;
var
Msg: TMsg;
ThreadID: DWORD;
begin
Msg.hwnd := hWnd;
Msg.message := uMsg;
Msg.wParam := wParam;
Msg.lParam := lParam;
Msg.time := GetTickCount;
GetCursorPos(Msg.pt);
ThreadID := GetWindowThreadProcessId(hWnd, nil);
// put the message structure into the queue for ThreadID...
Result := 1;
end;

function DispatchMessage(const lpmsg: PMsg): Longint; stdcall;
begin
with lpmsg^ do
Result := CallWindowProc( TFarProc(GetWindowLong(hwnd,
GWL_WNDPROC)), hwnd, message, wParam, lParam);
end;

function CallWindowProc(lpPrevWndFunc: TFarProc; hWnd: HWND; uMsg: UINT;
wParam: WPARAM; lParam; LPARAM): Longint; stdcall;
begin
Result := lpPrevWndFunc(hWnd, uMsg, wParam, lParam);
end;


// your thread functions ...

function MyWindowProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam;
LPARAM): Longint; stdcall;
begin
if uMsg = MY_MESSAGE then
begin
// do something
end;
Result := 1;
end;

procedure TMyThread.Execute;
var
Msg: TMsg;
begin
while not Terminated do
begin
GetMessage(Msg);
if Msg.hwnd <> 0 then
begin
// window message, call the window procedure for it ...
TranslateMessage(Msg);
DispatchMessage(Msg);
end else
begin
// handle a thread message as needed ...
end;
end;
end;

// somewhere else...
PostMessage(MyThreadWnd, MY_MESSAGE, 0, 0);


As you can see, you are still working with thread messages even if you have
a window for the thread. PostMessage() simply stores additional information
about the window so that the target window procedure can be determined
later. You can accomplish the same thing using thread messages without
using any windows at all. Simply post your message to the thread's message
queue directly, and then call your callback function immediate when the
message is received.

// OS translated function ...

function PostThreadMessage(idThreadID: DWORD; uMsg: UINT; wParam:
WPARAM; lParam: LPARAM): BOOL; stdcall;
var
Msg: TMsg;
begin
Msg.hwnd := 0;
Msg.message := uMsg;
Msg.wParam := wParam;
Msg.lParam := lParam;
Msg.time := GetTickCount;
GetCursorPos(Msg.pt);
// put the message structure into the queue for idThreadID...
Result := 1;
end;

// your thread functions ...

procedure TMyThread.Execute;
var
Msg: TMsg;
begin
while not Terminated do
begin
GetMessage(Msg);
if Msg.message = MY_MESSAGE then
begin
// do something...
end;
end;
end;

// somewhere else...
PostThreadMessage(MyThread.ThreadID, MY_MESSAGE, 0, 0);


So how much simplier that is to work with?

> Thus with the TThread class the execute method can move along its happy
> way occaisionally checking within its main loop, or process, for message
> flags, meanwhile the callback is listing to posted/sent messages which may
> do some side functionality within the thread that affects the main loop,
or
> other such data requests, etc.

As I showed above, a message posted/sent to a window is going to block the
message queue of the receiving thread until the window procedure exits. The
thread cannot "move along its happy way" while the callback is doing its
work.

> This makes the thread itself possible of being it's own message handler,
while
> not interrupting it's direct code. The idea is to have a repository class
that calls
> events in the main application.

Such events must be executed in the context of the main thread in order to
access the GUI safely. That means that the worker thread has to trigger the
event via the TThread.Synchronize() method, which will block the message
queue of the worker thread until the main thread responds to the message.
The only way to avoid that is to post messages to the main thread, but then
the worker thread can't wait for the main thread to respond to the messages,
unless you put an Event object in each message that the main thread then
signals when it is finished - which is exactly what Synchronize() does
internally.

> Like, instead of the main form of an application needing to call some
> loop, or constantly check to determine if a thread is finished, it can
> just have an event procedure that will inform it when the moment arises.

You only need messages for that if you don't want to block the thread while
the event is being processed, and if the thread doesn't care about the
result of the message handling. Otherwise, you don't need messages at all.
Simply have the TThread call Sychronize() to trigger an event handler. That
is what the TThread.OnTerminate event does, for example.


Gambit


Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 2, 2006, 9:35:13 PM9/2/06
to

"Rob Kennedy" <m...@privacy.net> wrote in message
news:44fa...@newsgroups.borland.com...

> Jaeden "Sifo Dyas" al'Raec Ruiner wrote:
>> "Rob Kennedy" <m...@privacy.net> wrote in message
>> news:44f9...@newsgroups.borland.com...

> A thread does not automatically have a message queue. (There's no such

> thing as a "message queue handle.") The OS will create a message queue for
> a thread when the thread calls GetMessage or PeekMessage.
>
> You don't have to use *only* messages. You can use events, mutex objects,
> and other kernel objects, too. The MsgWaitForMultipleObjects function lets
> you suspend execution of a thread until one of those objects becomes
> signalled or until a message arrives. You can tailor your thread's actions
> based on the result of that function. If you're not using any other kernel
> objects, then a simple call to GetMessage is probably enough.
>
> If you're going to use messages, then you need a message loop. You won't
> be "trapped" in that loop, though. You can exit it however you want. If
> your thread receives a wm_Quit message, that would be a good time to exit
> the loop. (GetMessage will return 0 in that case.)

> It doesn't have to be like that. The loop could be structured like this
> instead:
>
> repeat
> x := MsgWaitForMultipleObjects(Handles, cHandles, ...);
> if x < cHandles then begin
> // Handles[x] became signalled.
> end else if x = cHandles then begin
> // At least one message has arrived in the queue since the
> // last time the queue was checked. Empty the queue.
> while PeekMessage(msg, ..., pm_Remove) do begin
> // Handle the message.
> if Msg.Message = wm_Quit then
> exit;
> end;
> end else begin
> // Read in MSDN for other possible return values
> end;
> until False;

But At the Line MsgWaitForMultipleObjects, does it not wait until a
message/event/mutex etc, is present, meaning anything that isn't message
related is paused until the wait is over. So i'm either waiting, or working
not both. I want to check for a possible event/message but not wait around
until one is present, just every iteration do a check and process as
necessary.

> If the only thing the thread will do is listen for messages and then
> trigger operations in the main thread, then you don't need another thread
> at all. The main thread already listens for messages.

Actually, no. The main thread will be doing its own thing, as will the
threads it spawns. I just don't want the main threads execution to be
hindered by the functionality of the child thread. Basically, Thread1 (Vcl
thread, or T1) is manipulating some data. T2 is spawned to manipulate other
data. T1 may need to signal T2 about some event, or T2 may need to signal
T1 of some event, but neither should cease their operations.

Such as, with an object:
Obj1
onEvent: TObjEvent

Obj1.Proc1
begin
if Assigned(onEvent) then
onEvent(Self);
end;

This will instantly jump to wherever the onEvent procedure field points to,
executing that code and returning to the rest of Obj1's code.
(Note my idea has nothing to do with a thread termination, but this example
will work perfectly for explanating what I'm designing)
The effect that happens with TThread OnTerminate is what I wish to avoid.
The TThread creates a threadspace that executes the Execute() method, and
everything within that is within the execution code of it's Thread, as
spawned by the BeginThread call. Within that thread space, it calles
DoTerminate, which subsequently calls "Synchronize(CallOnTerminate)".
This says to me, which might be where my logic flaw is residing, that the
Thread, halts, pauses, or otherwise suspends operation, in order to
syncronize with the VCL thread, in order to call the OnTerminate event
method. It does not return, or proceed to the next command until the
CallOnThread returns from its execution. If I am wrong on this
interpretation, then I am begging to see my mistake.

Instead, I want to Send a PostThreadMessage, which does not wait for the
thread to process the message. For example two threads working with a data
buffer,
T1, the VCL thread is reading the buffer up to a specific marker. Say the
first 20000 bytes. If it reaches 20000, it will fall into a wait state
until the next section of the buffer is prepared. But T2, which is the
thread fulling the buffer, can post a message to the VCL thread, which is
processed, informing the Primary thread that the next segment of the buffer
is valid to read. Even if the T1 is still working at position 12000, it
won't hang and wait at 20000, since T2 already informed it the new limit is
40000. Thus the two threads can continue in their processes, while
communicating without waiting.

T1
repeat
if BufferIndex < BufferMax then
begin
CheckIfMessageOrEvent(); //NO WAIT HERE, since i just want to
see if a message/event exists, i'll deal with it if it does, but if it
doesn't i have other thigns
//to do this iteration.
if IsMessage then
DoMessageHandler //This could Inform T1 that buffer is full
and require a PostMessage with a new buffer and buffer size, or
//Could recieve a new BufferMax for T1's
processing loop
else if IsEvent then
DoEventHandler; //Could Signal T1 that T2 has finished
processing it's current data into the buffer, and awaits termination or
//New source to start processing.
BufferIndex:=UtilizeBufferSegment(Buffer, BufferIndex,
BufferMax); //Would process some amount of the buffer, and return with the
//current position in the buffer
end
else MsgWaitForMultipleObjects(); //which basically says that T1 has
surpassed T2 in processing, and since it can't do anything this iteration,
it WAITS here
//for T2 to inform T1 that T1 can begining processing for
more iterations of its loop
until bDone or bExit; //some booleans that would be set by any of the
calls within the Thread

T2
repeat
CheckIfMessageOrEvent();
if IsMessage then
DoMessageHandler
else if IsEvent then
DoEventHandler;
If (SourceDataIndex < SourceDataEnd) and (BufferLoadIndex<
BufferMax) then
SourceDateIndex:=ProcessSourceIntoBuffer(Buffer, BufferIndex,
BufferMax, BufferLoadIndex);
else begin
if SourceDataIndex >= SourceDataEnd then
PostThreadMessage(T1, MSG_NEWSOURCE) //Tell T1 i
need a new source to process
else if BufferLoadIndex = BufferMax then
PostThreadmessage(T1, MSG_NEWBUFFER); //Tell T2 I
need a new buffer to load into
MsgWaitForMultipleObjects(); //Wait until message is
sent with new source or buffer information
end;
until bDone or bExit;

with this design both T1 & T2 have their IDLE phases, but those are only
when necessary, and do not interrupt the message queue. So if No
Message/Event is present an their other requirements are met, they continue
with their tasks, until such time as they are inhibited by whatever factors,
and thus return to idle state. As well, T1 & T2 can respons to messages
that occur, (i'm guessing asynchronously) to their current process. Ie:
T1's bufferindex = buffermax div 2, it can post a message to T2 saying here
is a new buffer. T2, in its message handler, can add the new buffer to its
own internal handling, and should it reach BufferLoadIndex = BufferMax it
can just change over to the new buffer, without Posting a message or waiting
for a response. Similarly, T2 can Load the next stream into the buffer, and
inform T1 of the change before T1 even reaches BufferMax, and thus it will
not hesitate. Etc, Etc, Etc.
This is a crude example, but with this kind of processing, multiple threads
could be doing multiple things, without ever truly needing to wait, or
causing each other to wait for them.
A critical section helps with some of this, but I don't want to lock the
stream/buffer, only part of it, which if scheduled right between the two
threads, the locks would never overlap. Thus if i did: CritSect.Acquire;
ReadBuffer(Buffer); CritSect.Release; in T1, T2 woudl have to wait before
writing to the stream. Instead of locking the stream in this situation, The
two threads communicate as to their position within the stream, and neither
of them hesitate, or wait for each other (in ideal circumstances of course,
that is, it could still happen that they wait on each otehr, but it seems
more fluid in my mind, *shrug*) Basically, like using the
TThreadList.LockList/UnlockList, but T1 would only lock the first 100 items
of the list, so that T2 could continously Add to its own locked section 101
to 150. (I hope my explanation/analogy makes sense here)

> I think you're re-inventing the operating system's inter-thread
> communications. Functions like GetMessage and MsgWaitForMultipleObjects
> already put the calling thread into an efficient wait state. If the
> message queue is empty, GetMessage will wait forever until a message
> arrives.

That's the issue I want to avoid. I want to get a message/event if one is
present, but i don't want to wait for it to be there.

> There's no need to explicitly suspend the thread.

I'm trying to clarify these examples are for description only. I'm trying
to create a more universal idea than that. The suspend (as the Above
OnTerminate example) are only for comparitive analogy.

Examples of real world use:
Mp3 Player
VCL: Listens to user Input, and spawns T1 & T2
T1: Streams from File List unpacking Mp3 files into Buffer
sequentially
T2: Reads current buffer and process the mp3 data to send to
SoundCard

T1 feeds T2. Both Keep VCL appraised of their situation via
messages, and sound ensues.
VCL: Receives user input to Pause music. Sends messages to T1 & T2
Telling them to pause processing. (it wouldn't be a Thread.Suspend, but
some other message that will set the threads into a Wait State)

IP FileTranser
VCL: Listens to user Input and Spaws T1 & T2
SenderIP:
T1: Opens file and Processes through ZLib Compression updating
T2
T2: Uses Compressed buffer and transmits to RecipientIP
RecipientIP:
T1: Recives data from tcp transfer and appraises T2 of the
current process.
T2: uses ZLib to Decompress buffer into file.

T1 Feeds T2 depenedent upon the situation of this Client/server
(peer-to-peer) design and Keeps the VCL aware of the status, for updating
Progress bars, etc. User tells the program to pause execution for whatever
reason, who knows people these days. VCL Signals T1 & T2 to go to IDLE wait
state, T2 sends message to Recipient, whose T1 Processes the message and
messages T2 and VCL that the transfer has been paused, and the user display
is updated.


Recursive FileSearch
VCL listens to user input, Gathers RootDir folder list and Spawns T1
& T2
T1: Starts FindFirst/Next search in First Folder, Gathering all
SubFolders first, and Spawns T3 to search SubFolders while It searchs the
current folder
T2: Starts with next Folder, in its own search loop, and spawns T4
To start searching its sub folders.

T1, T3 stay in communication as to where they are, and thus never search the
same folder twice while individual covering more gound. T2, T4 act similar
but in a different Starting location. T1, T2, VCL keep in touch as to where
they are. All Threads, Populate a list of successful files found, (or
possibly the exact file looked for, dependent upon wildcards). Thus they
can ceep processing, jumping from location to location without steppnig on
each others toes, as well as create a complete list of discovered files. In
This situation the communication is imperative, and should only interrupt
another threads execution based on the search parameters. (ie
FirstInstanceOfFile).

By desiging a manager that handles such communication, any one of these
designs would be made simpler, as the programmer using the repository would
just need to write the individual messages, and the actual process code of
the thread, and the rest is self contained. Basically simplifying all of
the Thread Management stuff into event driven actions and requests. For
the way it seems now, In order to send a message/event to a thread, it has
to be expecting it. That means when you create a thread, you have to write
the handler for those messages/events every time you need thread. Here I'm
working to have some universal messages for the manager & threads, as well
as a opening for programmer events/messages. Thus in the TMyThread class,
there would be SendMessageToManager(...) which would signal the manager with
a message. The manager handles the universal messages, and if it is a
'user-defined' (programmer message) the manager would have a
OnMessageRecieved(...) event that might be assigned. If its assigned,
(programmer worte an event for the situation) the threadmanager calls it,
and the programmer can process their own messages. This idea seems to take
three (maybe 4) steps in my opinion.

Write MessageHandlerEvent for Manager //Which can be a simple Case
Statement
Write Thread.Execute Code WITH the occasional SendMessageToManager()
calls imbedded for whatever reasons communication is necessary.
Define Message Values and Meanings for whatever communication the
situation calls for.
(Optional: Write Thread OnMessageRecieved Event to handle messages
from manager to thread, this one is not always necessary)

Using the the OS intercommunication , you not only have to write the Three
items above, but also have to write the back end code accessing the
api/delphi calls that make them work. I'm trying to eliminate some of the
back end, making it more universal, and thus individual threads can be made
with thought to what they do, not how they are going to inform other threads
of what their current state is. I can just SendMessage/OnRecieveMessage
etc.

Maybe, this has already been done, or maybe everyone is just used to writing
this every time they need it. I usually try to write designs of things that
make my life simpler in the future, and the way I currently see the OS
thread managing, seems like a lot of work to create the functionality I want
in certain circumstances. By Making this manager the way my mind interprets
it, would make life a lot easier.

Martin James

unread,
Sep 3, 2006, 7:09:44 AM9/3/06
to
>
> Actually, no. The main thread will be doing its own thing, as will the
> threads it spawns. I just don't want the main threads execution to be
> hindered by the functionality of the child thread. Basically, Thread1 (Vcl
> thread, or T1) is manipulating some data. T2 is spawned to manipulate other
> data. T1 may need to signal T2 about some event, or T2 may need to signal
> T1 of some event, but neither should cease their operations.
>
> Such as, with an object:
> Obj1
> onEvent: TObjEvent
>
> Obj1.Proc1
> begin
> if Assigned(onEvent) then
> onEvent(Self);
> end;
>
> This will instantly jump to wherever the onEvent procedure field points to,
> executing that code and returning to the rest of Obj1's code.

It will providing execution is applied to Proc1.

> (Note my idea has nothing to do with a thread termination, but this example
> will work perfectly for explanating what I'm designing)
> The effect that happens with TThread OnTerminate is what I wish to avoid.
> The TThread creates a threadspace that executes the Execute() method, and
> everything within that is within the execution code of it's Thread, as
> spawned by the BeginThread call. Within that thread space, it calles
> DoTerminate, which subsequently calls "Synchronize(CallOnTerminate)".
> This says to me, which might be where my logic flaw is residing, that the
> Thread, halts, pauses, or otherwise suspends operation, in order to
> syncronize with the VCL thread, in order to call the OnTerminate event
> method. It does not return, or proceed to the next command until the
> CallOnThread returns from its execution. If I am wrong on this
> interpretation, then I am begging to see my mistake.

You are not wrong. Using an OnTerminate handler, (ie synchronize).
necessarily requires that the main thread be available to process the
synchronize, else the secondary thread will get stuck.

> Instead, I want to Send a PostThreadMessage, which does not wait for the
> thread to process the message. For example two threads working with a data
> buffer,
> T1, the VCL thread is reading the buffer up to a specific marker. Say the
> first 20000 bytes. If it reaches 20000, it will fall into a wait state
> until the next section of the buffer is prepared. But T2, which is the
> thread fulling the buffer, can post a message to the VCL thread, which is
> processed, informing the Primary thread that the next segment of the buffer
> is valid to read. Even if the T1 is still working at position 12000, it
> won't hang and wait at 20000, since T2 already informed it the new limit is
> 40000. Thus the two threads can continue in their processes, while
> communicating without waiting.

For such a requirement, it is more common to use more than one buffer
instance. T2 creates and fills a buffer, PostMessages off the buffer
object reference *and immediately creates another one*. The main thread
then gets the posted buffer reference and processes it, freeing it when
done Meanwhile, the secondary thread is filling the new buffer. This
asynchronously decouples the secondary thread and main thread since they
can never be working on the same buffer reference. This design is more
flexible than a 'classic' shared circular-buffer to which the main and
secondary threads have in/out indexes. For example, if the main thread
gets a buffer back that indicates an error, it can easily forward the
buffer on to a logging thread, rather than freeing it, without any
concern about the secondary thread.

Once you start to reach the level of interactions that your propose, you
are starting to head towards a a CS-protected state-machine.

IMHO, thread-management is not a serious issue in most apps. Data
management is much more important. In OO designs, threads should be
looked at as a means of applying execution to object methods.

IMHO, to generalise complex interactions, you need a state-machine. For
such an engine to work effectively across multiple threads, the
state-engine would need CS-protection and no action would be allowed to
make blocking calls at all. This requires producer-consumer queues,
either Windows Message Queues or other, to prevent any blocking in the
action routines.

Any other way of implementing complex behaviours is very difficult to
control/maintain/expand.


To take one example from above - the simple MP3 player. What states are
there?

1) Stopped
2) Paused
3) Playing
4) Errored


UI events cause some transitions, eg Playing>Paused, (user hits pause
button).

Secondary threas can raise events that cause other transitions, eg
Playing>Stopped, (EOF/playlist exhausted).

There are other transitions that are 'abnormal', but should be catered
for, eg Playing>Errored, which happens when the MP3 decoder fires a
'protocol error', perhaps on a corrupt file.

If a structured design that cannot easily cope with all possibilities is
not available, there will be unreliability/chaos in your app. In your
example, the MP3 player might get stuck somewhere, jump to the next
track, leak buffers, CPU-loop or otherwise behave badly.

For instance, in an asynchronous system, it is possible for an MP3
protocol error to occur while the system has been paused or stopped by
the user - the MP3 decoder-thread has been signaled to stop and all its
input buffers have been purged from its input queue, but it is till
processing its last buffer and detects an error :(

In an SM design, such oddities can be catered for in a controlled, safe
manner. Inside the CS-protected engine, the events can cause
transitions in a serial fashion, in one easily-monitored,
easily-debugged place. Note that this does not mean that all the
threaded processes are synchronous, just the control/management of them :)


It is not impossible to design a 'generic' state-engine and
thread-management system that can be reasonably cope with a range of
requirements while being reasonably easy to design/configure, *but it
not easy at all*.

One example of the problems that such a system must handle is shutdown.
You can forget calling 'TmyComplexSystem.free' and expecting
everything to go away. Such simple paradigms do not work in general,
especially with many Delphi/Windows components that interact with the
main thread - such a component, expecting a main-thread interaction on
free, would deadlock if the main thread was itself stuck on the
TmyComplexSystem.free' call. Asynchronous systems often require
asynchronous shutdown - calling a 'shutdown' method that returns
'immediately', and, later, a 'shutdownComplete' event is fired, often in
the context of some last, unknown thread inside the complex system just
before it exits.

Generic task/thread managers are complex beasts - the OS kernel itself
is one example of such a manager. To cleanly shut down the OS, you have
to tell it to shut down and wait. Eventually, it turns off the power
supply. Just unplugging the box leads to a messy restart - the OS
rattles away for minutes as it rebuilds its data before you get your
desktop up.

Don't let me put you off, BTW :) A generic mutithreaded task-management
system would doubtless be useful. If you get it working, please let me
have it :)

One thought I had was to first develop a simple-to-build state-machine.
With some help from Remy L, I used a TCollection of action-events that
could be designed visually. This was fine, and then I tried to apply
execution to it.... :((

Maybee I should look at that disaster again sometime <g>

Rgds,
Martin

Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 3, 2006, 11:56:53 AM9/3/06
to

"Martin James" <nos...@dial.pipex.com> wrote in message
news:44fa...@newsgroups.borland.com...

> For such a requirement, it is more common to use more than one buffer
> instance. T2 creates and fills a buffer, PostMessages off the buffer
> object reference *and immediately creates another one*. The main thread
> then gets the posted buffer reference and processes it, freeing it when
> done Meanwhile, the secondary thread is filling the new buffer. This
> asynchronously decouples the secondary thread and main thread since they
> can never be working on the same buffer reference. This design is more
> flexible than a 'classic' shared circular-buffer to which the main and
> secondary threads have in/out indexes. For example, if the main thread
> gets a buffer back that indicates an error, it can easily forward the
> buffer on to a logging thread, rather than freeing it, without any concern
> about the secondary thread.

Yea, I wasn't thinking my example through completely there, but in the same
circumstance being able to inform
T1 of the new buffer, would involve a similar system.

> IMHO, thread-management is not a serious issue in most apps. Data
> management is much more important. In OO designs, threads should be looked
> at as a means of applying execution to object methods.
>
> IMHO, to generalise complex interactions, you need a state-machine. For
> such an engine to work effectively across multiple threads, the
> state-engine would need CS-protection and no action would be allowed to
> make blocking calls at all. This requires producer-consumer queues,
> either Windows Message Queues or other, to prevent any blocking in the
> action routines.

To make sure I'm understanding this, CS-protection, as in CriticalSection?
Also, produce-consumer queues. would this like having a specific Thread or
Loop that's entire purpose
is to handle communication between One Entity and other entities:
Eg: a 3-threaded app, on thread sends a message (ie producer) and another
thread is recieving the message (ie: consumer)
and thus a 4th thread would be added just to act as the Ameritech Operator
switchboard between the two?

Actually, this was part of my design. That the state machine, if I
understand what you mean by that, would be my repository
manager. It would most likely handle the spawning of the worker threads,
recieve communication from those threads, and
upon receipt use Synchronize to fire events in the VCL thread, thus VCL
<-TM-> T1, T2, T3. My only issue appears to be
in the message handling queue. More on that later.

> It is not impossible to design a 'generic' state-engine and
> thread-management system that can be reasonably cope with a range of
> requirements while being reasonably easy to design/configure, *but it not
> easy at all*.

*Chuckle* I am very much aware of that...this was a project I started 3
years ago, and had to put it on the shelf cause I couldn't
wrap my mind around it completely. The design is much clearer now, i'm just
hung up on some of the flow problems.

> One example of the problems that such a system must handle is shutdown.
> You can forget calling 'TmyComplexSystem.free' and expecting everything to
> go away. Such simple paradigms do not work in general, especially with
> many Delphi/Windows components that interact with the main thread - such a
> component, expecting a main-thread interaction on free, would deadlock if
> the main thread was itself stuck on the TmyComplexSystem.free' call.
> Asynchronous systems often require asynchronous shutdown - calling a
> 'shutdown' method that returns 'immediately', and, later, a
> 'shutdownComplete' event is fired, often in the context of some last,
> unknown thread inside the complex system just before it exits.

Oh yea, I had planned for that. And I think most systems do that, since
when you close down VS2005, or BDS2006 they don't just exit, they take
their time shutting down their stuff. The manager idea wouldn't be used for
rewriting NotePad. It would be used to help other programmers lives be made
a little easier. So that such in such a situation of closing the
application, or something that calls for the shutting down of the complex
system, the VCL thread would signal the TM thread, which in turn would
signal the individual T1, T2 & T3 threads, allowing them to individual
shutdown a signal a shutdownComplete event. In such a situation the VCL
could implement the example used in the "Wait for a task to be completed"
page of the BDS help. It uses a count decrimenter to determine when an even
can be triggered, and the VCL just does something like this:
begin
TM.ShutdownComplexSystem;
if shutDownComplete.WaitFor(20000) <> wrSignaled
then error;
...
end;


> Don't let me put you off, BTW :) A generic mutithreaded task-management
> system would doubtless be useful. If you get it working, please let me
> have it :)

I will, no problem.

The only phase of my design resides in Thread Message Management. My
original sugguestion was to use a
MsgWaitForMultipleObjects() call, but with a VERY low millisecond wait, like
500 or so.

CheckForMsgEvent()
begin
WaitResult:=MsgWaitForMultipleObjects(cHandles, Handles, false, 500,
QS_ALLEVENTS);
if WaitResult = WAIT_FAILED then
raise EThread.Exception
else if WaitResult = WAIT_TIMEOUT then
Result:=False;
else if WaitResult >= WAIT_ABANDONED_0 then
//Handle Abandoned stuff
else if WaitResult >= WAIT_OBJECT_0 then
begin
Result:=True;
WaitResult:=WaitResult - WAIT_OBJECT_0;
DetermineHandleType(Handles, WaitResult);
end;
end;

Now, another said that setting the wait-for-object (multiple or otherwise)
to such a low delay period was a bad thing, but the more I look at it, it
seems
to be the only way I can achieve my aim. As the above code suggests, a
WAIT_TIMEOUT is not an ERROR. Would not the above code, basically determine
if
a message or event exists, and return true/false based upon that. Thus

if CheckForMsgEvent() then
begin
ProcessMessageEvent(); //ie: GetMessage, or ResetEvent
end;

would be a valid line within the thread's execution. With this, such as
your example of the Mp3 decoder thread, it wouldn't be exactly as simple as
by crude designs here, but it would upon decoding a buffer and finding an
error in stream, it woudl internally schedule the error message, but since
it was busy it would do something like this:

loop
if checkmsg then
handlemsg;
processmp3(buffer);
if error or complete then
sendmessage;
end loop

sendmessage()
if checkmsg then
msgresult:=handlependingmsgs();
else msgresult:= 0;
case msgresult of
//cases where the pending msgs override the error warning, ie the
user stopped/paused
else
//no messages were waiting, and the thread can continue as normal,
posting its message to the Manager
end;


The key here, is that I must be able to determine IF a message/event is
present. Not WAIT for one WHEN it comes. there is no WHEN, only IF.
*chuckle*
GetMessage and PeekMessage will cause the instruction flow to pause and wait
until they return. This is what I want to avoid. But the 'wait-for-object'
methods above give you a allowable 'time-out' clause, which makes sense to
me. Not as an "error thread hung" mentality because teh timeout was
reached, but more, "nothing is present" timeout.
Is this be a gross misunderstanding of their functionality?

Thanks

Martin James

unread,
Sep 3, 2006, 2:15:44 PM9/3/06
to
>
> Yea, I wasn't thinking my example through completely there, but in the same
> circumstance being able to inform
> T1 of the new buffer, would involve a similar system.

T1 would just itself get a new buffer, either by creating it or getting
it from a pool of such buffer objects, ie trivially, communicating to
the main thread:

procedure TThread1.execute;
var thisBuffer:TBuffer;
begin
repeat
thisBuffer:=TBuffer.create;
fill(thisBuffer);
postMessage(ahandle,WM_CUSTOMMESSAGE,0,integer(thisBuffer));
until terminated;
end;

> To make sure I'm understanding this, CS-protection, as in CriticalSection?

Sorry - yes. I'm so used to using 'CS' for CriticalSection that I forgot
to use 'Critical Section', in full, as the first reference & so set up
the 'CS' contraction <g>

> Also, produce-consumer queues. would this like having a specific Thread or
> Loop that's entire purpose
> is to handle communication between One Entity and other entities:
> Eg: a 3-threaded app, on thread sends a message (ie producer) and another
> thread is recieving the message (ie: consumer)
> and thus a 4th thread would be added just to act as the Ameritech Operator
> switchboard between the two?

No specific thread required for a P-C queue - just code. A really
simple one can be easily implemented with a TObjectQueue descendant and
a semaphore - see end of this post.

>
> Actually, this was part of my design. That the state machine, if I
> understand what you mean by that, would be my repository
> manager.

Tomaytoes/tomartoes <g>

> It would most likely handle the spawning of the worker threads,

You may want to consider not spawning any threads at all during the app
run. In fact, if you do, you will be adding hugely to your management
loading - as well as job queueing, result-handling etc, etc, you have to
then also manage create/terminate/free during an app run. This is most
unpleasant at the best of times. I try very hard to put off any thread
termination until app close time, when it does not matter much if
anything goes wrong.

> recieve communication from those threads, and
> upon receipt use Synchronize to fire events in the VCL thread, thus VCL
> <-TM-> T1, T2, T3. My only issue appears to be
> in the message handling queue. More on that later.

If you use TThread.synchronize in your non-trivial app, I doubt that you
will ever get it working reliably, or even at all <g>


>> It is not impossible to design a 'generic' state-engine and
>> thread-management system that can be reasonably cope with a range of
>> requirements while being reasonably easy to design/configure, *but it not
>> easy at all*.
>
> *Chuckle* I am very much aware of that...this was a project I started 3
> years ago, and had to put it on the shelf cause I couldn't
> wrap my mind around it completely. The design is much clearer now, i'm just
> hung up on some of the flow problems.
>
>> One example of the problems that such a system must handle is shutdown.
>> You can forget calling 'TmyComplexSystem.free' and expecting everything to
>> go away. Such simple paradigms do not work in general, especially with
>> many Delphi/Windows components that interact with the main thread - such a
>> component, expecting a main-thread interaction on free, would deadlock if
>> the main thread was itself stuck on the TmyComplexSystem.free' call.
>> Asynchronous systems often require asynchronous shutdown - calling a
>> 'shutdown' method that returns 'immediately', and, later, a
>> 'shutdownComplete' event is fired, often in the context of some last,
>> unknown thread inside the complex system just before it exits.
>
> Oh yea, I had planned for that. And I think most systems do that, since
> when you close down VS2005, or BDS2006 they don't just exit, they take
> their time shutting down their stuff.

Exactly :)


The manager idea wouldn't be used for
> rewriting NotePad.

<g> yes - please don't rewrite Notepad - I like it nice and simple like
it is :)

> It would be used to help other programmers lives be made
> a little easier. So that such in such a situation of closing the
> application, or something that calls for the shutting down of the complex
> system, the VCL thread would signal the TM thread, which in turn would
> signal the individual T1, T2 & T3 threads, allowing them to individual
> shutdown a signal a shutdownComplete event. In such a situation the VCL
> could implement the example used in the "Wait for a task to be completed"
> page of the BDS help. It uses a count decrimenter to determine when an even
> can be triggered, and the VCL just does something like this:
> begin
> TM.ShutdownComplexSystem;
> if shutDownComplete.WaitFor(20000) <> wrSignaled
> then error;
> ...
> end;

Not exactly what I had in mind - this is a hard-sync waitFor and blocks
the main thread. If the 'TM.ShutdownComplexSystem'happens to try and
close something dodgy, (eg. a poor 3rd-party component that requires a
synchronize call to be completed in the main thread before freeing
itself), then you're deadlocked!

More safely:

-----------------------------------------------------------------------
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
canClose:=false; // prevent app closing for now
TM.ShutdownComplexSystem(OnSystemShutdown); // initiate shutdown,
// passing a TNotifyEvent to be called upon shutdown completion
end;

procedure TForm1.OnSystemShutdown(Sender: TObject);
// called as last line in the last thread in TM
begin
PostMessage(self.handle,WM_SSHUTDOWN,0,0); // comms to main thread
end;

procedure TForm1.SYSTEMSHUTDOWN(var message: TMessage);
// called on receipt of message from procedure above
begin
OnCloseQuery:=nil; // prevent recursion
close; // close app
end;
-----------------------------------------------------------------------


This shutdown sequence keep the main thread available to process
messages/APC/synchronize/whatever while the complex subSystem is
shutting itself down.


>
>> Don't let me put you off, BTW :) A generic mutithreaded task-management
>> system would doubtless be useful. If you get it working, please let me
>> have it :)
> I will, no problem.

I admire your confidence :) You may be right if you can avoid
synchronize, waitFor and the like synchronous hard-wait calls <g>

> The only phase of my design resides in Thread Message Management. My
> original sugguestion was to use a
> MsgWaitForMultipleObjects() call, but with a VERY low millisecond wait, like
> 500 or so.

This is polling. Though your design might mitigate the worst
waste/latency associated with polling, it's still polling :(


> CheckForMsgEvent()
> begin
> WaitResult:=MsgWaitForMultipleObjects(cHandles, Handles, false, 500,
> QS_ALLEVENTS);
> if WaitResult = WAIT_FAILED then
> raise EThread.Exception
> else if WaitResult = WAIT_TIMEOUT then
> Result:=False;
> else if WaitResult >= WAIT_ABANDONED_0 then
> //Handle Abandoned stuff
> else if WaitResult >= WAIT_OBJECT_0 then
> begin
> Result:=True;
> WaitResult:=WaitResult - WAIT_OBJECT_0;
> DetermineHandleType(Handles, WaitResult);
> end;
> end;
>
> Now, another said that setting the wait-for-object (multiple or otherwise)
> to such a low delay period was a bad thing, but the more I look at it, it
> seems
> to be the only way I can achieve my aim.

No there is another way - I might not be able to see it exactly yet, but
there is <g>

Yes, and this is the problem too <g>

Multitasking OS are wholly driven by events. On the OS scale, this
means interrupts to drivers that then cause threads to be made running.
The whole OS is a massive, complex interrupt-handler, or, to put it
another way, an event-driven system. Apps that run under such a system
should be event-driven as well in order to make the best use of the
system resources.

I appreciate that you want to receive 'update' commands in your
work-threads as soon as possible. I would prefer to dodge the whole
issue by just not issuing updates to the work-threads themselves, but to
a state-machine to which the work-thread has to go back to in order to
output completed work, get new work, issue errors etc.

If the work-threads make blocking calls that can be somehow interrupted,
ie. made to return early by some 'abort' method, then so much the
better. Such a thread cannot poll for aborts while it is blocked on
some system call, but an abort method, called by some other thread,
(teimout thread?), could unblock it 'immediately' so that it can mark up
its current work-object as 'timed out' and retun to its input queue to
eat up its next bowl of gruel.

> GetMessage and PeekMessage will cause the instruction flow to pause and wait
> until they return. This is what I want to avoid.

I'm not yet convinced that this is, in fact, what you want to avoid -
most developers would want to avoid short-timeout loops!

Using a short-timeout poll of the input to see if any new
buffers/commands etc. have come in is a problem for the thread
processing rate. If any timeout other than 0 is used, each poll blocks
the thread for a while when it could be processing buffers. If 0 is
used, the worst of this delay is removed, but there is still a problem
with thread control - if processMP3 sticks or loops, the thread is
irretrievably blocked/loping and cannnot poll for 'stop' messages. Only
another thread can take any action to recover it, terminate it or orphan
it at idle priority for ever.

>
> But the 'wait-for-object'
> methods above give you a allowable 'time-out' clause, which makes sense to
> me. Not as an "error thread hung" mentality because teh timeout was
> reached, but more, "nothing is present" timeout.
> Is this be a gross misunderstanding of their functionality?
>

Not really. I think I know what you are trying to do, but I'm not
convinced that your design is the right way to do it.

IMHO, timeouts should not be handled by the thread/s that are doing
general work. A timeout should be performed in one, separate
timeout-thread that can fire a timeout event into a state-machine. This
allows stuck/looping threads to be timed out. Such timeouts should be
easily cancellable so that when a work thread fires a processed buffer
into the state-machine, the timeout is stopped. If a work-item has been
dispatched to a thread and does not return the item before the timeout,
the timeout-event action routine in the SM can queue an error-item to
the work-object initiator, mark the work-item that is 'lost' in the
thread as 'abandoned' and, perhaps, attempt to render the stuck thread
redundant and create another one.

Rgds,
Martin


unit MinimalSemaphorePCqueue;

{ Absolutely minimal P-C queue based on TobjectQueue and a semaphore.

The semaphore count reflects the queue count
'push' will always succeed unless memory runs out, then you're stuft anyway.
'pop' has a timeout parameter as well as the address of where any received
object is to be put.
'pop' returns immediately with 'true' if there is an object on the queue
available for it.
'pop' blocks the caller if the queue is empty and the timeout is not 0.
'pop' returns false if the timeout is exceeded before an object is available
from the queue.
'pop' returns true if an object is available from the queue before the
timeout
is exceeded.
If multiple threads have called 'pop' and are blocked because the queue is
empty, a single 'push' will make only one of the waiting threads ready.


Methods to push/pop from the queue
A 'semaHandle' property that can be used in a 'waitForMultipleObjects' call.
When the handle is signaled, the 'peek' method will retrieve the queued
object.
}
interface

uses
Windows, Messages, SysUtils, Classes,syncObjs,contnrs;


type

pObject=^Tobject;

TsemaphoreMailbox=class(TobjectQueue)
private
countSema:Thandle;
protected
access:TcriticalSection;
public
property semaHandle:Thandle read countSema;
constructor create; virtual;
procedure push(aObject:Tobject); virtual;
function pop(pResObject:pObject;timeout:DWORD):boolean; virtual;
function peek(pResObject:pObject):boolean; virtual;
destructor destroy; override;
end;


implementation

{ TsemaphoreMailbox }

constructor TsemaphoreMailbox.create;
begin
inherited create;
access:=TcriticalSection.create;
countSema:=createSemaphore(nil,0,maxInt,nil);
end;

destructor TsemaphoreMailbox.destroy;
begin
access.free;
closeHandle(countSema);
inherited;
end;

function TsemaphoreMailbox.pop(pResObject: pObject;
timeout: DWORD): boolean;
// dequeues an object, if one is available on the queue. If the queue
is empty,
// the caller is blocked until either an object is pushed on or the timeout
// period expires
begin // wait for a unit from the semaphore
result:=(WAIT_OBJECT_0=waitForSingleObject(countSema,timeout));
if result then // if a unit was supplied before the timeout,
begin
access.acquire;
try
pResObject^:=inherited pop; // get an object from the queue
finally
access.release;
end;
end;
end;


procedure TsemaphoreMailbox.push(aObject: Tobject);
// pushes an object onto the queue. If threads are waiting in a 'pop' call,
// one of them is made ready.
begin
access.acquire;
try
inherited push(aObject); // shove the object onto the queue
finally
access.release;
end;
releaseSemaphore(countSema,1,nil); // release one unit to semaphore
end;

function TsemaphoreMailbox.peek(pResObject: pObject): boolean;
begin
access.acquire;
try
result:=(count>0);
if result then pResObject^:=inherited pop; // get an object from
the queue
finally
access.release;
end;
end;


end.

Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 3, 2006, 3:33:46 PM9/3/06
to

"Martin James" <nos...@dial.pipex.com> wrote in message
news:44fb...@newsgroups.borland.com...

> No specific thread required for a P-C queue - just code. A really simple
> one can be easily implemented with a TObjectQueue descendant and a
> semaphore - see end of this post.

I'm gonna have to look into semaphores a little more...*chuckle*

Good Idea...I see how this would be better suited to the task.

>> The only phase of my design resides in Thread Message Management. My
>> original sugguestion was to use a
>> MsgWaitForMultipleObjects() call, but with a VERY low millisecond wait,
>> like 500 or so.
>
> This is polling. Though your design might mitigate the worst
> waste/latency associated with polling, it's still polling :(

Hrm.. There isn't by any chance some way to determine if something is in
the queue without polling? Because you're right I don't really want to poll
for it, because it would take up resources.

> I appreciate that you want to receive 'update' commands in your
> work-threads as soon as possible. I would prefer to dodge the whole issue
> by just not issuing updates to the work-threads themselves, but to a
> state-machine to which the work-thread has to go back to in order to
> output completed work, get new work, issue errors etc.
>
> If the work-threads make blocking calls that can be somehow interrupted,
> ie. made to return early by some 'abort' method, then so much the better.
> Such a thread cannot poll for aborts while it is blocked on some system
> call, but an abort method, called by some other thread, (teimout thread?),
> could unblock it 'immediately' so that it can mark up its current
> work-object as 'timed out' and retun to its input queue to eat up its next
> bowl of gruel.

Yea...This is the crux of the problem I keep banging my head against. I had
written a "progressform" unit for my many applications that allowed the
containment of a Modal dialog form in a single thread. THis allowed me to
work the operation magic, while updating the progressbar without using
synchronize. It was cludgy and very convoluded, but what I had done was use
a GetTickCount() and WM_TIMER to internally check if it was hung. Sort of a
self check if you may. This was for an old utility to parse mp3 file names
from napster downloads, and attempt to interpret the artist/name/album/track
from regular expression strings compared to the filename. Of course they
weren't regular expressions at the time, i just sort of invented my own
code. But as you can see from below, I used the Application.ProcessMessages
call. At the time I had no idea what it did, but I did know that it forced
within my loop the thread's form to check its messages.
the Thread Execute was simple: CreateForm, Execute Threadresult =
TProgForm.Execute. The Form Execute, Activated the timer, and set the
return value to ShowModal = mrOk; This was the mold that I wanted to use as
the basis for my manager, which is why i initialy thought I needed a
createwindow HWND to receive messages.

procedure TProgForm.TimerTimer(Sender: TObject);
begin
Case WhatsActive of
1: SendMessage(Self.Handle, WM_STARTRENAME, 0, 0);
2: If tfThread.Terminated then
Canceled:=True
else if tfFinished or tfCanceled or tfFailed then
Inc(tfWhatsActive);
3: Begin
CleanUp;
Timer.Enabled:=False;
end;
end; {case}
end;

DoRenaming
begin
While (I < FileList.Count) or tfStop do
begin
SetOldName(FileList[I]);
St:=ResetName(FileList[I]) + Mp3Ext;
SetNewName(St);
if FileExists(Directory + FileList[I]) then
RenameFile(Directory + FileList[I], Directory + St);
Application.ProcessMessages; //<-- Here is
where I did the Timer Loop
Inc(I);
SetProgBar(I);
SetOpLab(omProcess, Format('Renaming files... (%d, %d)', [I,
ProgBar.MaxValue]));
end;
end;

Now i look back and see I was doing so unnecessary work, where I could have
simply put a getmessage call in there or something, because ProcessMessages
just does a Peekmessage message loop. But, the concept, i think, of the
internal WM_TIMER message to check for aborts, as well as internal errors,
etc is a good one. I'm just now thinking that the message processing Might
not be the best way to go about it. I'll have to think on this one for a
bit to get my head straight.

> I'm not yet convinced that this is, in fact, what you want to avoid - most
> developers would want to avoid short-timeout loops!
>
> Using a short-timeout poll of the input to see if any new buffers/commands
> etc. have come in is a problem for the thread processing rate. If any
> timeout other than 0 is used, each poll blocks the thread for a while when
> it could be processing buffers. If 0 is used, the worst of this delay is
> removed, but there is still a problem with thread control - if processMP3
> sticks or loops, the thread is irretrievably blocked/loping and cannnot
> poll for 'stop' messages. Only another thread can take any action to
> recover it, terminate it or orphan it at idle priority for ever.

So true, so true. But that would be the job of the manager. If the Thread
is locked in-process, then the internal selfcheck interval will grow too
large, and the controlling thread will see that the currentTickCount >
lastTickCount + Interval, and would kill the tread, or orphan it. Now I see
i would need to make this a task of the manager, to manage the timeout
checks of the worker-threads. But, much as my above example, I had to,
wihtin my loop, process messages, or else the "Cancel" button on the modal
form wouldn't work. Being stuck in the loop, once started, the form never
exited until the end of the loop. This is sort of the issue i wanted to
avoid. Much like the thousands of applications out there, that when you
accidentally open the app, or run an operation. Say, VS2005 - Build, if it
didn't check for incoming messages during its compilation and linking loops,
the ctrl-c would never halt the operation. And so, in a quick fit, you tell
it to build your project, and seconds after, realize you needed to add a
line in there that you forgot. Without that message processing loop, you
would have to just wait for the 5 minutes until the project was built. And
then rebuild again once you made the change.
The same, I feel, is true for threads and other such asynchronous processes.
I want the ability to talk to the child thread, through messages or events,
so that the thread can react to the event as soon as feasibly possible.
Which i think the semaphore method below might help with that granted a few
clarifications.

>> But the 'wait-for-object' methods above give you a allowable 'time-out'
>> clause, which makes sense to me. Not as an "error thread hung" mentality
>> because teh timeout was reached, but more, "nothing is present" timeout.
>> Is this be a gross misunderstanding of their functionality?
>>
>
> Not really. I think I know what you are trying to do, but I'm not
> convinced that your design is the right way to do it.

<g> That's always been my problem.

> unit MinimalSemaphorePCqueue;
>
> { Absolutely minimal P-C queue based on TobjectQueue and a semaphore.
>
> The semaphore count reflects the queue count
> 'push' will always succeed unless memory runs out, then you're stuft
> anyway.
> 'pop' has a timeout parameter as well as the address of where any received
> object is to be put.
> 'pop' returns immediately with 'true' if there is an object on the queue
> available for it.
> 'pop' blocks the caller if the queue is empty and the timeout is not 0.
> 'pop' returns false if the timeout is exceeded before an object is
> available
> from the queue.
> 'pop' returns true if an object is available from the queue before the
> timeout
> is exceeded.
> If multiple threads have called 'pop' and are blocked because the queue is
> empty, a single 'push' will make only one of the waiting threads ready.

Again, I see something and it sounds awesome with what I 'want' to do, but
can't a way to 'do it'. It says here, that the push will add an object to
the end of the queue, and pop will return the first item in the queue. The
Semaphore count reflects the queue count. This seems to be ideal for my
situations, except, can you ask the system what the current count of a
semaphore is?
(The CreateSemaphore help says you the initialcount should be >0 but in your
code here you started it at 0, is that okay to do?)

So would it be more appropriate than the polling idea, to do something like
this:

ObjectQueue -> Maintain a list of messages, or events or whatever
communication design between Manager and Threads
createsemaphore(nil, 0, maxInt, nil);
OQ.Count:=0;

push
releasesemaphore(sema, 1, nil);
Inc(Count);

pop
waitforsingleobject(sema, timeout)

In my thread and/or manager do this
if ObjectQueue.Count > 0 then
OQ.Pop();


Would that be a way for me to easily dermine that a message/event was in the
queue, without "polling" the system with a 0 ms timeout?

Thanks
Jaeden "Sifo Dyas" al'Raec Ruiner


PS: Given the nature of the ObjectQueue, would that be something that I
could use to pass my own internal messages back and forth between manager
and thread without having to resort to the PeekMessage or Wait-For-Object
loops, thus bypassing that style of communication within the work-item
threads, while still being able to communicate with them?


Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 3, 2006, 6:56:34 PM9/3/06
to
As a quick side note to threads, I wanted to look at something and get some
advice on a little thing called CriticalSections.

TThreadList, basically is a wrapper for TList, which is a object interface
for an array of objects. Well a long time ago for a project I was working
on, I noticed that when dealing with say, 15000 items in a list, it could
get rather tedious looking for the specific item. So I wrote my own. (Yes,
I do tend to do that alot). Based upon a simplistic binary hash algorithm,
along with the age old joy of link lists, I was able to create a complete
repository of runtime mutable list classes. I even created a
VirtualAlloc/VirtualRealloc stream handler for large buffers, and wrapped it
around a TStream object, so that TFileStream could import/export from it.
Everything is cool. The hash algorithm is quite nice, if i say so myself,
interfacing directly with a predefined linklist type, where the first 8
bytes are the next/prev pointers and thus, as long as anyone inheriting the
HashTableClass, could easily flow with this design, since AllocHash,
FreeHash, and GetHashIndex are abstract. So as long as your list record
starts with a Next pointer to the next item in the hash, the default methods
will work. Of course I made GetNext/GetPrev virtual so if you change this
you can update it. The cool thing about this list, is that it bases itself
defaultly off an 8-bit hash, thus it initially creates an array 0-255, and
the Hash value is computed of the item index (32-bit) into an 8-bit byte
index for the array and is added into the appropriate link list. Very
standard for a hash indexing algorithm. The primary reason for this was, as
I said, we were dealing with lists of things in the multi-thousands, so
cycling through the first 12000 entries in a list to find 12001 sucked in
time constraints, but converting 12001 to an 8 bit hash (basically xoring
the individual bytes of the dword) you get 207 and you only have to look
through approximately 60 entries.

I say this list was real time mutable, because the HashIndex computation was
based upon a bit-limit hash. So, if say you are running a list that is only
15,000 items, an 8-bit hash is nice, but if that was 150,000 items, you
might feel the need to increase the hash alotment. By a simple call to
ResizeHashTable, you can change that 8-bit hash to a 10-bit hash, and
suddenly that array of 0-255, becomes an array of 0-1023, and instead of
searching through 585 items per index, you only are searching through 146.
You get my drift, enough on describing things you already know, just wanted
to give a little background as to where this came from.

In TThreadList, the list uses criticalsections to lock the list before
adding or deleteing or any manipulation, (which includes user (programmer)
controlled manipulations, like multiple adds). It does this by entering the
critical section before accessing the internal TList field, and then
leavining the critical section it afterwords. Of course, now that I am
working with threads, I want to make my list system thread safe. However,
I'm thinking about the time delay. For, there are two possibilities here,
you could do:

TThreadList.Add() -> Which Enters and Leaves the CriticalSection internally
or
TThreadList.LockList -> Which Returns a pointer to the TList object, which
you would follow up with TList.Add() or TList.Delete

This makes sense. I don't think anyone would do
TThreadList.LockList
TThreadList.Add() -> which would enter the critical section twice, seems
redundant.

Here's the kicker: Would it be prudent, given my list object design, to
instill a critical section WITHIN the list, locking/unlocking the critical
section at the moment of access? Instead of creating a wrapper around
MyHashListClass, as they did with TThreadList around TList, would it be
okay/wise to do something like this:

TList.Add()
EnterCS
doAdd
LeaveCS

TList.Delete
EnterCS
doDelete
LeaveCS

etcetera. Or would that be illogical use of the Criticalsection design?
Thanks

Martin James

unread,
Sep 4, 2006, 6:07:31 AM9/4/06
to
>
> I'm gonna have to look into semaphores a little more...*chuckle*

A 'classic' inter-thread comms synchro mechanism, available on all OS
for a long time. At a low-level, on many OS, the only way to
communicate from a driver to the scheduler, eg to make a thread ready
that was waiting on I/O from the driver.

The simple queue I posted is not the fastest P-C queue possible. It
always makes a semaphore kernel call on push/pop - this can be avoided
in those cases where a pop is made on a queue that already contains
objects or a push is made when there are no threads waiting. Also,
TObjectQueue is, in itself, slow and increasingly slow with large
numbers of objects - it's based on TList :(

The semaphore queue is however, very simple to code up and to understand
how it works. For 'thread-newbies', this is better than a much more
complex, but difficult-to-understand, high-performance queue. It's
faster than a Windows message queue anyway, at least for small numbers
of queued objects.

>>
>> This shutdown sequence keep the main thread available to process
>> messages/APC/synchronize/whatever while the complex subSystem is shutting
>> itself down.
>
> Good Idea...I see how this would be better suited to the task.

If there are several subsystems, they are easily tracked as they shut
down since the OnCompletion event is fired serially by the messages. A
count of the systems could be decremented or, if a list of the subSystem
references has been kept by the main thread, the postMessage could carry
a reference to the system that has shut down and so each system could
be removed from the list until the count is zero. Since the main thread
is still alive, a simple TTimer could time out the progress of the
shutdowns and, if timed out, could take any 'normal' delphi actions -
displaying a modal form with an error message, logging the identity of
the failed system/s to disk, whatever. The user could then perhaps
click a button that calls 'ExitProcess()', so instructing the OS to
force the app closed in a somewhat untidy manner - better than a frozen app.

>>> The only phase of my design resides in Thread Message Management. My
>>> original sugguestion was to use a
>>> MsgWaitForMultipleObjects() call, but with a VERY low millisecond wait,
>>> like 500 or so.
>> This is polling. Though your design might mitigate the worst
>> waste/latency associated with polling, it's still polling :(
>
> Hrm.. There isn't by any chance some way to determine if something is in
> the queue without polling? Because you're right I don't really want to poll
> for it, because it would take up resources.

Depends on the queue class <g>

You need more beer. Usually works for me <g>

>> I'm not yet convinced that this is, in fact, what you want to avoid - most
>> developers would want to avoid short-timeout loops!
>>
>> Using a short-timeout poll of the input to see if any new buffers/commands
>> etc. have come in is a problem for the thread processing rate. If any
>> timeout other than 0 is used, each poll blocks the thread for a while when
>> it could be processing buffers. If 0 is used, the worst of this delay is
>> removed, but there is still a problem with thread control - if processMP3
>> sticks or loops, the thread is irretrievably blocked/loping and cannnot
>> poll for 'stop' messages. Only another thread can take any action to
>> recover it, terminate it or orphan it at idle priority for ever.
>
> So true, so true. But that would be the job of the manager. If the Thread
> is locked in-process, then the internal selfcheck interval will grow too
> large, and the controlling thread will see that the currentTickCount >
> lastTickCount + Interval, and would kill the tread, or orphan it. Now I see
> i would need to make this a task of the manager, to manage the timeout
> checks of the worker-threads. But, much as my above example, I had to,
> wihtin my loop, process messages, or else the "Cancel" button on the modal
> form wouldn't work.

Yes, hence the need for secondary threads to do all work except
operating the GUI.

>
Being stuck in the loop, once started, the form never
> exited until the end of the loop. This is sort of the issue i wanted to
> avoid. Much like the thousands of applications out there, that when you
> accidentally open the app, or run an operation. Say, VS2005 - Build, if it
> didn't check for incoming messages during its compilation and linking loops,
> the ctrl-c would never halt the operation. And so, in a quick fit, you tell
> it to build your project, and seconds after, realize you needed to add a
> line in there that you forgot. Without that message processing loop, you
> would have to just wait for the 5 minutes until the project was built. And
> then rebuild again once you made the change.

Yes - decades of multitasking OS and we still, today, have those
VB-style hourglass-apps. It is indeed very frustrating for users to
accidentally start something they cannot stop.

> The same, I feel, is true for threads and other such asynchronous processes.
> I want the ability to talk to the child thread, through messages or events,
> so that the thread can react to the event as soon as feasibly possible.
> Which i think the semaphore method below might help with that granted a few
> clarifications.

To do this without excessive, or maybe any, polling-overhead, you could
do with some support from both the queue and the thread.

You could derive the threads, (or the work objects that thread executes,
if using a generic thread), from a class of TThread with a virtual
'abort' method. This method would, if not overridden, just set an
'abort' flag. A work-item that is just CPU-intensive, (eg. perhaps it
contains a matrix that the thread has to invert), can poll, (Ugh - but
it has to be done), this 'abort' boolean at suitable intervals, eg. at
the end of the innermost, 'tightest' loop. Testing a boolean is much
faster than a queue poll call. Once your loopy code has detected the
abort, it can clean up, mark the work-item as 'aborted', return it to
wherever it came from and go back to its input queue to wait for more work.

In the case of work-threads that are executing blocking calls, the
'abort' method could be overridden to 'break' the blocking call, eg. by
closing a socket that the thread is reading from or creating a temporary
file to prematurely wake-up a 'FindFirstChangeNotification' call.

How to call the 'abort' method? You could just call it from your
timeout/main/whatever thread. There is a problem with this in the
generic case. If there is more than one thread in a pool, the entity
that is trying to do the abort may not know which thread is executing
your work item. The queue can know - since the thread dequeued the item,
the queue can keep a reference to the work-item and thread in a list of
dequeued items. This implies that such an entry must be removed when the
thread has successfully processed it. This can be done easily if the
work-item has descended from a class with a virtual/abstract
'returnToSender' method - the thread can call a 'return' method of the
queue with the completed work-item, the queue removes the 'pending' list
entry and calls the 'returnToSender' method of the work-item.

The 'returnToSender' method could do whatever it needs to, eg. directly
postMessage itself to the main thread, queue itself on to another
thread, call a state-machine,whatever.

>
> Again, I see something and it sounds awesome with what I 'want' to do, but
> can't a way to 'do it'. It says here, that the push will add an object to
> the end of the queue, and pop will return the first item in the queue. The
> Semaphore count reflects the queue count. This seems to be ideal for my
> situations, except, can you ask the system what the current count of a
> semaphore is?

No, because it might be wrong by the time such a call returned <g>

> (The CreateSemaphore help says you the initialcount should be >0 but in your
> code here you started it at 0, is that okay to do?)

It's fine, from SDK:

lInitialCount

Specifies an initial count for the semaphore object. This value must be
greater than *or equal to* zero

> So would it be more appropriate than the polling idea, to do something like
> this:
>
> ObjectQueue -> Maintain a list of messages, or events or whatever
> communication design between Manager and Threads
> createsemaphore(nil, 0, maxInt, nil);
> OQ.Count:=0;
>
> push
> releasesemaphore(sema, 1, nil);
> Inc(Count);
>
> pop
> waitforsingleobject(sema, timeout)
>
> In my thread and/or manager do this
> if ObjectQueue.Count > 0 then
> OQ.Pop();
>
>
> Would that be a way for me to easily dermine that a message/event was in the
> queue, without "polling" the system with a 0 ms timeout?

Well.. maybee. You would still have to lock the CS to get the count.
I'm sorry, but the more I think about the 'polling the input queue'
plan, the less I like it. At worst, I would only want to poll a boolean
set by the thread asking for the abort.

> Thanks
> Jaeden "Sifo Dyas" al'Raec Ruiner
>
>
> PS: Given the nature of the ObjectQueue, would that be something that I
> could use to pass my own internal messages back and forth between manager
> and thread without having to resort to the PeekMessage or Wait-For-Object
> loops, thus bypassing that style of communication within the work-item
> threads, while still being able to communicate with them?

PeekMessage/Windows Message Queues:

1) Windows Message Queues are specifically designed for queueing
driver>GUI messages. Such messages are, what, 24-bytes long? This is
so small that the queue can efficiently store the entire 24 bytes inside
the queue. Allocating 24-bytes of memory, storing the data in it,
queueing the 32-bit reference and freeing this memory-block after
receipt would not be efficient. When developers are communicating
buffer-objects around threads, however, the buffer classes are typically
much larger than 24 bytes. Copying such data into a very wide queue,
and copying it out again, is obviously very bad and it's much quicker to
queue 32-bit references. Summary: WMQ are slower than user-space P-C
queues <g>

2) A WMQ call, eg. PeekMessage, always requires a kernel call. With
faster classes of user-space queues, this can be avoided in some cases.

3) A WMQ only allows one thread to wait on it - the one that created it.
This makes thread-pooling and object-pooling very awkward. A
user-space P-C queue can have many threads waiting on it and can easily
used to store a pool of inter-thread comms objects. Such pooling can be
very useful - to take the MP3 example again, there is the problem that
the file-reading thread can queue buffers much faster than the
sound-card thread can render them into music. To avoid memory-use
growth with a large playlist, you need flow-control. This is very easy
to do with P-C queues. You can shove, say, 16 buffers into a pool queue
at startup. The file thread gets buffers from this queue, loads 'em up
and queues them on another P-C queue to the sound-thread. The
sound-thread gets buffers, fires them into the sound card, waits until
the sound-card asks for another buffer and releases 'used' buffers back
to the pool queue. When the faster file-thread has queued off 16
buffers and tries to get another, it gets blocked on the now-empty pool
queue until the sound-thread eventually releases used buffers back to
the pool. Not only does this mechanism provide flow-control of the
buffers, it also eliminates the memory-management calls required to
continually create/free buffer objects.


4) Once a message has been posted to a WMQ, the kernel has it. It
cannot be purged from the queue except by the thread that is waiting on
the queue. In your polling-plan, you could issue an 'abort' message to
the queue but, if the target-thread already has 32 MP3-buffers queued to
it, it will not get the 'abort' message until it has polled/processed
the other 32 buffers first. WMQ are FIFO - you cannot send a
'high-priority' message and you cannot purge the queue from the sending
end :((( A P-C queue can be coded to queue messages in priority-order
or can be easily purged of now-redundant objects, eg:

var dump:TObject;
..
while myQueue.pop(@dump,0) do dump.free; // purge queue

5) WMQ are inpenetrable - you cannot add any 'special' debugging code to
the WMQ to find and fix some nasty, obscure bug.


I only use PostMessage/WMQ for comms to the main thread, ie. when it is
unavoidable. For all other inter-thread comms, I use a user-space P-C
queue.

Rgds,
Martin

David J Taylor

unread,
Sep 4, 2006, 6:21:19 AM9/4/06
to
Martin James wrote:
[]
> Rgds,
> Martin

Folks,

This thread, whilst it has become a little long, contains much valuable
information which I would like to see posted to a Web site (or somewhere
more permanent that a news server). Would anyone care to summarise the
salient points? (As I don't use threads, I don't feel competent to do
this myself).

Thanks,
David


Martin James

unread,
Sep 4, 2006, 9:56:05 AM9/4/06
to
>
> Folks,
>
> This thread, whilst it has become a little long, contains much valuable
> information which I would like to see posted to a Web site (or somewhere
> more permanent that a news server). Would anyone care to summarise the
> salient points?

That would be difficult as the OP and myself have not yet decided what
our salient points are <g>

Jaeden has not yet implemented his generic thread-manager. I built one
that did not work properly. I would not want to commit anything to any
web site as any sort of authoritative design plan unless an example of
it can be seen working, (at least for several seconds:)

(As I don't use threads, I don't feel competent to do
> this myself).

To be pedantic, if you develop any app you must use at least one <g>

Rgds,
Martin

David J Taylor

unread,
Sep 4, 2006, 10:49:56 AM9/4/06
to
Martin James wrote:
{}

>> (As I don't use threads, I don't feel competent to do
>> this myself).
>
> To be pedantic, if you develop any app you must use at least one <g>
>
> Rgds,
> Martin

As I don't use /multiple/ threads....

Actually, some of the communications and other components I use do
actually have separate threads.

<G>

David


Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 4, 2006, 11:01:18 AM9/4/06
to
Well then it is settled. The last time someone told me i couldn't do
something...
hehehe, An Access Database teacher of mine that told me that to perform a
Many-to-Many relationship, it required a Junction table in MS Access, a
table that couldn't be automatically populated, and had to be done manually.

heheheheh, suffice it to say, I proved him wrong and got the 4.0
*cheezygrin*

So when I get this done, we will all go round-robin on it to make sure it is
concise enough to support the local community.

*smile*

--

Jaeden "Sifo Dyas" al'Raec Ruiner

aka Fluffy
http://www.wayoftheleaf.net/


"Martin James" <nos...@dial.pipex.com> wrote in message

news:44fc3039$1...@newsgroups.borland.com...

Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 4, 2006, 12:27:30 PM9/4/06
to

"Martin James" <nos...@dial.pipex.com> wrote in message
news:44fb...@newsgroups.borland.com...
>>
> The simple queue I posted is not the fastest P-C queue possible. It always
> makes a semaphore kernel call on push/pop - this can be avoided in those
> cases where a pop is made on a queue that already contains objects or a
> push is made when there are no threads waiting. Also, TObjectQueue is, in
> itself, slow and increasingly slow with large numbers of objects - it's
> based on TList :(
>
> The semaphore queue is however, very simple to code up and to understand
> how it works. For 'thread-newbies', this is better than a much more
> complex, but difficult-to-understand, high-performance queue. It's faster
> than a Windows message queue anyway, at least for small numbers of queued
> objects.

Further down you mentioned the boolean flag polling. This got me thinking,
because this is Identical to the TThread's Terminate procedure and how you
(the programmer) are supposed to look for that flag in your Execute() loop.
Given that idea, combined with WaitForMultipleObjects, Semaphores, and
Object Queues, I came up with this cooooookeeee idea, really off the wall, i
know, but I'm reading logic, not exact specifics. But everything we've
talked about up to now as led me to this as a near final conclusion to what
I believe is my ... IDEA!!! (whew)

Okay, so wrap around this idea, stop me if you've heard it before, i'm
hoping my interpretation of semaphores is accurate (basiccaly that they can
go two ways):

TEM //Event manager class. using semaphores, possibly, two basic ones,
//but with the option for user added "events"
Sema1 = WaitIdleExit //Thread Listens
1.5 = IdleReceived //TM Listens
Sema2 = ItemInQueue //TM Listens
2.25 = UserSemaphore //Thread Listens
2.5 = ItemReceived //TM Listens
Sema3 = AbortQuit; //ThreadListens
3.5 = Quitting //TM listens

TM
[TimeOut SemaPhore(s)] //this might be a TEM class, but solely
dedicated to
//the timeout thread
[TimeOut Thread]
[Timeout Queue]
[T1, T2, T3]
[TQ1, TQ2, TQ3]
[EM1, EM2, EM3] //These need not be protected, since the Threads
never access them, they only manage the handles of the semaphores, so the
handles
//can be passed upon creation, or via Object Queue (for the use
of adding new handles to the timeout thread)

Thread //from which T1, T2, T3 are derived
Abort(); virtual; //signals abort flag
Idle(); virtual; //Signals idle flag, which retreats from Thread 'loop'
//to WaitForMultipleObjects(EM#.WaitIdleExit & EM#.AbortQuit)
//If I'm right on Semaphores the WaitIdleExit Semaphore could be
//used here as a Return Receipt of the Idle Boolean Flag to the TM
//or maybe a seperate semaphore needs to be used to call back to
//TM.
User(); virtual; //abstract? if not abstract just be empty.
//Sets the USER flag. The user Flag (boolean) indicates to the
Thread,
//that an Item is waiting in it's Personal TQ# Object Queue, which
//naturally containes Programmer Coded specific Thread Message/
//Operation/Information which naturally could include the Calling
Thread
//(similar to the WM_USER messages of the WMQ, just using an
//Object Queue instead of PeekMessage
ReturnToTM(); // This would set the EM#.ItemInQueue Semaphore
//After pushing an object into its personal TQ# Object queue
//Back to the TM.

The Timeout Thread could be used in conjunction with the EM# event managers
to create a single
WaitForMultipleObjects(TimeLimit), with a list of all possible semaphore
handles to the subsequent child threads, and use Synchronize() to call event
procs in the TM class (which is in the VCL thread) to inform it of the
*whatever* event for *whatever* thread. (This could also use WMQ, or
Semaphore/Queue Whichever is most appropriate for the situation, I think WMQ
or Synchronize is best in this situation between VCL based TM and TimeOut)
The TimeoutSemaphore is for the TM class to communicate with the Timeout
Thread, to let it know to break its Wait-For-Function, and execute a specifc
TM callback event, synchronized,messaged, whatever, with whatever the
necessary information may be, like a newly added thread which means new
semaphore handles need to be added to the wait-for-function, or a thread
shutdown has completed and been freed, so we no longer need to wait-for that
thread's semaphore handles. etc.

This Model seems to utilize the best of all worlds, by forcing the TimeOut
thread to be the only one to ever synchronize with or message the main VCL
thread, and it only does so to call TM.OnEvent callbacks (which in turn do
whatever VCL events are necessary). Synchronize possibly could be avoided
by useing a PostMessage(Application.handle) and then the message through the
main form sent to the TM, but whichever is most appropriate, the TM Handles
Messages (in & out) for the vcl, The TimeOut thread waits for messages from
the Threads and the TM, and each thread has its own internal message flag
processing, with a loop somewhat like this:

repeat
while Not Checkflags do
begin
//Thread Stuff
end;
if Abort then break;
if Done and GoIdleWhenDone then Idle:=True
else break; //This could be used to say, that the current process is
over, but a new one may be added so wait for it
until false;

CheckFlags(); virtual; (so the inheriting object could override this
functionality to suit their needs)
var AbortIdle, UserIdle;
if Not Abort then //Check if abort is set as a priority flag;
begin
if User then ProccessUserObject(True); //processes the
UserSemaphore since one is set
if Idle then
Res:=WaitForMultipleObjects(WaitIdleExit & AbortQuit &
UserSemaphore) - WAIT_OBJECT_0;
UserIdle = (Res = UserSemaphore) //to process possible Idle
state from DONE to User provided new information to restart thread.
AbortIdle = (Res = AbortQuit) //to process possilbe Abort
states quile idle
end
else begin
If User then
Notify TM of Abort Overrideing User Object Queue (for Object
Queue handling, ie, release object from queue since it is still there

If Idle then
Notify TM of Abort Overriding Idle; Might be necessary might
not be.
end;
if Abort or AbortIdle then DoAbortCleanup(AbortIdle)
//DoAbortCleanup would naturally remove the pending AbortQuit
semaphore if AbortIdle is False
//Mmeaning that the abort procedure was called, because
TM.AbortThread(Index) would naturally flag
//the semaphore and the Threads.Abort() proc, to catch either an
IDLE loop, or the Abort flag directly.
//if the Abort Flag was directly set, the AbortIdle would remain
false, but if the Idle thread was flagged
//and an abort semapore was sent, AbortIdle would be true.

else if UserIdle then ProcessUserObject(False); //ignores the
UserSemaphore since it has already been caught

Result:=Abort;

The cool part (i think) is that TimeOut Thread could be sceduled with
similar event processing, so ReleaseSemaphore( handle, 2) could cause the
timeout thread to flag a message was sent to a specific thread, and change
listenfor handles based on priority. Say Initially the semaphore 'Call to
the thread' would be set to 2, (one for the timeout, one for the thread).
The timeout, upon receiving that call, would jump to a different set of
handles including the specific Thread's 'CallBack' semaphore, not its 'call
to' semaphore, and if a timeout occurred without receiving that callback, an
error would flag, ie hung thread, otherwise, once the callback semaphore was
received the timeout thread, would revert back to its initial 'call to'
thread wait state.

The intermixing of semaphore event handling would be complex, I agree, but i
*THINK* the model is sound. (I might need to put the TM in its own thread
and communicate from it to the VCL with messages, since i worry how much the
timeout thread will interfere with the VCL always communicating back to the
TM, but check me on the internal logic of this design model first.)

> You need more beer. Usually works for me <g>

Oh, you BET I DO!! *chuckle*, and possibly a whiskey chaser. *smile*

> lInitialCount
>
> Specifies an initial count for the semaphore object. This value must be
> greater than *or equal to* zero

yea...*chuckle* literacy...who'd a thunk it? *whoops*

And btw, this thread info and that WMQ information is priceless. You guys
have been a blessing in helping me understand this so i can start taking my
concept and convert it to reality.

--

Jaeden "Sifo Dyas" al'Raec Ruiner

aka Fluffy
http://www.wayoftheleaf.net/


Martin James

unread,
Sep 4, 2006, 1:13:23 PM9/4/06
to
Jaeden "Sifo Dyas" al'Raec Ruiner wrote:
> Well then it is settled. The last time someone told me i couldn't do
> something...

I would never say such a thing. Anyone saying that something cannot be
done is often interrupted by someone else who is already doing it <g>

>
> So when I get this done, we will all go round-robin on it to make sure it is
> concise enough to support the local community.
>

OK, maybee we should ask them for a requirement spec?

Rgds,
Martin

Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 4, 2006, 4:18:04 PM9/4/06
to

"Martin James" <nos...@dial.pipex.com> wrote in message
news:44fc5e77$1...@newsgroups.borland.com...

>> So when I get this done, we will all go round-robin on it to make sure it
>> is concise enough to support the local community.
>
> OK, maybee we should ask them for a requirement spec?

Hrm...Not yet, as I know right now I'll only be handle Win32, which means
that Linux is out of the question for the moment....
besides, if I start trying to meet all the communities needs...it'll never
get done.

--

Jaeden "Sifo Dyas" al'Raec Ruiner

aka Fluffy
http://www.wayoftheleaf.net/

There was a man who once talked to me about scope creep, but the filibuster
never ceased...


Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 9, 2006, 2:06:31 PM9/9/06
to
I figure since this is a continuation of a similar topic to just keep in all
within this thread, no pun intended. I have two questions about threads, or
near enough.

First CriticalSections:

I understand the purpose of critical sections, but not exactly the flow.
For example say I have a list of pointers contained in a class, and there
are methods to manipulate that list. Like TThreadList, in the Add() method,
I would lock the list, but what about X:=List.Items[2]^.Value? When i want
to reference the list for reading what's the rule there?
Basically if one thread is adding to the list, the list is in a critical
section lock out, but, what if another method I use that references the list
doesn't contain a critical section acquisition? Something like this:

List.Add()
EnterCriticalSection;
try
DoListAdd(Item);
finally
LeaveCriticalSection
end;


List.GetItem
if Index<Count then
Result:=FItems[Index];


Okay, Now, If one thread calls Add(), and at the same time, another thread
called GetItem(), would GetItem be stalled via the critical section? I
think it wouln't, but that says to me EVERY access point to shared data must
be protected by CS's, even for reading, not just writing.
Also, if I'm working with a list of Pointers, and one thread has a Pointer
address from the list, the list may be protected, but the pointer memory is
not, correct? So if two threads were to share the same list information,
they have to protect the underlying data so that:
Thread1
P:=List.GetItem(1);
P^.Value:=2;

Thread2
P:=List.GetItem(1);
P^.Value:=5;

These two thread interactions don't overlap. Am I right in this
understanding?


Second TThread.Synchronize:

I have spent a lot of time looking through the code of Classes.Pas | TThread
so that I can understand exactly what Synchronize does. The current problem
is that it accesses a lot of globals in the process, and was wondering if
anyone could narrow down why they are doing the things they are doing in
that aspect of threads.
WakeMainThread - I've never used this before, and yet here it seems
like I should have been, what's it for?
SignalSyncEvent - Is there a loop somewhere in the main thread
that is listening for this event? The only time I see it even being looked
for is in CheckSynchronize, which is only called from WaitFor.
Synchronize(Psynchronizerecord) - Some of this just doesn't quite make
sense as the whole package. For a Queue'd event it acts one way, and for a
straight synchronize it acts another. This is fine, and makes sense.
However, the only time throughout this rather important method for thread
managemetn, that it even ever calls the method you wanted to synchronize, is
if GetCurrentThreadID = MainThreadID. So, how does it get to the
mainthread? if the current thread isn't the main thread, then it signals a
syncevent, but where does it look for the event to be signaled?
CheckSynchronize does, but as I said, I only found it being used in
TThread.WaitFor.
Obviously, i'm a little confused as to what they are doing, so if anyone
could clear these details up for me it would be awesome. Thanks

--

Jaeden "Sifo Dyas" al'Raec Ruiner
aka Fluffy

http://www.wayoftheleaf.net/


Rob Kennedy

unread,
Sep 9, 2006, 4:31:26 PM9/9/06
to
Jaeden "Sifo Dyas" al'Raec Ruiner wrote:
> I figure since this is a continuation of a similar topic to just keep in all
> within this thread, no pun intended. I have two questions about threads, or
> near enough.
>
> First CriticalSections:
>
> I understand the purpose of critical sections, but not exactly the flow.
> For example say I have a list of pointers contained in a class, and there
> are methods to manipulate that list. Like TThreadList, in the Add() method,
> I would lock the list, but what about X:=List.Items[2]^.Value? When i want
> to reference the list for reading what's the rule there?

You want to prevent anyone from writing to that list while you're
reading it. Note that "writing" is very broad. It includes the following
actions: Add, Insert, SetItem, Clear, Delete.

> Basically if one thread is adding to the list, the list is in a critical
> section lock out, but, what if another method I use that references the list
> doesn't contain a critical section acquisition? Something like this:
>
> List.Add()
> EnterCriticalSection;
> try
> DoListAdd(Item);
> finally
> LeaveCriticalSection
> end;
>
>
> List.GetItem
> if Index<Count then
> Result:=FItems[Index];
>
>
> Okay, Now, If one thread calls Add(), and at the same time, another thread
> called GetItem(), would GetItem be stalled via the critical section?

Since GetItem never even mentions the critical section, it cannot be
stalled by it.

If *any* of the methods mentioned above could ever possibly get called
while GetItem is running, then GetItem must use the critical section as
well. This is true even for Add, which you might at first expect to be
OK -- you're reading from a different part of the array than the part
that Add is modifying. But Add might need to re-allocate memory, so
between the point where GetItem loads the array address in FItems and
the time it indexes into that memory, the data might not be at the same
address anymore.

> I
> think it wouln't, but that says to me EVERY access point to shared data must
> be protected by CS's, even for reading, not just writing.

Correct. That's a requirement that the programmer must fulfill, not the
critical-section implementation. The critical section has no information
about what memory it's protecting.

> Also, if I'm working with a list of Pointers, and one thread has a Pointer
> address from the list, the list may be protected, but the pointer memory is
> not, correct? So if two threads were to share the same list information,
> they have to protect the underlying data so that:
> Thread1
> P:=List.GetItem(1);
> P^.Value:=2;
>
> Thread2
> P:=List.GetItem(1);
> P^.Value:=5;
>
> These two thread interactions don't overlap. Am I right in this
> understanding?

If there is no other thread running that might modify the value stored
in the List variable or the contents of the object it references, then
the value of P in both threads will be the same.

As I understand it, writing a 32-bit value to 32-bit aligned memory is
an atomic operation. That means that the value of P^.Value will be
either 2 or 5, whether you protect P^.Value with a critical section or
not. You have a race condition, but race conditions are OK as long as it
doesn't matter which thread wins.

> Second TThread.Synchronize:
>
> I have spent a lot of time looking through the code of Classes.Pas | TThread
> so that I can understand exactly what Synchronize does. The current problem
> is that it accesses a lot of globals in the process, and was wondering if
> anyone could narrow down why they are doing the things they are doing in
> that aspect of threads.
> WakeMainThread - I've never used this before, and yet here it seems
> like I should have been, what's it for?

When Borland redid TThread, it made TThread independent of Forms unit.
Previously, TThread would always post messages to Application,MainForm,
which was inappropriate for programs that didn't have a main form, such
as console programs.

WakeMainThread is a callback function. TApplication assigns that
variable in its constructor (via HookSynchronizeWakeup). When you call
TThread.Synchronize, TThread needs to know how to tell the main thread
that there is work to do. It calls WakeMainThread to do that.
TApplication tells TThread how to wake it by assigning the
WakeMainThread variable. TApplication's wake-up function simply posts a
wm_Null message to itself. That forces a message onto the main thread's
message queue, so it the main thread was sleeping, waiting for a
message, it will wake up in response to the wm_Null. Once it wakes up,
it will notice the new work item in the synchronization queue, which
TThread put there before calling WakeMainThread.

A console program might have some other way of notifying the main thread
that there is work to do.

> SignalSyncEvent - Is there a loop somewhere in the main thread
> that is listening for this event? The only time I see it even being looked
> for is in CheckSynchronize, which is only called from WaitFor.

SignalSyncEvent is another way of telling the main thread that there's
work to do.

If TApplication used MsgWaitForMultipleObjects, it probably wouldn't
need WakeMainThread. TThread signals SyncEvent after it puts a work item
in the queue, so any thread waiting on that event would be notified.
Using MsgWaitForMultipleObjects would allow TApplication to wait for
SyncEvent as well as the messages it currently processes with
WaitMessage and PeekMessage.

TApplication calls CheckSynchronize when it receives a wm_Null event
(which, as we saw earlier, gets posted by WakeMainThread). That's how
TThread.Synchronize manages to tell the main thread to execute a given
procedure.

> Synchronize(Psynchronizerecord) - Some of this just doesn't quite make
> sense as the whole package. For a Queue'd event it acts one way, and for a
> straight synchronize it acts another. This is fine, and makes sense.
> However, the only time throughout this rather important method for thread
> managemetn, that it even ever calls the method you wanted to synchronize, is
> if GetCurrentThreadID = MainThreadID. So, how does it get to the
> mainthread?

Take a closer look at CheckSynchronize. That's where methods get executed.

> if the current thread isn't the main thread, then it signals a
> syncevent, but where does it look for the event to be signaled?
> CheckSynchronize does, but as I said, I only found it being used in
> TThread.WaitFor.

Don't limit your studies to Classes.pas. Look in Forms.pas, too.

--
Rob

Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 10, 2006, 8:50:56 PM9/10/06
to
"Rob Kennedy" <m...@privacy.net> wrote in message
news:4503249b$1...@newsgroups.borland.com...

>You have a race condition, but race conditions are OK as long as it doesn't
>matter which thread wins.

So As near as I can figure, if at any point the programmer is sharing data
between two threads, that data "should" be protected, unless the data is
obviously read-only, at which point it doesn't matter what thread's are
"reading" the information, as long as none of them change it. If any thread
is going to Update or Alter data in a "shared buffer space" then all access
points to that buffer must be protected. Given the examble of a global list
of data, if the VCL thread FNF (fire and forget) creates the list, and all
subsequent threads are only "reading the list" as some sort of input
information, then no CS's are necessary. But in the same circumstance if
one thread might add/delete/change list entries while processing, then ALL
access points should be gaurded, not just the Add/Delete/Change ones,
because of the "race condition" effect.

Okay. If i'm right on this that makes sense. Thanks

>> Second TThread.Synchronize:
>> WakeMainThread

So currently TApplication only uses WakeMainThread, which I understand how
it works now.
And thus:

>> SignalSyncEvent
Exists to Sync up the CheckSynchronize call from within the Main thread, and
other event based synchronization. The Mainthread calls to
CheckSynchronize, but CheckSyncronize will only "wait" for the event if it
is given a "timeout", otherwise, it just resets the event (elminates it from
signaled state).

> If TApplication used MsgWaitForMultipleObjects, it probably wouldn't need
> WakeMainThread. TThread signals SyncEvent after it puts a work item in the
> queue, so any thread waiting on that event would be notified.

However, looking at how this "syncronization" works, it does two basic
things:
Queued Methods
Are sent to the VCL thread the same as Synchronized Methods, but
they are not "Waited" upon.
Synchronized Methods
Are sent to the VCL thread, but after sending them, the Synchronize
method enters a "WaitForSingleObject(SyncProcPtr.Signal, INFINITE);" loop
waiting for the method to be processed and the event to be signaled by the
VCL thread, in effect suspending the current thread until the VCL can handle
a specific item.

Given this set up, is it not possible to design the Synchronized And/Or
Queued methods to occur between any of multiple threads? Not Just the VCL
thread? (naturally it would require some writing, but it seems logical that
the same code design could be mimicked to handle thread to thread
syncrhonization, instead of always requiring it to be handled by the VCL).

> Don't limit your studies to Classes.pas. Look in Forms.pas, too.

Yea, I tend to fall into 2-dimensional thinking from time to time, sorry
'bout that. *chuckle*

Thanks for the pointers, i've got my mind going off on countless new
tangents. *cheezgyrin*

--

Jaeden "Sifo Dyas" al'Raec Ruiner

aka Fluffy
http://www.wayoftheleaf.net/


Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 11, 2006, 12:37:52 AM9/11/06
to
I'm a little fuzzy about Interlocked* functions
Increment
Decrement
Exchange

The help says that they do "operation" on the Parameter in such a way that
other threads cannot access until the operation is finished. but in
SysUtils.pas it's just a bunch of assembly commands, very simple ones at
that. The Help also says that the sysutils versions are for linux only, and
the winapi functions take precedence in Windows.

Could someone clarify exactly how these work, and how I can determine what
their return values are? The Help is not explicit about the return value of
the operations, and I see many functions that base their boolean return
values off of the return values of Interlocked* functions.

Thanks
--

Jaeden "Sifo Dyas" al'Raec Ruiner
aka Fluffy

http://www.wayoftheleaf.net/


Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 11, 2006, 1:51:00 AM9/11/06
to
I have found my solution...*chuckle*

With all the critical section stuff, i mised the true joy of exploration of
code, and suddenly i somehow stumbled upon the
TMultiReadExclusiveWriteSynchronizyer class. This is beautiful thing, that
will make my life ten times easier. It took me a moment to understand the
intricacies of the Interlocked* functions, but I eventually mapped them out,
and understood how this class operates. For all intents and purposes, I
cannot see how the TThreadList is so focused upon the CriticalSection lock
of the list itself. Given my described HashTable list classes from before,
I can easily utilize the MREWS class to allow as many reads as possible to
the list, but when a write call is made to lock out the reads until the
write is completed. This makes much more thread-safe logic when it comes to
large lists of shared data, especially when they'll be read from multiple
threads.

Just an fyi on what I've discovered, so that if anyone reading this
post-thread can check it out on their own for examination of other ways to
be thread safe with out the locking totality of critical sections.

Regards
--

Jaeden "Sifo Dyas" al'Raec Ruiner

aka Fluffy
http://www.wayoftheleaf.net/


"Rob Kennedy" <m...@privacy.net> wrote in message
news:4503249b$1...@newsgroups.borland.com...

Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 13, 2006, 5:52:12 AM9/13/06
to
Just a Quickie on the TMultiReadExclusiveWriteSynchronizer:

When you call BeginRead, it increases that current Thread's
"RecursionCount". If that count goes from 0 to 1, it marks the Sentinal
validation flag as a thread has opened a read state on the data, you can
recurse other BeginReads subsequently after that, but they do not change the
Sentinal validation flag. When you call EndThread, the RecursionCount is
reduced by 1, and when it is reduced to 0 it removes the thread from the
list, and returns its readlock from the Sentinal Validation flag.

Thus, my question is:

Property Item[Index]:
BeginRead
Result:=ItemLists[Index];

DOES NOT CALL EndRead. I reserve this for External usage. Thus a
programmer (myself) can access the Data in the list somewhere else, and when
I'm done with that data, I call List.Unlock (which subsequently calls the
Endread) to say that I'm done reading that individual pointer/object from
the list. This is to protect the data in the list as well as the list
itself, so I can do:

P:=List.Item[Index];
St:=P^.Name;
List.Unlock

And if another thread were to try and write to the pointer that P referes to
while I was accessing the Name field of the record, it will wait until I
unlock the list.

But:

function loop;
BeginRead;
while true {
X:=Item[I]
}
EndRead;

In this circumstance, the same thread calls BeginRead before the loop is
executed, so the loop can complete without being blocked by another thread
trying to "write" new data to the list. However, when I access the Item[]
Property, the TMultiReadExclusiveWriteSynchronizer class will increase the
Thread's RecursionCount. This says to me that I would have to call EndRead
after each access to the Item[] property so when the function loop exits,
the list is at its previous blocked/unblocked state. (naturally if other
read operations are going on that's fine, but i want this to exit cleanly,
no extraneous RecursionCount.) Am I right in that deduction?

Jaeden "Sifo Dyas" al'Raec Ruiner

unread,
Sep 15, 2006, 10:34:16 AM9/15/06
to
APCs...

yea, this seems kinda cool, and a way to set up Method/procedure calls
between threads. But...I got some questions.

naturally, i've looked into the Synchronize() method of TThread, which
basically does the following:

Thread
-Create SyncRec pointer (with member pointing to the method to be
Syncrhonrized)
-Adds SyncRec to global SyncList
-Signals MainThread (via the PostMessage(WM_NULL)
-Wait for SyncRec.Event Signal from Main Thread
MainThread
-Receives WM_NULL
-Calls CheckSyncrhonize
-Pops Item from SyncList and Runs SyncRec.Method
-Signals SyncRec.Event

Given this model, I realized I could do one better, or at least it seemed
so. By creating a Per-Thread Queue, and the StateMachine/TimeOut thread, I
could do something like this, noting that Thread1 and Thread2 are variable,
and determined run-time:
Thread1
-Create SyncRec pointer with member pointer to SyncMethod
-Set Calling Thread ThreadID. This is the Thread that will Execute
the SyncMethod (ie Thread2)
-Set SyncSemaphore Handle
-Add SyncRec to Thread1.Queue
-Signal ItemInQueue Semaphore
-If Synchronize
WaitFor SyncSemaphore Handle

TimeOut
-Receive ItemInQueue Semaphore
-Pop Thread1.Queue -> SyncRec
-Push SyncRec into Tread2.Queue
-Set Thread2.ItemInQueue Semaphore

Thread2
-Receive Thread2.ItemInQueue Semaphore
-Pop Thread2.Queue -> SyncRec
-Execute SyncRec.SyncMethod
-if Synchronize
Signal SyncSemaphore

With this, I can have 3 or 4 threads that may need to synchronize method
calls with each other, for whatever purposes (i'm just thinking possiblities
at the moment, not necessarily specifics), and can even queue up
Asynchronous calls, by not setting the "synchronize" boolean. Basically
similar to the QueuedEvent of TThread, which does not wait for a return
signal from the synchronized method, it just continues onward.

Looking into the QueueUserAPC() API call, seems to say that I could instead
grab the Handle to Thread that I wish to Asynchronously call a method, and
have a different thread queue up a APC to that handle, instead of waiting on
a Semaphore Queue. Is this better/worse, or are APCs primarily used for IO
routines, not extraneous method thread method calls?

This leads me to this statement from before:


> The semaphore queue is however, very simple to code up and to understand
> how it works. For 'thread-newbies', this is better than a much more
> complex, but difficult-to-understand, high-performance queue. It's faster
> than a Windows message queue anyway, at least for small numbers of queued
> objects.


What is an example of a more complex/high-performance queue? Just thinking
out loud and trying to understand thread Queue's, i've got a object model
that seems to be very effective for my end result, but I do want it as
streamlined as possible. Thus if using a Push/Pop style queue is slow (even
if it is not based on TObjectQueue.TList, but my own hash list algorithm
which uses TMultiReadExcluseWriteSyncrhonizer), what would be faster and
more high-performance. My idea at the moment, is utilizing a
StateMachine/Timeout thread to manage communication with other threads
utilizing semaphores. The SM/T is always in a WaitState, while individual
threads POLL (tragic but we discussed that) for a boolean before entering
their own WaitState. This means that the individual threads, though rare,
will occasionally receive semaphores from the TimeOut thread, after their
"Event" boolean is flagged and polled to true. Otherwise, they can signal
semaphores to the SM/T at any moment which will alert the VCL or other event
driven whatnot's dependent upon the worker threads and the semaphore
signaled. Sometimes this may involve the Queueing of an object. I'm
beginning to question some of my design. I appear to be using Semaphores
backwards, as a "SignalCount" instead of a "ReleaseCount". Meaning, that
All my Semaphores begin at 0, and when I flag an event from the main thread
(should it need to communicate with a child thread) I ReleaseCount(2). The
StateMaching/TimeOut thread listens to ALL semaphores, which reduces the
ReleaseCount by 1, and the Individual Thread which i'm signalling also
listens for the specific semaphore and further releases it down to 0, and
performs whatever the signaled event was telling it to perform. The TimeOut
thread having heard the semphore signal, goes into a new WaitState for a all
semaphores, except the Signaled Semaphore is replaced by its specifc
"eventHandled" semaphore, which is set by the thread, when it is done
processing the Original Semaphore event.
I did it this way so that I could do event based process queues. Such as,
Tell a Thread to process some buffer data, but I won't tell that thread to
process more, until it is finished with the first buffer. Meanwhile, I can
still tell other threads to process different buffers, and when Thread1
comes back with 'data processed' the timeout thread lets the main thread
know, and the next buffer can be queued up. Sort of a multi-worker-thread
system, where each thread has its own type of data to process, and the
timeout thread synchronizes the lot.

I've often been guilty of looking at what *could* be done, instead how it
*should* be done, and i'm wondering if my approach is flawed.
Is there a smarter way to go about this?
--

Jaeden "Sifo Dyas" al'Raec Ruiner

aka Fluffy
http://www.wayoftheleaf.net/


0 new messages