Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Apr : Re: TIdTCPServer - threads, global data contd.
| Subject: | Re: TIdTCPServer - threads, global data contd. |
| Posted by: | "Stephen Odgaard" (s..@cowi.dk) |
| Date: | Mon, 17 Apr 2006 21:52:30 |
Thanks Martin,
I think I have a plan figured out by now. I have to dig one step further
into the OnExecute infinite look.
My current implementation of the .Execute is a ReadLn and a WriteLn.
I can see there is a "IdTimeOutDefault = -1" defining that the "Default
Timeout" should be used for ReadLn, but not what it is. Where can I see
this?
(I can see that the ReadLn(ATerminator, ATimeout, AMaxLineLength) could be
used, to assure this is under control.)
For WriteLn there seem not to be any timeout defined.
So basically the wait (or sleep) in a Execute thread containing a ReadLn and
WriteLn thread is basically this mystical "Default Timeout" value...
Stephen
"Martin James" <mjames_falcon@dial.pipex.com> wrote in message
news:44430582@newsgroups.borland.com...
> >
>> I need to understand exactly what you mean by continuous loop, but
> blocking
>> (u mentioned elsewhere)
>
> The thread calls onExecute 'event' in a loop:
>
> ---------------------------------
> procedure TpeerThread.execute;
> repeat
> onExecute(AContext);
> until false;
> end;
> ---------------------------------
>
> Inside the onExecute event, your user code makes blocking read/write
> calls.
>
>> The question is thus by what and how often it is unblocked?
>
> Read calls - when data arrives, or on timeout.
> Write Calls - when data can be sent.
>
>> >> 1c) How can I (eg. from the main thread) "provoke" the OnExecute Event
>> >> handler of a given client to be executed in order to empty an outbound
>> > info
>> >> queue?
>> >
>> > One way is to conver the socket to non-blocking, (see 'Interrupting
>> > ReadFromStack call?' thread from Aart). This allows a thread to wait
>> > on
>> > both a socket and a synchro object, (eg. a semaphore), associated with
> an
>> > object queue.
>> >
>>
>> Ok, this sounds like a way to go, although getting somewhat complex with
> the
>> changing of the behaviour.
>
> It is somewhat.
>
>>
>> Well what I actually want is to store some client specific information
> (eg.
>> about the capabilities of the connected client).
>
> Oh, that stuff - config data.
>
>> After looking futher into this, it would seem that using the
>> AContext.Data
>> object should be a handle at my disposition for a user defined class.
>> Correct?
>
> Yes.
>
>>
>> Ok, this sounds a bit concerning to me when you say the effects on Indy
>> is
>> somewhat unknown.
>
> It *should* be OK. If not, the socket would have to be switched back to
> blocking mode after each signal.
>
>> > attempting direct writes.
>>
>> Right - In order to assure an awareness of what clients are connected to
> the
>> server, I would have to get access to a list of active AContexts.
>> They must be maintained by either the TidTCPServer or its assigned
>> TidScheduler. Can you point me in the right direction on how to get this
>> awareness?
>
> Oh - TidTCPServer already has such a list. I forget the name of the thing
> at them moment, but should be easy to find in the help.
>
>> The P-C queue could actually be part of the AContext.Data structure could
> it
>> not? That way the AContext.Connect and .Disconnect could create it and
> free
>> it again.
>
> Yes, that's where I would put it.
>
>> Juging by the "Interrupting ReadFromStack call?" thread this method is
>> not
>> very common (only Aart), and I could be concerned of unknown problems. So
>> before selecting this method I would like to hear if there are other
>> alternative approaches.
>
> Well, you could use a short-timeout read call to allow polling the data
> queue. This introduces a timeout- tradeoff between the CPU cycles wasted
> in
> continually polling empty queues and write latency. This is a miserable
> design, but one that others have used because of the difficulties with
> Indy
> and chat apps.
>
> A small pool of threads could be used to perform the write operations,
> independently of the the Indy peer threads that are then only used for
> reading. The write-threads would all wait on the same P-C queue for data
> to
> send. The data-carrier object would have to store the context to send on
> as
> well as the data to send. That would work - if a client crashed, only
> one
> thread in the pool would get stuck and the other threads would be able to
> continue writing to the other clients. The snag is that the server would
> only be able to survive as many 'suddenly-unreachable' clients as there
> are
> threads in the pool. Another problem is that, again, a context could
> become
> disconnected/freed while it was in the pool queue. The write thread that
> got the context/data for this gone-away client would then AV when
> attempting
> the write. The pool queue could be purged of all objects for that client
> upon disconnect, but it all adds complexity.
>
> I wish Indy did not immediately free up contexts when clients disconnect.
> It would have been better if disconnected contexts were timed-out over,
> say,
> 2 minutes, (like the OS does with the sockets and TIMED_WAIT), and for the
> same reason - to avoid problems after disconnect with outstanding data.
>
> Rgds,
> Martin