[fpc-devel] ConsoleIO and flushing buffered output

Michael Van Canneyt michael at freepascal.org
Mon Jun 8 17:47:47 CEST 2020



On Mon, 8 Jun 2020, Christo Crause via fpc-devel wrote:

> Michael, it is entirely possible that I am misunderstanding your
> suggestion, I probably don't grasp the complexities of the RTL texmode IO
> system and also not explaining my intention clearly, for this I apologise.
> Take for example the esp32 unit provided by Florian, here the link between
> the underlying OS output and the RTL is configured by calling OpenIO and
> providing readchar and writechar functions which in turn calls getchar and
> putchar (
> https://github.com/ccrause/freepascal/blob/76911c528251b48e18c348de1758c098ee9fb763/rtl/freertos/xtensa/esp32.pp#L106).
> In this unit Florian uses a custom printpchar procedure which pushes
> characters to the OS and at the end directly calls the OS fflush function.
> This ensures that the haltproc message gets transmitted before the cpu goes
> to sleep.
>
> I'm trying to change the controller unit to use standard RTL write
> functionality, since this gets configured during unit initialization
> anyway. My attempt at "Pascalizing" Florian's version (
> https://github.com/ccrause/freepascal/blob/76911c528251b48e18c348de1758c098ee9fb763/rtl/freertos/xtensa/esp8266.pp#L59)
> calls the normal write functionality and works, except for the last string
> before esp_deep_sleep which doesn't reach the remote terminal.  At the
> moment I fix this by directly calling the OS fflush function.
>
> The only configuration option exposed via consoleio is OpenIO, which
> doesn't have a parameter for a low level flush function.  I could create an
> overloaded OpenIO function with an extra parameter for a flush function
> pointer, and call this, if assigned, at the end of Console_Write.  Is this
> kind of the lower level detail behind your suggestion Michael?

I would add a flushfunc to TUserData and to the OpenIO call in consoleIO:

Type
   TFlushIOFunc = function(UserData: pointer): boolean;

and change
       PUserData = ^TUserData;
       TUserData = record
         WriteChar: TWriteCharFunc;
         ReadChar: TReadCharFunc;
         FlushFunc : TFlushIOFunc;
         UserData: Pointer;
       end;

change
  procedure OpenIO(var f: Text; AWrite: TWriteCharFunc; ARead: TReadCharFunc; AMode: word; AUserData: pointer);
to
  procedure OpenIO(var f: Text; AWrite: TWriteCharFunc; ARead: TReadCharFunc; aFlush : TFlushIOFunc; AMode: word; AUserData: pointer);

and add
   userdata^.FlushFunc := AFlush;

At the end of Console_Write I would call this new flush function:

        if i<>t.BufPos then
           InOutRes:=101
         else
           begin
           if userdata^.FlushFunc(userdata^.UserData) then
             InOutRes:=0
           else
             InOutRes:=101;
           end;
         t.BufPos:=0;
       end;

Console_Write is only called when the internal buffer is full or when the
output must be forced to terminal, so that should be sufficient.

Hope this helps,

Michael.


More information about the fpc-devel mailing list