Article View: borland.public.cppbuilder.internet.socket
Article #1326Re: Passing info between threads
From: Lesley Anne
Date: Wed, 21 Feb 2007 22:00
Date: Wed, 21 Feb 2007 22:00
113 lines
5537 bytes
5537 bytes
"Bob Gonder" <notbg@notmindspring.invalid> wrote in message
news:vj8nt2llf7deda6ioqggci4rds885qcmne@4ax.com...
>
> I see that you are also concerned about the Thread falling behind
> the application, and getting messages out of order. One way out
> is to add a ring buffer.
> The application stuffs data into the head of the ring, then tells
> the thread that new data is available. (Once again, the data is
> now in an escrow buffer, so the application data can change or
> "go away".) The thread takes data off the tail of the ring, and
> sends it.
This sounds like the queue approach that Paul was talking about. I've
looked at TThreadList, and think I can use that for a queue of commands I
want the thread to process. Here's how that looks so far:
In the header, I defined a structure to hold commands and their parameters.
It looks like this:
enum TSctpCommand { scmdConnect, scmdShutDown, scmdSend };
typedef struct SctpCmdParamRec {
TSctpCommand Command;
unsigned char MsgBuffer[MAX_BUFFER_LENGTH];
int MsgLen;
unsigned int AssocID;
unsigned char DestAddr[SCTP_MAX_IP_LEN];
unsigned short DestPort;
int SiteIndex;
} TSctpCmdParams;
Then I have:
TThreadList* SctpCommandList;
defined globally in my main unit (and extern in the thread unit), which gets
instantiated with 'new' in my main form's constructor.
Whenever the main form wants to initiate something in the SCTP thread, it
does something like this:
// --------------------------------------------------------------
void __fastcall TForm1::Send(String Message, int Site)
{
if (sctpThread) {
TSctpCmdParams *SctpCmdParams = new TSctpCmdParams;
SctpCmdParams->Command = scmdSend;
SctpCmdParams->AssocID = associationID[Site];
strcpy(SctpCmdParams->MsgBuffer, Message.c_str());
SctpCmdParams->MsgLen = Message.Length();
SctpCommandList->Add(SctpCmdParams);
sctpThread->HandleCommand();
} else
Memo1->Lines->Add("ERROR: sctp Thread does not exist");
}
// --------------------------------------------------------------
(The Connect and Disconnect functions in the main form look almost identical
to this except that they set different members of SctpCmdParams.)
In the SCTP Thread unit, anything coming from the VCL Thread will enter via
this function:
// --------------------------------------------------------------
void TsctpThread::HandleCommand(void)
{
TList* CmdList;
TSctpCmdParams* SctpCmdParams = NULL;
CmdList = SctpCommandList->LockList();
if (CmdList->Count > 0) {
SctpCmdParams = (TSctpCmdParams*)CmdList->First();
CmdList->Remove(SctpCmdParams);
}
SctpCommandList->UnlockList();
if (SctpCmdParams) {
switch (SctpCmdParams->Command) {
case scmdConnect:
Connect(SctpCmdParams->DestAddr,
SctpCmdParams->DestPort,
SctpCmdParams->SiteIndex);
break;
case scmdShutDown:
ShutDown(SctpCmdParams->AssocID);
break;
case scmdSend:
Send(SctpCmdParams->MsgBuffer,
SctpCmdParams->MsgLen,
SctpCmdParams->AssocID);
break;
}
delete SctpCmdParams;
}
// should probably add an 'else' here for an error message
}
// --------------------------------------------------------------
This does have the VCL thread allocating structures which the SCTP thread
eventually deletes, but I think that should work so long as the TThreadList
buffers the two accesses adequately. The VCL thread never looks at the
SctpCmdParams it created again after putting it on the TThreadList, and the
SCTP thread uses and deletes it after getting it off of that list.
There is a bit of overhead in my TSctpCmdParams structure, because space for
all possible parameters gets allocated each time, even though only the
parameters relevant to that particular command get used. I'm not too
worried about that, though, because by far the largest piece of it is the
MsgBuffer, and that's what I'm going to need the most often anyway. (The
Send command is the one that can get called a lot. Connect and ShutDown
commands, where that MsgBuffer is unnecessary, are infrequent events.)
Technical Details
Message-ID:
<45dcc0cb@newsgroups.borland.com>Path:
arc1-ca.pugleaf.net!g2news2.google.com!news4.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mailReferences:
<45d9e83a$1@newsgroups.borland.com> <h21mt21bg7maqp25d2lqkr9b1iet0eu3g6@4ax.com> <45db2486$1@newsgroups.borland.com> <vj8nt2llf7deda6ioqggci4rds885qcmne@4ax.com>Show Full Headers
Complete Article Headers
X-Google-Thread: 11508e,234a9a04e64155b0 X-Google-Attributes: gid11508e,public X-Google-Language: ENGLISH,ASCII-7-bit From: "Lesley Anne" <mspfila (dash) brl (at) yahoo (dot) com> Newsgroups: borland.public.cppbuilder.internet.socket References: <45d9e83a$1@newsgroups.borland.com> <h21mt21bg7maqp25d2lqkr9b1iet0eu3g6@4ax.com> <45db2486$1@newsgroups.borland.com> <vj8nt2llf7deda6ioqggci4rds885qcmne@4ax.com> Subject: Re: Passing info between threads Date: Wed, 21 Feb 2007 17:00:17 -0500 Lines: 115 X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.3028 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3028 X-RFC2646: Format=Flowed; Original NNTP-Posting-Host: 144.160.5.25 Message-ID: <45dcc0cb@newsgroups.borland.com> X-Trace: newsgroups.borland.com 1172095179 144.160.5.25 (21 Feb 2007 13:59:39 -0800) Path: arc1-ca.pugleaf.net!g2news2.google.com!news4.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail