Re: Multi Threading Options



class CAwAvatar
{
int x, y, z, messages_to, session;

void SendMsg(LPCTSTR text)
{
aw_whisper(session, text) << External C API
messages_to++;
}

void Kill(LPCTSTR reason)
{
FOR_EACH_OF_AVATARS << Linked List Enumerator
pUser->SendMsg(reason);
END_FOR_EACH << aka '}'
}
}

class CAwAvatars
{
CTypedPtrList<CPtrList, CAwAvatar*> vCol;

CAwAvatar* create( ); << adds new user to vCol
void Delete(CAwAvatar*) << removes from vCol
CAwAvatar* find(int session); << loops through, finds session match
}

extern CAwAvatars avatars; << defined globally in stdafx

[could be any thread #2]
void some_externally_triggered_func(int session, int x, int y, int z, [...])
{
CAwAvatar* pUser = avatars.find(session);
if (pUser)
{
pUser->x = x;
pUser->y = y;
[...]
}
}

[could be any thread except #2]
void another_external_func(int session, LPCTSTR msg)
{
CAwAvatar* pUser = avatars.find(session);
if (!strcmp(msg, "bad word"))
pUser->Kill("User said something... regrettable");
}

[ --- thread #2 --- ]
void MyDlg::OnTimer( )
{
FOR_EACH_OF_AVATARS
DoDrawingOf(pUser);
END_FOR_EACH
}

void MyDlg::DoDrawingOf(CAwAvatar* pUser)
{
>> rather large drawing code here based on variables in pUser <<
>> also some methods of pUser may be called here that change its data <<
}

Thats the bread and butter of it, of course there are over 100 methods and
properties associated with the AwAvatar class, all are set directly via
pUser->x = x and the like (somehow setting and getting vars through
functions sounds like a good way to add extra overhead, is this going to
come back and bite me in the back side now?)

So really, I dont want CAwAvatar to be added or removed while I am looping
through them, and I do not want the AwAvatar object to be changed by
anything else while I am actually reading from it, but while I am reading
from it I need to call functions inside it that change things - even if
those variables are shielded from obvious view by the class

So in summary:

- Looping and Adding to linked list must be mutally exclusive
- Any data from the avatar should be readable at any time, but should wait
until all data has finished being updated;
- Any thread needs to be able to call methods in the avatar class without
fear of half-way-changing other things in it for something else thats
reading.

I hope that allows you to suggest anything else you may be able to think of.

--
- Mark Randall
http://zetech.swehli.com

"Joseph M. Newcomer" <newcomer@xxxxxxxxxxxx> wrote in message
news:76ir91ph8nf8ur627rgc412mt24uln25rg@xxxxxxxxxx
>I concur. Your original description was not sufficient to deduce the
>desired behavior.
> You do not need to synchronize the entire structure. We used this
> technique back in 1975
> to avoid deadlock in a huge multiprocessor system. Each data structure had
> a "custodian"
> thread (in those days, it meant a custodian process with shared memory),
> so what would
> happen is that, in the context of your app, you sent either update
> requests (which change
> the structure) or paint requests (which update the screen...and I don't
> mean WM_PAINT
> messages, I mean a user-defined request). If you use
> PostMessage/PostThreadMessage, then
> the requests are queued up. You could also choose to force a paint if no
> messages came
> within some delta-T or after every N structure udpate requests. I've used
> similar
> techniques to handle various kinds of asynchronous queueing. You can apply
> all sorts of
> techniques to control the flow and updating frequency. In one case, I did
> the equivalent
> of
> if(!PeekMessage(...))
> if(GetQueuedCompletionStatus(...,0))
> MyProcessQueuedRequest(...);
>
> which would, if there was no message pending, dequeue from an I/O
> completion port. This
> let me have WM_TIMER messages in the queue. In another case, I would do
> for(i=0; i < n;
> i++) to dequeue the first ten messages in the completion queue (see my
> essay on the use of
> I/O Completion Ports on my MVP Tips site) that meant that there were no
> long delays on
> user interaction but if nothing was happening we would try to flush the
> pending requests.
> Kept the mouse alive in the main GUI thread while allowing floods of
> asynchronous updates
> to the display data.
> joe
>
> On Wed, 01 Jun 2005 07:32:16 -0500, "Scott McPhillips [MVP]"
> <org-dot-mvps-at-scottmcp>
> wrote:
>
>>Mark Randall wrote:
>>> My problem is that I want to run a pretty hefty drawing routine on the
>>> other
>>> thread - I really want to cause thread 2 to wait for data to finish
>>> being
>>> written before it starts drawing the next image, and cause thread 2 to
>>> tell
>>> thread one it can update again once it has finished drawing.
>>
>>In code such as this, where the threads are to "voluntarily" take turns,
>>you have a third option. In addition to a mutex or crictical section,
>>you can consider the use of an interthread message. When thread 1
>>finishes updating the list it can post a message to thread 2 requesting
>>a paint. And vice versa. Use PostMessage to a GUI thread,
>>PostThreadMessage to a non-GUI thread. Example here:
>>http://www.mvps.org/vcfaq/mfc/index.htm
>
> Joseph M. Newcomer [MVP]
> email: newcomer@xxxxxxxxxxxx
> Web: http://www.flounder.com
> MVP Tips: http://www.flounder.com/mvp_tips.htm


.


Loading