avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-libc-dev] fflush() implementation


From: Georg-Johann Lay
Subject: Re: [avr-libc-dev] fflush() implementation
Date: Sat, 25 Aug 2012 00:19:19 +0200
User-agent: Thunderbird 2.0.0.24 (Windows/20100228)

Daniel Otte schrieb:
Hi,
the current state of fflush() according to stdio.h is:
   Flush \c stream.

   This is a null operation provided for source-code compatibility
   only, as the standard IO implementation currently does not perform
   any buffering.

This is ok for the stream implementation itself if it is not buffering, but if
the device driver which forms the base of the stream performs buffering it may
be would like to be informed if fflush() is called to flush its own buffers.

I currently run into this case because I have an interrupt-driven UART component
which manages its own buffers. And especially during debugging fflush() is very
helpful as messages may get stuck in the buffer before a crash and you are
searching for the problem at the wrong location.
A possible solution would be using a dedicated flush-function provided by the
driver but this is neither elegant nor very portable.

Well, if it's only about debugging an application by ad-hoc sprinkling
commands over the file, I think portability is no issue.  Changing the
ABI for a transient use case like this is not appropriate, IMO.

The command will go away after you finished the debugging stage and
won't be present in productive code.

So a possible solution would be to extend the __file struct with a field
containing a pointer to a driver provided flush-function and registering this
function via a dedicated function. This has the two cons, that the structure
would require more space (2 bytes) and that another auxiliary function is 
required.

There are more cons.  One is that you change the binary interface and
therefore existing code is no more link-compatible.

The respective release would have to mention the caveat of an ABI change
in its release notes at least.

Another solution would be to change the prototype of the supplied put-function 
from
  int (*put)(char, FILE *)
to
  int (*put)(int, FILE *)
and use a magic value outside the range of char to trigger the flush-function.

The function to hook in are according to standards, e.g. fputc.
It's no good idea to change that.

This has the big con, that the prototype has to be changed, and existent
conforming code may cause a warning but (if I remember the ABI correctly) would
still continue to work.

There are a lot of other possible solutions and possible modifications of the
above two (like using a dedicated flag to indicate the presence of the auxiliary
field). Feel free to add other good solutions.

You could write your application as usual:

#include <stdio.h>

int main (void)
{
    return fflush (stdout);
}

In Projects where you use AVR-Libc, supply a C module fflush.c and
a header fflush.h

fflush.c implements fflush to whatever you deem appropriate.
When linking, you link fflush.o to your application, and when
compiling, you compile with -include fflush.h

fflush.h could look like that:

#ifndef FFLUSH_H
#define FFLUSH_H

#define fflush fflush_be_gone
#include <stdio.h>
#undef fflush

extern int fflush (FILE*);
#endif /* FFLUSH_H */


That's it.
No need to change the tools or the ABI.
No need to change yours or others system headers.
No need to explicitly #include "fflush.h"
It' all hidden behind two command options in your Makefile
or build script.

And if you want to run your code without the fflush you
can simply make fflush void or activate in fflush.h a line like

#define fflush(X) (void)(X)


Johann

Best regards,
  Daniel




reply via email to

[Prev in Thread] Current Thread [Next in Thread]