Re: [Haskell-cafe] Double free-ing (was: Reading from a process)

2009-12-18 Thread Mitar
Hi!

On Fri, Dec 18, 2009 at 8:16 AM, Jason Dusek jason.du...@gmail.com wrote:
  Concatenating two `ByteString`s is O(n)?

This is what it is written here:

http://haskell.org/ghc/docs/latest/html/libraries/bytestring-0.9.1.5/Data-ByteString.html#v%3Aappend


Mitar
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Double free-ing

2009-12-18 Thread Mitar
Hi!

On Fri, Dec 18, 2009 at 8:29 AM, Ketil Malde ke...@malde.org wrote:
 Lazy ByteStrings should be able to append with O(1).  (Or use strict BS
 hGetNonBlocking, and Lazy ByteString fromChunks.)

Oh, true. Thanks!

But ... lazy ByteString's hGetNonBlocking is probably not lazy? Could
it be? It has to read at that moment whatever it can? But appending is
really better. Why are lazy ByteStrings not default?

Thanks again.


Mitar
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Double free-ing

2009-12-18 Thread Mitar
Hi!

On Fri, Dec 18, 2009 at 6:54 PM, Mitar mmi...@gmail.com wrote:
 On Fri, Dec 18, 2009 at 8:29 AM, Ketil Malde ke...@malde.org wrote:
 Lazy ByteStrings should be able to append with O(1).  (Or use strict BS
 hGetNonBlocking, and Lazy ByteString fromChunks.)

 Oh, true. Thanks!

 But ... lazy ByteString's hGetNonBlocking is probably not lazy? Could
 it be? It has to read at that moment whatever it can? But appending is
 really better. Why are lazy ByteStrings not default?

Tried it and it really works great! Thanks to all.


Mitar
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Double free-ing (was: Reading from a process)

2009-12-17 Thread Mitar
Hi!

On Thu, Dec 17, 2009 at 5:28 AM, Jason Dusek jason.du...@gmail.com wrote:
  It seems like the message delimiter to me because you keep
  buffering till you receive it.

Hm, true. I have changed code to this:

getLastMyData :: MySate (Maybe MyData)
getLastMyData = do
  p - gets process
  case p of
Nothing  - fail No process
Just (MyProcess processOut processPid processBuffer) - do
  processRunning - io $ getProcessExitCode processPid
  case processRunning of
Just _ - processExited
_  - do
  ret - io $ tryJust (guard . isEOFError) $ slurpMyData
processOut processBuffer
  case ret of
Left _   - processExited -- EOF
Right (datalist, currentBuffer) - do
  modify (\s - s { process = Just (MyProcess processOut
processPid currentBuffer) })
  if null datalist
then return Nothing
else return $ Just $ head datalist -- MyData is stored
in the reverse order so head is the last MyData from the process

slurpMyData :: Handle - DataBuffer - IO ([MyData], DataBuffer)
slurpMyData = slurpMyData' []
  where slurpMyData' datalist h buffer@(DataBuffer capacity array
bytecount) = do
  ready - hReady h
  if not ready
then return (datalist, buffer)
else do
  let array' = advancePtr array bytecount
  count - hGetBufNonBlocking h array' (capacity - bytecount)
  let bytecount' = bytecount + count
  chars - peekArray bytecount' array
  let (d, rest) = readData . dataToString $ chars
  rest' = stringToData rest
  if null d
then if length rest' == capacity
   then error Invalid data from the process
   else return (datalist, buffer)
else do
  assert (length rest' = capacity) $ pokeArray array rest'
  let buffer' = DataBuffer capacity array (length rest')
  slurpMyData' (d ++ datalist) h buffer'

readData :: String - ([MyData], String)
readData = readData' []
  where readData' datalist  = (datalist, )
readData' datalist string = case reads string of
  [(x, rest)] - readData' ((head
x):datalist) rest -- x is a list and currently it has only one element
  []  - (datalist,
string) -- we probably do not have enough data to read MyData properly
  _   - error Ambiguous
parse from the process

And now it works. I just do not like using malloc and free.

And talking about free, I have now a problem of double freeing this
buffer. I am getting it after I send ctrl-c to the main process (with
underlying process I am communicating with). I am freeing it in
processExited:

processExited :: MyState a
processExited = do
  terminateDataProcess
  fail Process exited

terminateDataProcess :: MyState ()
terminateDataProcess = do
  p - gets process
  case p of
Just (MyProcess _ processPid (DataBuffer _ array _)) - do
  modify (\s - s { process = Nothing })
  io $ free array
  io $ terminateProcess processPid
_ - return ()

So I run processExited if there is EOF from underlying process. But I
also run terminateDataProcess in a bracket I am calling getLastMyData.
Code is like this:

bracket initDataProcess terminateDataProcess (... read getLastMyData
repeatedly and process it ...)

Why I am getting this double free-ing errors? Should I introduce some
locks on terminateDataProcess?

I am using Linux 2.6.30 amd64 and 6.10.4.


Mitar
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Double free-ing (was: Reading from a process)

2009-12-17 Thread Jason Dusek
  You shouldn't have to use `malloc` and `free` to accumulate
  input. Just append to a list or a ByteString, which is to say,
  add a byte to a ByteString to get a new ByteString. Yes, really.

  Maybe there is something I am missing here; but I can't see any
  reason to adopt this unnatural (for Haskell) approach.

--
Jason Dusek
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Double free-ing (was: Reading from a process)

2009-12-17 Thread Mitar
Hi!

On Fri, Dec 18, 2009 at 1:53 AM, Jason Dusek jason.du...@gmail.com wrote:
  You shouldn't have to use `malloc` and `free` to accumulate
  input. Just append to a list or a ByteString, which is to say,
  add a byte to a ByteString to get a new ByteString. Yes, really.

Oh, I did not know that ByteString has hGetNonBlocking. When I see
that System.IO's hGetBufNonBlocking uses Ptr I started crying and kept
crying while coding with it. It was really strange for me to use
Foreign.* modules for code which should be clean Haskell.

  Maybe there is something I am missing here; but I can't see any
  reason to adopt this unnatural (for Haskell) approach.

I checked ByteString's hGetNonBlocking now and I do see why it is
still better to use System.IO's hGetBufNonBlocking. I would like to
have a buffer of fixed length and just fill it until it is full. With
hGetBufNonBlocking this is possible as I can just give different
starting positions in the buffer while retaining data already read
where it is (so I do not to copy anything around). But with
hGetNonBlocking I would have to append two different buffers to get a
resulting buffer, what is completely unnecessary O(n). Why would I
read data into some other buffer just to be able to append it to main
buffer later.

Any suggestion how can I do that in Haskell why?


Mitar
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Double free-ing (was: Reading from a process)

2009-12-17 Thread Jason Dusek
  Concatenating two `ByteString`s is O(n)?

--
Jason Dusek
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Double free-ing

2009-12-17 Thread Ketil Malde
Mitar mmi...@gmail.com writes:

 I checked ByteString's hGetNonBlocking now and I do see why it is
 still better to use System.IO's hGetBufNonBlocking.

 [...] But with hGetNonBlocking I would have to append two different
 buffers to get a resulting buffer, what is completely unnecessary
 O(n).

Lazy ByteStrings should be able to append with O(1).  (Or use strict BS
hGetNonBlocking, and Lazy ByteString fromChunks.)

-k
-- 
If I haven't seen further, it is by standing in the footprints of giants
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe