I have a TWSocket descendant called TWSocketClientDeluxe. It does its work on
a background thread. I have confirmed that this is the case by setting
breakpoints on various events and inspecting the Threads window to make sure it
is not on the main thread. It creates its own client thread and its
Multithreaded property is TRUE.
I recently changed my Send() method override to post buffers to the client
thread so that the actual Send() takes place on the worker thread and not on
the thread that calls TWSocketClientDeluxe.Send(). To facilitate this, the
custom message loop I created to replace the base class method has custom
windows messages for executing certain relevant requests and for processing the
Send() data requests posted by TWSocketClientDeluxe.Send(). The client thread
message loop then takes those buffers and calls a method I created called
BgSend(). That method simply calls the base class Send() method (inherited
Send()). I am having various problems so I am posting the code I wrote for the
client thread's custom message loop to see if any of you see any problems with
it. It's a little lengthy so my apologies in advance.
The reason I have taken such extreme measures like moving to a background
thread and decoupling the Send() operation is to avoid any thread blocking
issues as much as I can. My application is the middleman between two sockets
that cooperate in a multiple real-time audio streams. Therefore, I have to
grab the buffer from one socket and send it out the other as quickly as
possible. Hence the extreme measures. Note, the interface object retrieved
from the MsgRec was already _AddRef'd an extra time before it was posted to
make sure it did not destroy prematurely when recovered by the custom message
loop.
Here's the code, hopefully the formatting doesn't fall apart in your E-mail
reader. Please comment on anything that is wrong or might cause instabilities
or problems:
------------------ Custom Message Loop For Socket Client Thread --------
while GetMessage(MsgRec, 0, 0, 0) do
begin
TranslateMessage(MsgRec);
// Is it a request to execute a custom background thread request?
if MsgRec.message = WM_BG_CUSTOM_SOCKET_REQUEST then
begin
// ATI: 1-10-2012: Custom background thread request.
//
// If our owner socket is a TWSocketClientDeluxe instance and
// we have a custom background request event handler, then
// call it now.
if WSocket is TWSocketClientDeluxe then
begin
theSockCliDeluxe := TWSocketClientDeluxe(WSocket);
if Assigned(theSockCliDeluxe.OnBgCustomRequestProc) then
theSockCliDeluxe.OnBgCustomRequestProc(MsgRec);
end; // if WSocket is TWSocketClientDeluxe then
end
// Is it a request to reconnect with the same settings as the
// last connect (current settings)?
else if MsgRec.message = WM_BG_SOCKET_RECONNECT then
begin
// If we are not "closed" then this is an error.
if not (WSocket.State = wsClosed) then
raise Exception.Create('(TClientThread.Execute) A reconnect request
was received when our socket was not in the "closed" state. Socket name: ' +
WSocket.Name);
// --------------- RECONNECT ---------------
// Re-connect.
WSocket.Connect;
end // if (GAUNTLET) then
else if MsgRec.message = WM_BG_SOCKET_SEND_REQUEST then
begin
// -------------- SEND DATA REQUEST ------------------
// Recover the send data request interface.
intf := nil;
P := Pointer(MsgRec.lParam);
if not Assigned(P) then
raise Exception.Create('(TClientThread.Execute) Long parameter was
not assigned, received pointer invalid while recovering the
IPostBufferToCollection interface.');
Move(P, intf, sizeof(intf));
if not Assigned(intf) then
raise Exception.Create('(TClientThread.Execute) Received an
unassigned interface object.');
if not Supports(intf, IClientSocketSendDataRequest,
intfCliSockSendDataReq) then
raise Exception.Create('(TClientThread.Execute) Interface object
received is not a IClientSocketSendDataRequest interface.');
if not Assigned(intfCliSockSendDataReq.data) then
raise Exception.Create('(TClientThread.Execute) The send data
request has an unassigned data pointer.');
if intfCliSockSendDataReq.dataLen <= 0 then
raise Exception.Create('(TClientThread.Execute) The send data
request''s buffer length is less than or equal to 0.');
// Send the data now but use the background send method that
// calls the inherited Send() method directly or we
// will create a recursive self-posting situation.
with WSocket as TWSocketClientDeluxe do
BgSend(intfCliSockSendDataReq.data, intfCliSockSendDataReq.dataLen);
// Release the interface variables we used.
intf := nil;
intfCliSockSendDataReq := nil;
end
else
// Pass it on.
DispatchMessage(MsgRec);
end; // while()
--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be