Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2010-11

Reading and writing TMemoryStream in events?

12 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bo Berglund

I intended to use a TMemoryStream object to collect incoming serial port data, but now I am not so sure it will be possible...

The problem as I see it is illustrated as follows: In the event of the serial port component:

  s := FComm.ReadData;
  FMemStr.Seek(0, soFromEnd);  // To make sure we write at the end
  FMemStr.WriteBuffer(s[1], Length(s);

Then in the program waiting for the data to arrive:

  T1 := GetTickCount;
  while FMemStr.Position = 0 do
  begin
    Sleep(10);
    if GetTickCount - T1 > FCommTimeout then break;
  end;
  if FMemStr.Position = 0 then exit;
  FMemStr.Seek(0, soFromBeginning); //Read first byte
  C := FMemStr.ReadByte;

PROBLEM:
What will happen if a receive event is fired between the FMemStr.Seek and C := FMemStr.ReadByte statements?

If the event handler does its thing then the memory stream pointer will have been moved to a different value (end of stream) and the ReadByte call will fail, right?

How can I avoid this from happening?

Bo Berglund

Reply by email

Bo Berglund
to Bo Berglund
Bo Berglund wrote
I intended to use a TMemoryStream object to collect incoming serial port data, but now I am not so sure it will be possible...

Never mind,
I solved the problem by creating a new class containing a dynamic byte array that I manage myself. THis way I get full control over the read and write pointers and the size of the storage.

Bo Berglund Developer in Sweden

Reply by email

Michael Schnell
to Bo Berglund: I intended to use a TMemoryStream object to collect incoming serial port data, but now I…

If the "Event" is just a normal (main-thread) event, there should be no problem using whatever data structure in the normal way.

f the "Event" is fired in a thread context, you need to use critical sections top manage the mutual accesses. TThreadList does this for you, so you might want to allocate a new chunk of the data when the thread read it and add the pointer to the chunk in a TThreadList.

-Michael

Reply by email

Paul Breneman
to Michael Schnell
Michael Schnell wrote 7 lines
If the "Event" is just a normal (main-thread) event, there should be no problem using whatever data structure in the normal way. f the "Event" is fired in a thread context, you need to use critical sections top manage the mutual accesses. TThreadList does this for you, so you might want to allocate a new chunk of the data when the thread read it and add the pointer to the chunk in a TThreadList.

I have used TThreadList as you mentioned for threaded serial communication (using SynaSer) with a console program under Linux.

As you and I and others have discussed several times in the past several years, having some method for non-GUI messaging would seem nicer but my program just works with 1200 baud radio communication so using TThreadList and polling is fast enough for that. :)

Regards, Paul Breneman www.dbReplication.com - VCL database replication components www.TurboControl.com - Hardware and software development services - Educational programming project for environment monitoring - Information on using FreePascal for embedded systems - Support information for the TurboPower open source libraries

Reply by email

Henry Vermaak
to Paul Breneman
Paul Breneman wrote 16 lines
Michael Schnell wrote: > If the "Event" is just a normal (main-thread) event, there should be > no problem using whatever data structure in the normal way. > > f the "Event" is fired in a thread context, you need to use critical > sections top manage the mutual accesses. TThreadList does this for > you, so you might want to allocate a new chunk of the data when the > thread read it and add the pointer to the chunk in a TThreadList. I have used TThreadList as you mentioned for threaded serial communication (using SynaSer) with a console program under Linux. As you and I and others have discussed several times in the past several years, having some method for non-GUI messaging would seem nicer but my program just works with 1200 baud radio communication so using TThreadList and polling is fast enough for that. :)

Just curious, why don't you use select() instead of polling?

Henry

Reply by email

Henry Vermaak
to Michael Schnell
Michael Schnell wrote
On 11/08/2010 01:52 PM, Henry Vermaak wrote: > Just curious, why don't you use select() instead of polling? AFAIK, select() is not portable.

It's pretty portable, being POSIX and all. For Windows you'd use overlapped io, iocp and wait functions. Or libevent, which is supposed to be completely cross platform, but I haven't tried that yet.

Henry

Reply by email

Paul Breneman
to Henry Vermaak
Henry Vermaak wrote 8 lines
On 08/11/10 15:56, Michael Schnell wrote: > On 11/08/2010 01:52 PM, Henry Vermaak wrote: >> Just curious, why don't you use select() instead of polling? > AFAIK, select() is not portable. It's pretty portable, being POSIX and all. For Windows you'd use overlapped io, iocp and wait functions. Or libevent, which is supposed to be completely cross platform, but I haven't tried that yet.

I am trying to keep my code portable, so I'll have to look at libevent more. Thanks for mentioning it.

Reply by email

Michael Schnell
to Henry Vermaak: It's pretty portable, being POSIX and all. For Windows you'd use overlapped io, iocp and…
Henry Vermaak wrote
It's pretty portable, being POSIX and all.

With "portable", here I meant "same code for Windows and Linux" (I'd better called it "Cross-Platform").

For Windows you'd use overlapped io, iocp and wait functions. Or libevent, which is supposed to be completely cross platform, but I haven't tried that yet.

So there is some cross platform method in libevent that can be used ?

(AFAIK, he wants to wait for serial characters and for a timer at the same time in a project without a GUI.)

-Michael

Reply by email

Paul Breneman
to Michael Schnell
Michael Schnell wrote 13 lines
On 11/08/2010 05:39 PM, Henry Vermaak wrote: > > It's pretty portable, being POSIX and all. With "portable", here I meant "same code for Windows and Linux" (I'd better called it "Cross-Platform"). > For Windows you'd use overlapped io, iocp and wait functions. Or > libevent, which is supposed to be completely cross platform, but I > haven't tried that yet. > So there is some cross platform method in libevent that can be used ? (AFAIK, he wants to wait for serial characters and for a timer at the same time in a project without a GUI.)

It is a little hard to explain since my Comm DataModule has 2200 lines with input and output threads and a TThreadList for each, and that DataModule is created by another thread with message processing. The same unit works with AsyncPro in Windows (Delphi) and SynaSer in Linux (Free Pascal and fpGUI for GUI programs). There are console and GUI programs in each OS.

The way I write serial communication "engines" would never work for servers with a high load, but industrial serial communication almost always presents very little load to the CPU. Therefore I can add additional layers of threads (on top of the 3 threads that AsyncPro itself creates) as needed to best abstract the code so it isn't coupled into the GUI. The additional threads also allow me to avoid writing state machines with multiple event handlers interacting (for received data, timeouts, etc) which is the standard way to use AsyncPro and which is heavily coupled into the GUI. I find it nice to write "linear" code in a separate thread so all error handling is inline.

In the main project for this code the protocol contains device addresses so an embedded Linux touchscreen controller can receive a command to set its clock and the engine can deal with that and send back the acknowledgment to the requesting master device at the same time the user is using the touchscreen to interact with a different device. So its not just a simple request/response situation.

There are examples of basic "engines" using AsyncPro on this page: http://www.turbocontrol.com/APro.htm

I'd like to duplicate some of those with SynaSer or other cross-platform libraries (and add them to the page below) so if anyone has some extra time please contact me... :)
http://www.turbocontrol.com/simpleserial.htm

Regards, Paul Breneman www.dbReplication.com - VCL database replication components www.TurboControl.com - Hardware and software development services - Educational programming project for environment monitoring - Information on using FreePascal for embedded systems - Support information for the TurboPower open source libraries

Reply by email

Bo Berglund
to Paul Breneman
Paul Breneman wrote 14 lines
Michael Schnell wrote: > On 11/08/2010 05:39 PM, Henry Vermaak wrote: >> >> It's pretty portable, being POSIX and all. > With "portable", here I meant "same code for Windows and Linux" (I'd > better called it "Cross-Platform"). >> For Windows you'd use overlapped io, iocp and wait functions. Or >> libevent, which is supposed to be completely cross platform, but I >> haven't tried that yet. >> > So there is some cross platform method in libevent that can be used ? > > (AFAIK, he wants to wait for serial characters and for a timer at the > same time in a project without a GUI.)

Well, I want to have a responsive GUI application which can do stuff while the data are streamed from the DA system. Depending on the measurements performed the data may be upwards of several hundred kilobytes. The max speed the DA system can do is 38400 baud so I am looking at several minutes of transfer time...
And the platform is embedded Debian Linux on an ARM device with a touch screen.

Show quoted text 6 lines
It is a little hard to explain since my Comm DataModule has 2200 lines with input and output threads and a TThreadList for each, and that DataModule is created by another thread with message processing. The same unit works with AsyncPro in Windows (Delphi) and SynaSer in Linux (Free Pascal and fpGUI for GUI programs). There are console and GUI programs in each OS.

Did you do conditionals in the code to mask out AsyncPro in Linux and SynaSer on Windows?
I tried at first to use my old code by disguising SdpoSerial as the TSerial I was using originally but it was too much work...

Show quoted text 17 lines
The way I write serial communication "engines" would never work for servers with a high load, but industrial serial communication almost always presents very little load to the CPU. Therefore I can add additional layers of threads (on top of the 3 threads that AsyncPro itself creates) as needed to best abstract the code so it isn't coupled into the GUI. The additional threads also allow me to avoid writing state machines with multiple event handlers interacting (for received data, timeouts, etc) which is the standard way to use AsyncPro and which is heavily coupled into the GUI. I find it nice to write "linear" code in a separate thread so all error handling is inline. In the main project for this code the protocol contains device addresses so an embedded Linux touchscreen controller can receive a command to set its clock and the engine can deal with that and send back the acknowledgment to the requesting master device at the same time the user is using the touchscreen to interact with a different device. So its not just a simple request/response situation.

My case on the other hand is rather like a request/response system. The DA comm interface is designed to enable host PC up/download of data and settings. But it is not by itself originating any data except for the single case whan it is used in a monitoring situation where each measure event is flagged by a packet of bytes on the serial channel so the host can keep tabs on the measure progress. So I probably have a simpler situation.

Show quoted text 11 lines
There are examples of basic "engines" using AsyncPro on this page: http://www.turbocontrol.com/APro.htm I'd like to duplicate some of those with SynaSer or other cross-platform libraries (and add them to the page below) so if anyone has some extra time please contact me... :) http://www.turbocontrol.com/simpleserial.htm -- Regards, Paul Breneman

Hi Paul, there you are again! Good to hear from you! :-)

I took your advice on the ARM based dev board with touch screen, which is now sitting on my desk. Just have to get my code right and then try to push it onto this little gadget. Hope it will work OK for my purposes as a front-end to the DA system.

After reading the initial responses to this thread I decided to create my own comm buffer class based on a dynamic byte array and use it to collect the data arriving from the data acquisition system. As you rightly say the load will be very light.

I will use a SdpoSerial component, which is based on SynaSer but gives me the event function I am used to with the other comm controls I have used in Windows.

BTW I see you mention AsyncPro, is it ported to FPC for multi-platform use? Just curious, but I won't use it here because of the unneeded complexity of that piece of software...

Instead I will package the SdpoSerial and my CommBuf class together in a communications handler class that understands the actual protocol of the DA system. Then I will move up the ladder to the application and start using it to do actual comm stuff.
I am still at the comm handler class stage, though. Soon reaching the stage where I can do actual tests...

Bo Berglund Developer in Sweden

Reply by email

Paul Breneman
to Bo Berglund
Bo Berglund wrote
On Tue, 09 Nov 2010 08:45:48 -0500, Paul Breneman wrote:

...

Show quoted text 9 lines
> It is a little hard to explain since my Comm DataModule has 2200 lines > with input and output threads and a TThreadList for each, and that > DataModule is created by another thread with message processing. The > same unit works with AsyncPro in Windows (Delphi) and SynaSer in Linux > (Free Pascal and fpGUI for GUI programs). There are console and GUI > programs in each OS. Did you do conditionals in the code to mask out AsyncPro in Linux and SynaSer on Windows?

Yes I use conditionals. Isn't too much of a mess.

...

I took your advice on the ARM based dev board with touch screen, which is now sitting on my desk. Just have to get my code right and then try to push it onto this little gadget. Hope it will work OK for my purposes as a front-end to the DA system.

Technologic Systems has been a good supplier for a long time for one of my clients so I'm happy to recommend them.

...

BTW I see you mention AsyncPro, is it ported to FPC for multi-platform use? Just curious, but I won't use it here because of the unneeded complexity of that piece of software...

I doubt AsyncPro will get ported, but someone on this list said they might duplicate all the top-level API so that might work.

Instead I will package the SdpoSerial and my CommBuf class together in a communications handler class that understands the actual protocol of the DA system. Then I will move up the ladder to the application and start using it to do actual comm stuff.

SdpoSerial sounds interesting and I need to check it out more.

I am still at the comm handler class stage, though. Soon reaching the stage where I can do actual tests...

Please let me know how things work out.

Reply by email