DZ-Jay wrote:
> On Oct 11, 2007, at 06:47, Arno Garrels wrote:
> 
>> Iterating thru Srv.Clients is not the way to go!! It is not
>> thread-save and will most likely throw strange AVs. Instead
>> iterate thru the thread-list and post a custom message to each
>> thread, the inside the thread iterate thru each thread's
>> client list, see TWSocketThrdServer.DisconnectAll as example.
>> Now one problem is that TWSocketThrdServer has no public property
>> ThreadList and TWsClientThread.PumpMessages doesn't fire an event
>> OnMessage. So the code has to be tweaked a little bit for common use.
> 
> So, would you recommend that I extend the component and override
> DisconnectAll to, say, fire an event that I could hook on to send the
> messages; and then call DisconnectAll() from my worker thread instead
> of using the loop?  If so, we should add something like this to the
> component itself, no? (I could provide the code when I'm done with
> it.)

I suggest an event OnMessage that fires from PumpMessages like this:

    TMessageEvent = procedure(Sender: TObject; var Msg: TMessage; var Handled: 
Boolean);
    TWsClientThread = class(TThread)
    private
        FReadyForMsgs     : Boolean;
        FServer           : TWSocketThrdServer;
        FClients          : TList;
        FEventArray       : array [TWsClientThreadEventID] of THandle;
        FOnMessage        : TMessageEvent;
    protected
        procedure   DetachClient(Client: TWSocketThrdClient);
        procedure   AttachClient(Client: TWSocketThrdClient);
        procedure   DisconnectAll;
        procedure   PumpMessages(WaitForMessages : Boolean); virtual;
        procedure   Execute; override;
        function    GetClientCount : Integer;
    public
        constructor Create(Suspended : Boolean);
        destructor  Destroy; override;
        property    ClientCount  : Integer             read  GetClientCount;
        property    ReadyForMsgs : Boolean             read  FReadyForMsgs;
        property    OnMessage    : TMessageEvent       read  FOnMessage
                                                       write FOnMessage;
    end;

procedure TWsClientThread.PumpMessages(WaitForMessages: Boolean);
..
            WM_THREAD_EXCEPTION_TEST :
                raise Exception.Create('** TEST EXCEPTION ***')
            else
                MsgRec.Msg    := Msg.message;
                MsgRec.WParam := Msg.wParam;
                MsgRec.LParam := Msg.lParam;
                Handled := False;
                if Assigned(FOnMessage) then
                    FOnMessage(Self, MsgRec, Handled);
                if not Handled then
                    Dispatch(MsgRec);
            end;

This is untested code. Also FThreadList has to be made public.
Note that OnMessage would fire in different thread contexts but
a single handler for all is fine. Hope this helps.

> 
>> The only reason why I started writing this component was to derive
>> a SSL multi-threaded server from it only to be able to test
>> thread-safety of the SSL code.
> 
> Are you suggesting the component is not stable for a production
> application?

I think it isn't very fast, I tested once with some stress
clients and many concurrent connections successfully over many
hours until that point it looked stable. In any case I won't use
multi-threading if not absolutely necessary, simply because it's
easier to code and to debug. TWSocketServer can handle many hundreds
of concurrent connections in a single thread.

--
Arno Garrels [TeamICS]
http://www.overbyte.be/eng/overbyte/teamics.html

-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to