File I/O unbuffered/uncached cross platform?

Just starting out? Need help? Post your questions and find answers here.
hoerbie
Enthusiast
Enthusiast
Posts: 123
Joined: Fri Dec 06, 2013 11:57 am
Location: DE/BY/MUC

File I/O unbuffered/uncached cross platform?

Post by hoerbie »

Hi,

I've actually stumbled in communication with an usb device, that is simply recognized as a normal usb drive, so in Windows it gets a normal drive letter, on OS X it is found in /Volumes/devicename, and in general it is normal accessible with PBs CreateFile, OpenFile...

My problem was, that for the communication with its internal processor there is one file of a fixed bytesize, where I have to write commands into, and after writing my command, I have to get the answer from the same file with the same fixed bytesize. (Although it is a file in the directory, it seems to be internally something like a pipe to the processor in the usb device...)

Whenever I wrote my command, I simply got the same written bytes back for minutes, because of Windows and OS Xs file buffering/caching. As the communication is a time sensible one, where users of the software have to wait for the command and its answer, the normal PB functions are not usable.

I've tried a lot with the flags and commands

Code: Select all

#PB_File_NoBuffering
FileBuffersSize(#PB_Default,0)
FlushFileBuffers(#file)
but nothing worked. In another forum I found a thread of a VB6 user, that stumbled on the same problem, and he said using another VB6 command did its work, but this seems a special one of VB.

So I came to using WinApi direct and got below a second of answer time in using the following code in PB on Windows (tested in 7 Pro and 10 Home):

Code: Select all

Procedure.i file_read_unbuffered(fname.s, *fbuffer, flen.i)
  Protected.i bread,fhandle
  fhandle = CreateFile_(@fname,#GENERIC_READ,0,#Null,#OPEN_EXISTING,#FILE_FLAG_NO_BUFFERING,#Null)
  If fhandle <> #INVALID_HANDLE_VALUE
    ReadFile_(fhandle,*fbuffer,flen,@bread,#Null)
    CloseHandle_(fhandle)
  Else
    bread = -1
  EndIf
  ProcedureReturn bread
EndProcedure

Procedure.i file_write_unbuffered(fname.s, *fbuffer, flen.i=0)
  Protected.i bwrite,fhandle
  fhandle = CreateFile_(@fname,#GENERIC_WRITE,0,#Null,#OPEN_ALWAYS,#FILE_FLAG_NO_BUFFERING|#FILE_FLAG_WRITE_THROUGH,#Null)
  If fhandle <> #INVALID_HANDLE_VALUE
    WriteFile_(fhandle,*fbuffer,flen,@bwrite,#Null)
    CloseHandle_(fhandle)
  Else  
    bwrite = -1
  EndIf
  ProcedureReturn bwrite
EndProcedure
So my questions are now:

1. Is this the right way for Windows or does anyone knows a better way?

2. As the software should work cross platform later, how can I solve this on OS X and Linux? I found some postings of using O_DIRECT, setvbuf(... _IONBF ...) or pubsetbuf(0, 0). Anyone stumbled on and solved this problem?

Maybe unbuffered/uncached file i/o could be a point for the feature request forum...

Greetings, Hoerbie
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: File I/O unbuffered/uncached cross platform?

Post by Mijikai »

I dont know how to test #PB_File_NoBuffering as i never use it.
However ur WinAPI code lacks errorhandling.
hoerbie
Enthusiast
Enthusiast
Posts: 123
Joined: Fri Dec 06, 2013 11:57 am
Location: DE/BY/MUC

Re: File I/O unbuffered/uncached cross platform?

Post by hoerbie »

Sorry Mijikai,

but I can't see, where errorhandling really lacks.
In WinApi it is said, that CreateFile_ in success gives a handle back or #INVALID_HANDLE_VALUE in case of an error, this is checked.
And ReadFile and WriteFile give back the amount of read/written bytes to my vars bread/bwrite, that I check outside of the procedures.
OK, maybe I should additionally check success of CloseHandle_...

Greetings, Hoerbie
Post Reply