🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
5 messages
5 total messages Started by Mike Collins Wed, 30 Apr 2008 01:21
Conceptual design question...
#322
Author: Mike Collins
Date: Wed, 30 Apr 2008 01:21
21 lines
1741 bytes
Hi guys,

I'm just starting the re-design of a product suit that we have. I have a 
conceptual design quesiton and i'm looking for some pointers from the 
*experts*.

Basically i have a Service (non VCL/TService) that has registered to be 
informed when a user logs on or off.  I then have four other TThreads that 
are responcible for carrying out indipendant tasks such as hardware polling 
etc.

I'm looking for a suitably robust and streamline method of informing my 
child threads of the users logon / off.  My current demo uses 
PostThreadMessage but i was wondering if there is a better method of 
Inter-Thread Communication.  This system works ok but i've managed to spoof 
the messages from a rouge service so i was looking for a more secure system 
of ITC.

Any ideas or pointers would be gratefully recieved,

Mike C 
Re: Conceptual design question...
#327
Author: Bob Gonder
Date: Wed, 30 Apr 2008 14:32
36 lines
2101 bytes
Mike Collins wrote:

>i'm looking for some pointers from the *experts*.

Do I qualify?

>i have a Service that is informed when a user logs on or off.
> I then have four other TThreads that are hardware polling 
>
>I'm looking for a suitably robust and streamline method of informing my 
>child threads of the users logon / off.  My current demo uses 
>PostThreadMessage but i was wondering if there is a better method of 
>Inter-Thread Communication.  This system works ok but i've managed to spoof 
>the messages from a rouge service so i was looking for a more secure system 
>of ITC.

I think for the highest security, you go with memory-only transfers.
If the threads are already polling, then simply extend the poll to
a global variable, or a public TThread variable.

	bool	ThreadOneITC = false;
	bool	ThreadTwoITC = false;

MessageHandler()
{
	case logon:
		ITCdata = LOGON;
		ThreadOneITC = true;
		ThreadTwoITC = true;
		break;

If ITC can occur faster than the threads poll, then you
would want to FIFO the data, and have the thread re-poll
before sleeping.

For a simple bool flag, locking shouldn't be an issue.
Re: Conceptual design question...
#333
Author: Bob Gonder
Date: Thu, 01 May 2008 16:29
10 lines
1424 bytes
Bob Gonder wrote:

>I think for the highest security, you go with memory-only transfers.
>If the threads are already polling, then simply extend the poll to
>a global variable, or a public TThread variable.

Additionally, if you want to continue with messages,
set a memory sentinal before signaling.
The recipient checks memory and ignores the signal if false.
The idea being that external spoofers won't be setting your memory.
Re: Conceptual design question...
#335
Author: Mike Collins
Date: Fri, 02 May 2008 02:58
12 lines
1362 bytes
hay bob,

thanks for the reply - can you expand a bit - what do you mean by a memory 
sentinal - are you just taking about some sort of global variable that 
indicates that the messages were sent internally?  What is the situation 
with ensuring thread access safety?

Mike

"Bob Gonder" <notbg@notmindspring.invalid> wrote in message 
news:8nrj14576vnl3cf62pgbgcgvc4a7vho0fg@4ax.com...
> Bob Gonder wrote:
Re: Conceptual design question...
#337
Author: Bob Gonder
Date: Fri, 02 May 2008 15:15
118 lines
4344 bytes
Mike Collins wrote:

>thanks for the reply - can you expand a bit - what do you mean by a memory 
>sentinal - are you just taking about some sort of global variable that 
>indicates that the messages were sent internally?

Yes.

> What is the situation with ensuring thread access safety?

Minor issue with polling (see last paragraph).
No issue with messages (in your case).

You would want to have one variable per thread
so each thread can be sure that you really
called it, and not one of the others.

The variable could be global or thread:

If the main thread is calling, then it has
access to the TThreads and can write to a
public bool that you add to the class.

class MyThread	public TThread
{
public
	bool	Sentinal;
	/* other stuff */
	/* don't forget to construct Sentinal */
}
	MyThread *MyThreads[4];

   case LOGIN:
	for( int i=0; i<4; ++i )
	{
		MyThreads[ i ]->Sentinal = true;
		Signal( MyThreads[ i ] );
	};

Or a global Sentinal[4] where each thread
knows it's number (can be passed via
CreateThread lpParameter).

	bool	Sentinal[4] = {false};
	TThread *MyThreads[4];

   case LOGIN:
	for( int i=0; i<4; ++i )
	{
		Sentinal[ i ] = true;
		Signal( MyThreads[ i ] );
	};

The thread then gets the message and checks
this->Sentinal. If true, set to false and process.
If false, go back to sleep.

	case MySignal:
		if( Sentinal )
		{	Sentinal = false; //minimize race
			ProcessLogin();
		};
		break;
 - or -
	case MySignal:
		if( Sentinal[ MyNumber ] )
		{	Sentinal[ MyNumber ] = false; //minimize race
			ProcessLogin();
		};
		break;

The only issue is if main can try to signal the
same thread before the thread has checked/reset
the flag. There could be a race on the reset-set
and if the race looses, the thread ignores
the second legit message.

Seems doubtfull that user logins would happen
fast enough to cause a race.

In other situations, where you might get
race conditions, you would want to replace
the bool with an int and do locked incriment/decriment.
	InterlockedIncrement()
	InterlockedDecrement()


  -- Cascade Messages
And, finally, there is cascade.
Main sets global flag.
Main wakes up thread 1.
Thread 1 ensures legit wakeup and wakes up thread 2.
Thread 2 ensures legit wakeup and wakes up thread 3.
Thread 3 ensures legit wakeup and wakes up thread 4.
Thread 4 ensures legit wakeup and resets global flag.

This has a much larger race window, but serializes
the processing.


  -- Polling Race
If you decide to add a sentinal check to your polling....

Main writes "true" whenever it wants.
Thread is only reading (polling).

If there is a race, the thread will read either true or false.
If false, then it hits next cycle, otherwise it hits this time.

Main will finish the write before it can be swapped out.
The thread should therefore only need to wait a few
instructions (multi-cpu only, single-cpu is a non-issue)
before it is safe to reset the bool. The testing of
the bool after reading it should be adequate delay.

Overflow occures only if main cycles "true" faster
than the threads can poll. If that can happen,
then you switch to a locked counter.
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads