From: ··········@gmail.com
Subject: unbuffered io?
Date: 
Message-ID: <1163299931.634575.307560@h48g2000cwc.googlegroups.com>
Hi -

I am wondering whether there is a standard way (or maybe implementation
specific) of doing unbuffered I/O in lisp.  I am trying to create a
module that will basically allow multiple writes to the same file (for
different regions of the file to ensure there are no conflicts), but
the open/close call appears to buffer the stream so the multiple write
does not really work (basically the last one gets flushed to disk will
overwrite all other writes).

Please advice on how this can be accomplished, thanks. 

yinso

From: Sam Steingold
Subject: Re: unbuffered io?
Date: 
Message-ID: <m364dl8im4.fsf@loiso.podval.org>
> *  <··········@tznvy.pbz> [2006-11-11 18:52:11 -0800]:
>
> I am wondering whether there is a standard way (or maybe
> implementation specific) of doing unbuffered I/O in lisp.

http://clisp.cons.org/impnotes/stream-dict.html#buffered

-- 
Sam Steingold (http://sds.podval.org/) on Fedora Core release 5 (Bordeaux)
http://pmw.org.il http://truepeace.org http://honestreporting.com
http://iris.org.il http://ffii.org http://israelunderattack.slide.com
The only intuitive interface is the nipple.  The rest has to be learned.
From: ··········@gmail.com
Subject: Re: unbuffered io?
Date: 
Message-ID: <1163318720.024900.232090@k70g2000cwa.googlegroups.com>
Hi - thanks for the pointer.  Per my previous message, I am trying to
see if I can have multiple writers working on different segment of the
file.  Based on the document from clisp it appears that the :buffered
keyword only turns off clisp internal buffer, not the operating system
buffer.  I tested quick code with clisp and it appears that :buffered
nil does not do what I am looking for, which is somewhat analogues to
the code snippet below.

(setf f1 (open <filespec> :direction :io :if-exists :overwrite))
(setf f2 (open <filespec> :direction :io :if-exists ;overwrite))
(file-position f1 10)
(file-position f2 20)
(write-char #\a f1)
(write-char #\b f2)
(close f1)
(close f2)

and the file retains both #\a and #\b from the write-char calls.  The
code as written only keep the changes from the stream that closes last.


I am definitely not a lisp expert... let me know if I am doing
something incorrect here.

Thanks,
yinso

Sam Steingold wrote:
> > *  <··········@tznvy.pbz> [2006-11-11 18:52:11 -0800]:
> >
> > I am wondering whether there is a standard way (or maybe
> > implementation specific) of doing unbuffered I/O in lisp.
>
> http://clisp.cons.org/impnotes/stream-dict.html#buffered
>
> --
> Sam Steingold (http://sds.podval.org/) on Fedora Core release 5 (Bordeaux)
> http://pmw.org.il http://truepeace.org http://honestreporting.com
> http://iris.org.il http://ffii.org http://israelunderattack.slide.com
> The only intuitive interface is the nipple.  The rest has to be learned.
From: Pascal Bourguignon
Subject: Re: unbuffered io?
Date: 
Message-ID: <87r6w9jaob.fsf@thalassa.informatimago.com>
··········@gmail.com writes:

> Hi - thanks for the pointer.  Per my previous message, I am trying to
> see if I can have multiple writers working on different segment of the
> file.  Based on the document from clisp it appears that the :buffered
> keyword only turns off clisp internal buffer, not the operating system
> buffer.  I tested quick code with clisp and it appears that :buffered
> nil does not do what I am looking for, which is somewhat analogues to
> the code snippet below.
> [...]

What about something like this:

(defstruct cursor stream position)

(defun cursor-write-char (object cursor)
  (file-position (cursor-stream cursor) (cursor-position cursor))
  (prog1 (write-char object  (cursor-stream cursor))
    (setf (cursor-position cursor) (file-position (cursor-stream cursor)))))

(defmacro with-open-cursor ((cursor filespec &rest args
                                    &key &allow-other-keys)
                            &body body)
  (let ((vstream (gensym)))
    `(with-open-file (,vstream ,filespec ,@args)
       (let ((,cursor (make-cursor :stream ,vstream :position 0)))
         ,@body))))

(let ((<filespec> "test.data"))
  (with-open-file (file <filespec> :direction :output
                      :if-does-not-exist :create
                      :if-exists :supersede)
    (format file "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx~%"))
  (with-open-cursor  (c1 <filespec>
                       :direction :io
                       :if-exists :overwrite)
    (let ((c2 (copy-cursor c1)))
      (setf (cursor-position c1) 10)
      (setf (cursor-position c2) 20)
      (cursor-write-char #\A c1)
      (cursor-write-char #\B c2)
      (cursor-write-char #\1 c1)
      (cursor-write-char #\2 c2)))
    (with-open-file (file <filespec> :direction :input
                      :if-does-not-exist :error)
      (read-line file)))

--> "xxxxxxxxxxA1xxxxxxxxB2xxxxxxxxxxxxxxxxxx" ;
    NIL



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

PUBLIC NOTICE AS REQUIRED BY LAW: Any use of this product, in any
manner whatsoever, will increase the amount of disorder in the
universe. Although no liability is implied herein, the consumer is
warned that this process will ultimately lead to the heat death of
the universe.
From: Sam Steingold
Subject: Re: unbuffered io?
Date: 
Message-ID: <m3r6w87hh5.fsf@loiso.podval.org>
> *  <··········@tznvy.pbz> [2006-11-12 00:05:20 -0800]:
>
> Based on the document from clisp it appears that the :buffered keyword
> only turns off clisp internal buffer, not the operating system buffer.

yes.
for that you would need some ioctl call (?)

> I tested quick code with clisp and it appears that :buffered nil does
> not do what I am looking for, which is somewhat analogues to the code
> snippet below.
>
> (setf f1 (open <filespec> :direction :io :if-exists :overwrite))
> (setf f2 (open <filespec> :direction :io :if-exists ;overwrite))

no wonder - you did not pass :BUFFERED to it.
also, the semicolon (instead of a colon) indicated that this is not a
results of a cut and paste.

> (file-position f1 10)
> (file-position f2 20)

you just overwrote the file, it has been truncated, so you cannot seek()
to 10 or 20.

> (write-char #\a f1)
> (write-char #\b f2)
> (close f1)
> (close f2)
>
> and the file retains both #\a and #\b from the write-char calls.  The
> code as written only keep the changes from the stream that closes last.

yes, because you did not pass :BUFFERED NIL to OPEN.

-- 
Sam Steingold (http://sds.podval.org/) on Fedora Core release 5 (Bordeaux)
http://truepeace.org http://jihadwatch.org http://honestreporting.com
http://pmw.org.il http://memri.org http://israelunderattack.slide.com
Illiterate?  Write today, for free help!
From: ··········@gmail.com
Subject: Re: unbuffered io?
Date: 
Message-ID: <1163446534.735359.214090@f16g2000cwb.googlegroups.com>
Hi -

Sam Steingold wrote:
> > *  <··········@tznvy.pbz> [2006-11-12 00:05:20 -0800]:
> >
> > Based on the document from clisp it appears that the :buffered keyword
> > only turns off clisp internal buffer, not the operating system buffer.
>
> yes.
> for that you would need some ioctl call (?)

How to do that within lisp?

> >
> > (setf f1 (open <filespec> :direction :io :if-exists :overwrite))
> > (setf f2 (open <filespec> :direction :io :if-exists ;overwrite))
>
> no wonder - you did not pass :BUFFERED to it.
> also, the semicolon (instead of a colon) indicated that this is not a
> results of a cut and paste.

Yes - this is just me typing rather than doing copy/paste... thanks for
spotting the semicolon... ;)

Also - I actually also tested the code with :buffered keyword - it
appears that without buffering random access no longer works.  All
file-position call returns NIL instead of the actual positions.  That's
why I did not use that as the code snippet here.  

Thanks,
yinso