Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Apr : Re: TIdTCPServer - threads, global data contd.

www.cryer.info
Managed Newsgroup Archive

Re: TIdTCPServer - threads, global data contd.

Subject:Re: TIdTCPServer - threads, global data contd.
Posted by:"Martin James" (mjames_falc..@dial.pipex.com)
Date:Mon, 17 Apr 2006 04:10:04

>
> 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

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive