[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