[Lazarus] Lazarus implementation of TListView etc?

Mark Morgan Lloyd markMLl.lazarus at telemetry.co.uk
Sat Oct 31 14:28:40 CET 2015


Bo Berglund wrote:
> On Sat, 31 Oct 2015 10:22:08 +0000, Mark Morgan Lloyd
> <markMLl.lazarus at telemetry.co.uk> wrote:
> 
>> Bo Berglund wrote:
> 
>> What does the main thread do? If you can contrive to write that as a 
>> loop, then as you've already been told you can call CheckSynchronize() 
>> which hands control to whatever's been queued by threads using 
>> Synchronize().
> 
> Right now the main thread (you mean the program code itself in the
> console program DoRun event, right) does this (mostly debug messages
> into the console):

I don't use Indy, but If I'm reading that lot correctly the answer is 
"outputs a couple of messages and terminates, within a second of startup".

Everybody's usage of threads etc. differs, depending on what they're 
doing and what their background is, so I hope somebody else is checking 
what I'm saying here (there's a big difference between using something 
and being competent to explain it- I consider myself in the former 
category). What I'd do is change the main code to be a loop to output 
your test messages without starting a background thread, and to loop for 
say a minute with Sleep() and CheckSynchronize(): if this crashes then 
you've got bigger problems.

Once this runs enable your comms thread and get it to output a couple of 
messages via Synchronize(), again this should not crash while the main 
program is running.

After that concentrate on- in particular- shutting down in good order, 
i.e. making sure that background threads are terminated before pulling 
the process out from under them.

>     Writeln('Freeing FComm at time ' + IntToStr(T2-T1));
>   finally
>     FComm.Free;
>   end;
>   // stop program loop
>   Terminate;
> end; 
> 
> And the output into the console is this:
> 
> Creating TCP client
> Start communications at time 27
> Connecting to www.sunet.se on port 80
> Going to sleep 500 at time 27
> Event: Socket connected! Time = 71 ms
> Waking up from sleep 500, at time 527
> Going to sleep 300 at time 527
> Waking up from sleep 300 at time 827
> Terminating thread
> Freeing FComm at time 827

I hope somebody else will comment about how much housekeeping FPC does 
here, but I do believe you've got a race condition: what happens if the 
main thread (i.e. the overall process) terminates faster than the 
background thread?

> When I run it in Lazarus there is a pop-up window saying:
> 
> Project IndyTCPtest raised exception class 'External: SIGSEGV'.
> 
>  At address 3132

Make sure you're compiling with debugging enabled.

>> Depending on exactly what the program does, you might need to do 
> 
> I just wanted to make a test with the TThread child I created, which
> also contains the TIdTcpClient object, to see if the events fire off.
> But I only get a single one into my code, then the SIGSEGV error.

You need to loop dequeuing events.

>> something like fudging keyboard access using fpSelect(), but basically 
>> it works... I've got a mainframe emulator here which responds to 
>> keyboard commands and also interleaves output from the various backend 
>> processes, I've used Lazarus as the IDE but it's entirely a console app.
> 
> I will have to figure out a way to make the test code do that loop. I
> had hoped that while executing sleep() statements the main thread
> would yield to the TCP thread but it seems like it does not...

Definitely not. Think about it for a moment: Sleep() is basically a 
low-level OS call, it really doesn't want to get involved with the 
complexity of deciding whether it's already in an event handler or is in 
a background thread.

A good starting point would be having the main loop run for a fixed 
time- a minute or something like that. In my case I've fudged my own 
keyboard handler etc. in a way that (hopefully) will allow me to use a 
GUI frontend, in other words it has to either poll the keyboard (the 
simpler case) or use fpSelect(). Potentially, for a non-GUI program 
keyboard handling etc. could simply be moved into its own thread so when 
it's accumulated a command (e.g. 'quit') it simply enqueues it using 
Synchronize() and the main thread decides what to do with it.

>>> I cannot use Synchronize because then the events fire off only when
>>> the main program code ends and if I don't use Synchronize then I get a
>>> SIGSEG exception somewhere.
>> Assume that none of the LCL is thread-safe, i.e. background threads have 
>> no safe UI access. Assume that the RTL and FCL are not specifically 
>> thread safe except where documented, but that you can use it in 
>> conjunction with conventional "cautious" programming techniques.
> 
> I have assumed as much so there is no side access to any data as far
> as I can tell.
> 
> Again, this is just a very simple console test program to check the
> operations of the threaded TCPIP communications, nothing near the
> final code because there I will have exit conditions and such.

Start off with a very simple program to /only/ test a background thread. 
I'd suggest leaving Indy etc. out of it until you're confident that it 
works and never throws an exception, /particularly/ during startup and 
shutdown.

-- 
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]




More information about the Lazarus mailing list