
Hi, On 14.01.2012, at 12:11, Serge D. Mechveliani wrote:
On Fri, Jan 13, 2012 at 12:19:34PM -0800, Donn Cave wrote:
Quoth "Serge D. Mechveliani"
, ... Initially, I did the example by the Foreign Function Interface for C. But then, I thought "But this is unnatural! Use plainly the standard Haskell IO, it has everything".
So, your advice is "return to FFI" ?
Well, it turns out that the I/O system functions in System.Posix.IO may work for your purposes. I was able to get your example to work with these functions, which correspond to open(2), read(2), write(2).
I would also use these functions in C, as you did in your C program. Haskell I/O functions like hGetLine are analogous to C library I/O like fgets(3) - in particular, they're buffered, and I would guess that's why they don't work for you here.
Specifically, openFile "toA" WriteOnly Nothing defaultFileFlags openFile "fromA" ReadOnly Nothing defaultFileFlags
fdWrite toA str (str, len) <- fdRead fromA 64 return str
Great! Thank you very much. As I find, Posix.IO is not of the standard, but it is of GHC. Anyway, it fits my purpose. By openFile you, probably, mean openFd.
Another point is the number of open files, for a long loop. I put toA_IO = openFd "toA" WriteOnly Nothing defaultFileFlags fromA_IO = openFd "fromA" ReadOnly Nothing defaultFileFlags
axiomIO :: String -> IO String axiomIO str = do toA <- toA_IO fromA <- fromA_IO fdWrite toA str (str, _len) <- fdRead fromA 64 return str
When applying axiomIO in a loop of 9000 strings, it breaks: "too many open files". I do not understand why it is so, because toA_IO and fromA_IO are global constants (I have not any experience with `do').
Anyway, I have changed this to
toA = unsafePerformIO toA_IO fromA = unsafePerformIO fromA_IO axiomIO :: String -> IO String axiomIO str = do fdWrite toA str (str, _len) <- fdRead fromA 64 return str
And now, it works in loong loops too (I need to understand further whether my usage of unsafePerformIO really damages the project).
I'd say this use of unsafePerformIO is *not* safe. E.g. a Haskell compiler is allowed to evaluate the right hand side of toA and fromA multiple times. If you aren't 100% sure that it is ok to use unsafePerformIO, don't use it! Try something like the following:
initIO = do to <- toA_IO from <- fromA_IO return (to, from)
axiomIO (to,from) str = do fdWrite to str (str, _len) <- fdRead from 64 return str
main = do fds <- initIO … res <- axiomIO fds "…"
Obviously I didn't compile and test this code.
Its performance is 9/10 of the C <-> C performance (ghc -O, gcc -O, Linux Debian). It is still slow: 120000 small strings/second on a 2 GHz machine. But this is something to start with.
I was able to get your example to work with these functions, which correspond to open(2), read(2), write(2).
I would also use these functions in C, as you did in your C program. Haskell I/O functions like hGetLine are analogous to C library I/O like fgets(3) - in particular, they're buffered, and I would guess that's why they don't work for you here.
Indeed. Initially, I tried C <-> C, and used fgets, fputs, fflush. And it did not work, it required to open/close files inside a loop; I failed with attempts. Again, do not understand, why (do they wait till the buffer is full?).
Then, I tried read/write, as it is in fifoFromA.c which I posted. And it works. Now, Haskell <-> C gives a hope. Nice.
Thanks,
------ Sergei mechvel@botik.ru
_______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users