Re: [Haskell-cafe] Code generation and optimisation for compiling Haskell

2012-01-13 Thread Thomas Schilling
JHC itself is based upon Boquist's GRIN language described in his PhD
thesis: Code Optimization Techniques for Lazy Functional Languages
http://mirror.seize.it/papers/Code%20Optimization%20Techniques%20for%20Lazy%20Functional%20Languages.pdf

On 13 January 2012 01:50, Jason Dagit dag...@gmail.com wrote:
 On Tue, Jan 10, 2012 at 9:25 AM, Steve Horne
 sh006d3...@blueyonder.co.uk wrote:

 Also, what papers should I read? Am I on the right lines with the ones I've
 mentioned above?

 Thomas Schilling gave you a good response with papers so I will give
 you a different perspective on where to look.

 Most of the Haskell implementations were written by academics studying
 languages and compilers.  This is good but it also implies that the
 implementors are likely to share biases and assumptions.  I know of
 one Haskell compiler in particular that was written by someone who did
 not know Haskell when starting the project.  The compiler was
 developed to be different than GHC.  That person was John Meacham.  He
 created JHC, a work in progress, so you might want to study his
 compiler and implementation notes as they should provide a different
 perspective on how to tackle Haskell implementation and optimization.

 http://repetae.net/computer/jhc/

 I hope that helps,
 Jason

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



-- 
Push the envelope. Watch it bend.

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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Chaddaï Fouché
On Thu, Jan 12, 2012 at 7:53 PM, Serge D. Mechveliani mech...@botik.ru wrote:
 People,

 (I wonder: is this for  beginn...@haskell.org ?)

I don't think so.


 I need to organize a  string interface  for a Haskell function
 Main.axiom  and a C program
                            fifoFromA.c

 via a pair of  named pipes  (in Linux, UNIX).
 The pipes are created before running, by the commands    mkfifo toA
                                                         mkfifo fromA

 Main.axiom  outputs a  string  to  toA  and inputs the respond string
                                            from  fromA  as the result.
 fifoFromA  inputs a string from  toA,
           converts it to the string  resStr,  outputs resStr to  fromA.

 Now that seems interesting, but just to be clear : did you choose
this solution (and why won't you use the FFI instead) or is this just
to see how to work it out ?

-- 
Jedaï

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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Serge D. Mechveliani
On Fri, Jan 13, 2012 at 04:34:37PM +0100, Chadda?? Fouch?? wrote:
 On Thu, Jan 12, 2012 at 7:53 PM, Serge D. Mechveliani mech...@botik.ru 
 wrote:
  People,
 
  (I wonder: is this for  beginn...@haskell.org ?)
 
 I don't think so.
 
 
  I need to organize a  string interface  for a Haskell function
  Main.axiom  and a C program
                             fifoFromA.c
 
  via a pair of  named pipes  (in Linux, UNIX).
  The pipes are created before running, by the commands    mkfifo toA
                                                          mkfifo fromA
 
  Main.axiom  outputs a  string  to  toA  and inputs the respond string
                                             from  fromA  as the result.
  fifoFromA  inputs a string from  toA,
            converts it to the string  resStr,  outputs resStr to  fromA.
 
  Now that seems interesting, but just to be clear : did you choose
 this solution (and why won't you use the FFI instead) or is this just
 to see how to work it out ?


Because it is a direct and the simplest approach. Why does one need a
foreign language, if all the needed functions are in the standard 
Haskell library?

Sergei.

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


[Haskell-cafe] [ANNOUNCE] JuicyPixels 1.0 - image loading library

2012-01-13 Thread Vincent Berthoux
Hello,

I'd like to announce the first release of JuicyPixels, an image loading library 
written entirely in Haskell. The focus of this library is ease of use and 
correct loading. In this first version the library is capable of the following 
actions :

 - PNG(.png) 
* Reading 
- 1,2,4,8 bits loading, Grayscale, 24bits, 24 bits with alpha,
  interleaved  filtered (fully compliant with the standard,
  tested against png suite).

* Writing
- 8bits RGB (non interleaved)
- 8bits RGBA (non interleaved)
- 8bits greyscale (non interleaved)

 - Bitmap (.bmp) (mainly used as a debug output format)
* Reading
- 24bits (RGB) images

* Writing
- 32bits (RGBA) per pixel images
- 24bits (RGB) per pixel images
- 8 bits greyscale (with palette)

 - Jpeg   (.jpg, .jpeg) 
* Reading non-interlaced baseline DCT image, seems to be OK
* Writing : none yet

I'm interested on any feedback regarding ease of use, performance and bugs.

GitHub : https://github.com/Twinside/Juicy.Pixels
Hackage : http://hackage.haskell.org/package/JuicyPixels

Thanks
Vincent Berthoux

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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Brandon Allbery
On Fri, Jan 13, 2012 at 12:25, Serge D. Mechveliani mech...@botik.ruwrote:

 On Fri, Jan 13, 2012 at 04:34:37PM +0100, Chadda?? Fouch?? wrote:
   Now that seems interesting, but just to be clear : did you choose
  this solution (and why won't you use the FFI instead) or is this just
  to see how to work it out ?

 Because it is a direct and the simplest approach. Why does one need a
 foreign language, if all the needed functions are in the standard
 Haskell library?


I hope you are aware of the many gotchas involved with FIFOs.  There are
very good reasons why they are not widely used.

-- 
brandon s allbery  allber...@gmail.com
wandering unix systems administrator (available) (412) 475-9364 vm/sms
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] STM atomic blocks in IO functions

2012-01-13 Thread Rob Stewart
Hi,

My question is regarding the correct us of STM in Haskell. I have put
to together a simple example, which represents more verbose code in a
library that I am writing.

The question is a simple one. Must all operations on a TVar happen
within *the same* atomically block, or am I am I guaranteed thread
safety if, say, I have a number of atomically blocks in an IO
function. Here's my example: http://pastebin.com/Hit5vKmk .

Is this example permissible?

thanks,

--
Rob Stewart

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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Donn Cave
Quoth Serge D. Mechveliani mech...@botik.ru,
[ ... why in Haskell instead of FFI ... ]

 Because it is a direct and the simplest approach. Why does one need a
 foreign language, if all the needed functions are in the standard 
 Haskell library?

The GHC Haskell library makes some compromises with normal I/O
functionality for the sake of its runtime thread system.  As
difficult as named pipes can be in any case, they can be even
trickier in GHC Haskell for this reason.  I didn't suggest an
FFI approach myself, in my previous follow-up, only because
if you haven't worked with the FFI it's a significant initial
investment, but I believe it's what I would do.  (If I were
somehow compelled to used named pipes.)

Donn

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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Michael Craig
Brandon, can you elaborate? Are you talking about UNIX named pipes or
FIFO/queue data structures in general?

Mike Craig



On Fri, Jan 13, 2012 at 12:39 PM, Brandon Allbery allber...@gmail.comwrote:

 On Fri, Jan 13, 2012 at 12:25, Serge D. Mechveliani mech...@botik.ruwrote:

 On Fri, Jan 13, 2012 at 04:34:37PM +0100, Chadda?? Fouch?? wrote:
   Now that seems interesting, but just to be clear : did you choose
  this solution (and why won't you use the FFI instead) or is this just
  to see how to work it out ?

 Because it is a direct and the simplest approach. Why does one need a
 foreign language, if all the needed functions are in the standard
 Haskell library?


 I hope you are aware of the many gotchas involved with FIFOs.  There are
 very good reasons why they are not widely used.

 --
 brandon s allbery  allber...@gmail.com
 wandering unix systems administrator (available) (412) 475-9364 vm/sms


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


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


Re: [Haskell-cafe] STM atomic blocks in IO functions

2012-01-13 Thread Bryan O'Sullivan
On Fri, Jan 13, 2012 at 10:04 AM, Rob Stewart
robstewar...@googlemail.comwrote:


 The question is a simple one. Must all operations on a TVar happen
 within *the same* atomically block, or am I am I guaranteed thread
 safety if, say, I have a number of atomically blocks in an IO
 function.


If you want successive operations to see a consistent state, they must
occur in the same atomically block.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] named pipes interface

2012-01-13 Thread Serge D. Mechveliani
I thank people for the notes.
People write that the example without  unsafePerformIO  is desirable.
So I present the improved question and improved, pure code.

--
I need to organize a  string interface  for a Haskell function  
Main.axiom  and a C program   
fifoFromA.c  

via a pair of  named pipes  (in Linux, UNIX).
The pipes are created before running, by the commandsmkfifo toA
 mkfifo fromA
 
Main.axiom  outputs a  string  to  toA  and inputs the respond string 
from  fromA  as the result.
fifoFromA  inputs a string from  toA, 
   converts it to the string  resStr,  outputs resStr to  fromA.

Main.axiom  must be able to be applied in a loop,
and there must be avoided repeated opening of a file/channel in a loop.
As an example, the string conversion in  fifoFromA.c  is put the 
conversion of each character to the lower case:

-- fifoFromA.c  --
#include string.h
#include stdio.h
#include fcntl.h

#define BOUND 64

int main()
{
  int  toA, fromA, i, numread;
  char buf[BOUND];

  toA = open(toA, O_RDONLY);  fromA = open(fromA, O_WRONLY);

  for (;;)
  {
numread = read(toA, buf, BOUND);
buf[numread] = '\0';
// printf(A:  Read from toA:  %s\n, buf);

i = 0; // convert the string to the lower case
while (i  numread) {buf[i] = tolower(buf[i]);  i++;}
write(fromA, buf, strlen(buf));
  }
}
---

For the to-A part writen in C  (instead of Haskell), this interface 
loop works all right.
With Haskell, I manage to process only the first string in the loop, 
and then it ends with an error.

Main.hs  is given below. Can you, please, fix the code?

Please, copy the response to  mech...@botik.ru

Thanks,

--
Sergei
mech...@botik.ru




import System.IO (IOMode(..), IO(..), Handle, openFile, hPutStr, 
  hGetLine, hFlush)

dir = showString /home/mechvel/ghc/axiomInterface/byLowerLevel/

toA_IO   = openFile (dir toA)   WriteMode:: IO Handle
   -- used as global values
fromA_IO = openFile (dir fromA) ReadMode --

axiomIO :: String - IO String
axiomIO str = do
  toA   - toA_IO
  fromA - fromA_IO  
  hPutStr toA str 
  hFlush toA
  hGetLine fromA
 
-- Example of usage --
main = do
   putStr str1  --  
   str1' - axiomIO str1
   putStr (str1' ++ \n)
   putStr str2  --  
   str2' - axiomIO str2
   putStr (str2' ++ \n)
   where
   n   = 9
   str0= ABC
   strings = [str0 ++ (show i) | i - [1 .. n]]
   str1: str2: _ = strings
--

I use  Glasgow Haskell  ghc-7.01.

Build: gcc -o fifoFromA fifoFromA.c
   ghc --make Main

Running:  first, command  ./fifoFromA
  on  terminal-2,
  then command./Main
  on  terminal-1.

And it processes only the first string:
terminal-1:
 m ./Main
 str1  --  abc1
 str2  --  Main: /home/mechvel/m/toA: 
openFile: does not exist (No such device or address)


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


Re: [Haskell-cafe] feed release plan

2012-01-13 Thread Simon Michael

Aha, thanks both.

The haskell organisation looks bigger, I think I'd like to upload feed there. Could the owner add contact info or a 
how-to-join note to the page ?


-Simon


On 1/10/12 12:22 PM, David Terei wrote:

There is also:

https://github.com/haskell

  where a bunch of us are hosting librari

On 10 January 2012 12:01, Erik de Castro Lopomle...@mega-nerd.com  wrote:

Haskell package janitors might be an appropriate one:

https://github.com/haskell-pkg-janitors




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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Serge D. Mechveliani
I (Sergei) am invesigating (so far) only Unix named pipes.

  I hope you are aware of the many gotchas involved with FIFOs.  
  There are very good reasons why they are not widely used.

At least in C - C, the Unix named pipes do work. 
And I am trying to replace the first end with Haskell.


On Fri, Jan 13, 2012 at 01:23:24PM -0500, Michael Craig wrote:
 Brandon, can you elaborate? Are you talking about UNIX named pipes or
 FIFO/queue data structures in general?
 
 Mike Craig
 
 
 On Fri, Jan 13, 2012 at 12:39 PM, Brandon Allbery allber...@gmail.comwrote:
 
  On Fri, Jan 13, 2012 at 12:25, Serge D. Mechveliani mech...@botik.ruwrote:
 
  On Fri, Jan 13, 2012 at 04:34:37PM +0100, Chadda?? Fouch?? wrote:
Now that seems interesting, but just to be clear : did you choose
   this solution (and why won't you use the FFI instead) or is this just
   to see how to work it out ?
 
  Because it is a direct and the simplest approach. Why does one need a
  foreign language, if all the needed functions are in the standard
  Haskell library?
 
 
  I hope you are aware of the many gotchas involved with FIFOs.  There are
  very good reasons why they are not widely used.
 
  --
  brandon s allbery  allber...@gmail.com
  wandering unix systems administrator (available) (412) 475-9364 vm/sms
 
 
  ___
  Haskell-Cafe mailing list
  Haskell-Cafe@haskell.org
  http://www.haskell.org/mailman/listinfo/haskell-cafe
 
 

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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Serge D. Mechveliani
On Fri, Jan 13, 2012 at 10:08:04AM -0800, Donn Cave wrote:
 Quoth Serge D. Mechveliani mech...@botik.ru,
 [ ... why in Haskell instead of FFI ... ]
 
  Because it is a direct and the simplest approach. Why does one need a
  foreign language, if all the needed functions are in the standard 
  Haskell library?
 
 The GHC Haskell library makes some compromises with normal I/O
 functionality for the sake of its runtime thread system.  As
 difficult as named pipes can be in any case, they can be even
 trickier in GHC Haskell for this reason.  I didn't suggest an
 FFI approach myself, in my previous follow-up, only because
 if you haven't worked with the FFI it's a significant initial
 investment, but I believe it's what I would do.  (If I were
 somehow compelled to used named pipes.)

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 ?

--
Sergei
mech...@botik.ru

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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Brandon Allbery
On Fri, Jan 13, 2012 at 13:23, Michael Craig mks...@gmail.com wrote:

 Brandon, can you elaborate? Are you talking about UNIX named pipes or
 FIFO/queue data structures in general?


I mean POSIX named pipes.  They work, but they don't do what most people
think they do, and they're rather annoying to work with in general.

-- 
brandon s allbery  allber...@gmail.com
wandering unix systems administrator (available) (412) 475-9364 vm/sms
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Serge D. Mechveliani
On Fri, Jan 13, 2012 at 04:34:37PM +0100, Chadda?? Fouch?? wrote:
 On Thu, Jan 12, 2012 at 7:53 PM, Serge D. Mechveliani mech...@botik.ru 
 wrote:
  [..]
  I need to organize a  string interface  for a Haskell function
  Main.axiom  and a C program
                             fifoFromA.c
 
  via a pair of  named pipes  (in Linux, UNIX).
  The pipes are created before running, by the commands    mkfifo toA
                                                          mkfifo fromA
 
  Main.axiom  outputs a  string  to  toA  and inputs the respond string
                                             from  fromA  as the result.
  fifoFromA  inputs a string from  toA,
            converts it to the string  resStr,  outputs resStr to  fromA.
 
  Now that seems interesting, but just to be clear : did you choose
 this solution (and why won't you use the FFI instead) or is this just
 to see how to work it out ?


I am trying to interface my large DoCon program for algebra to (a much 
larger algebra program) Axiom (the FriCAS license allows this).
And for many reasons, there is no real way for this except the  
string interface.  Further, the first candidate for the string interface 
is  Unix named pipes.
If the GHC IO cannot sufficiently work with named pipes, I would return
to the attempt with the Foreign Function Interface and C - C exchange.

Sergei.
mech...@botik.ru

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


Re: [Haskell-cafe] feed release plan

2012-01-13 Thread Johan Tibell
On Fri, Jan 13, 2012 at 10:46 AM, Simon Michael si...@joyful.com wrote:
 Aha, thanks both.

 The haskell organisation looks bigger, I think I'd like to upload feed
 there. Could the owner add contact info or a how-to-join note to the page ?

The Haskell organization on GitHub is for core libraries (i.e. the
Haskell Platform) only at this point. It exists to make it easier for
a few maintainers to maintain all those libraries.

-- Johan

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


Re: [Haskell-cafe] named pipe interface

2012-01-13 Thread Donn Cave
Quoth Serge D. Mechveliani mech...@botik.ru,
...
 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

Donn

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


Re: [Haskell-cafe] [Haskell] [ANNOUNCE] JuicyPixels 1.0 - image loading library

2012-01-13 Thread Daniel Díaz Casanueva
Thanks for this upload! I searched something like this a time ago. I'll
test it soon and, if I have any issue, send you some feedback. Thanks again
for the work. I made a library to work with PPM images (not released to
Hackage), but I'm glad to see a Haskell implementation of PNG and JPG.

Good luck,
Daniel Díaz.

On Fri, Jan 13, 2012 at 6:26 PM, Vincent Berthoux 
vincent.berth...@gmail.com wrote:

 Hello,

 I'd like to announce the first release of JuicyPixels, an image loading
 library written entirely in Haskell. The focus of this library is ease of
 use and correct loading. In this first version the library is capable of
 the following actions :

  - PNG(.png)
 * Reading
 - 1,2,4,8 bits loading, Grayscale, 24bits, 24 bits with alpha,
   interleaved  filtered (fully compliant with the standard,
   tested against png suite).

 * Writing
 - 8bits RGB (non interleaved)
 - 8bits RGBA (non interleaved)
 - 8bits greyscale (non interleaved)

  - Bitmap (.bmp) (mainly used as a debug output format)
 * Reading
 - 24bits (RGB) images

 * Writing
 - 32bits (RGBA) per pixel images
 - 24bits (RGB) per pixel images
 - 8 bits greyscale (with palette)

  - Jpeg   (.jpg, .jpeg)
 * Reading non-interlaced baseline DCT image, seems to be OK
 * Writing : none yet

 I'm interested on any feedback regarding ease of use, performance and bugs.

 GitHub : https://github.com/Twinside/Juicy.Pixels
 Hackage : http://hackage.haskell.org/package/JuicyPixels

 Thanks
 Vincent Berthoux


 ___
 Haskell mailing list
 hask...@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell


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


[Haskell-cafe] How to make asynchronous I/O composable and safe?

2012-01-13 Thread Joey Adams
I'm not happy with asynchronous I/O in Haskell.  It's hard to reason
about, and doesn't compose well.  At least in my code.

I'm currently trying to build a networking layer for my application
using Network.TLS.  Here is a rather minimalist API:

   newtype Connection = Connection (TLSCtx Handle)

   connectClient :: Handle         -- ^ Connection handle, as returned
by 'connectTo'
                 - X509           -- ^ TLS certificate (i.e. public key)
                 - IO Connection

   connectServer :: Handle         -- ^ Connection handle, as returned
by 'accept'
                 - X509           -- ^ TLS certificate (i.e. public key)
                 - TLS.PrivateKey -- ^ TLS private key
                 - IO Connection

   close :: Connection - IO ()

   sendMessage :: Connection - Message - IO ()

   recvMessage :: Connection - ByteString - IO (Message, ByteString)

The module provides little more than connection initialization and
message serialization.  I don't try to use locks or STM to multiplex
the connection or, in the case of recvMessage, hide connection state.
I just be sure to only use sendMessage in one thread at a time, only
use recvMessage in one thread at a time, and marshal the extra bytes
parameter of recvMessage from call to call (with the help of StateT).

I wrote a simple chat server to test it.  The client turned out okay:

   main :: IO ()
   main = do
       cert - getCertificate
       handle - connectTo localhost (PortNumber 1337)
       conn - connectClient handle cert
       _ - forkIO $ forever $ do
           s - getLine
           sendMessage conn $ TestMessage s
       forever $ flip runStateT B.empty $ do
           msg - StateT $ recvMessage conn
           case msg of
               TestMessage s -
                   liftIO $ putStrLn s
               _ -
                   liftIO $ hPrintf stderr
                       Warning: unrecognized message from server: %s\n
                       (messageTypeName msg)

The only glaring problem is that, if the user presses Ctrl+D, the
forked (sending) thread dies, but the main (receiving) thread lingers.
 I'd have to add exception handlers to ensure that when one thread
dies, the other thread dies too.

However, the server is an abomination (see attachment).

Unfortunately, it's not as simple as spawn one thread per client.
We need at least two threads, one to listen for messages from the
client, and another to send messages to the client.  GHC won't let us
simultaneously, in the same thread, wait for input from a connection
and wait for an STM transaction to succeed.

Another source of complexity is: what if we throw an exception at a
thread while it is in the middle of sending a packet?  Then we can't
shut down the connection properly (i.e. Network.TLS.bye), because the
receiver might think the close_notify packet is part of the
interrupted packet.

Having a thread for each client is good, as it:

 * Lets us think about each client separately.  No need to turn our
code inside out or write one big loop that juggles all the clients.

 * Isolates exceptions.  If sendMessage or recvMessage throws an
exception, it doesn't bring the whole server down.

On the other hand, having multiple threads interact with a single
client is hard to think about:

 * We have to synchronize the threads (e.g. when one dies, kill the other one)

 * Multiple places where an exception can arise

 * Can multiple threads interact with the connection handle simultaneously?

So why don't I make my connection API handle some of this?  Well, I
tried.  There are so many ways to do it, and I couldn't find a way
that simplified usage much.  The approach used by Handle and by
Network.TLS is to use MVars and IORefs to ensure that, if two threads
access the same connection, the connection doesn't become totally
corrupt.  If I do the same, then I'll have *three* layers of locking
under the hood.

Worse, the locking done by Handle and Network.TLS doesn't guarantee
much.  I don't know if it's safe to have one thread sending and
another thread receiving.  Especially in the case of Network.TLS,
where 'recvData' automatically handshakes in some cases, which sends
packets.  Since I don't know how much thread safety to expect, I can't
write networking code and know for sure that it is safe.

I'm certainly not protected from interleaved data if multiple threads
send on the same handle.  For example:

import Control.Concurrent
import System.IO

main :: IO ()
main = do
hSetBuffering stdout NoBuffering
_ - forkIO $ putStrLn One sentence.
putStrLn Another sentence.

produces:

AnOonteh esre nsteenntceen.c
e.

That is, I can't rely on putStrLn being atomic.  To produce
intelligible output (without changing the buffering mode), I have to
lock the output each time I write something.  putStrLn doesn't do it
for me.

=== Summary ===

In Haskell, sound logic and a great type system lead to elegant,
composable code in a variety of 

Re: [Haskell-cafe] How to make asynchronous I/O composable and safe?

2012-01-13 Thread Bardur Arantsson

On 01/14/2012 06:24 AM, Joey Adams wrote:

I'm not happy with asynchronous I/O in Haskell.  It's hard to reason
about, and doesn't compose well.  At least in my code.


[--snip--]

Async I/O *is* tricky if you're expecting threads to do their own 
writes/reads directly to/from sockets. I find that using a 
message-passing approach for communication makes this much easier.


If you need multiple server threads to respond to the same client 
(socket) then the easiest approach might be to simply use a (Chan a) for 
output. Since you always put full messages to the Chan, exceptions cause 
no problems with respect to partial messages, etc.


You can also use a Chan for forwarding messages from the client socket 
to the appropriate server threads -- if you need several (or even all) 
threads to receive messages from the client you can use dupChan on the 
input-from-client channel you pass to the server threads.


So, the API becomes something like:

   runSocketServer :: ((Chan a, Chan b) - IO ()) - ... - IO ()

where the first parameter contains the client logic and A is the 
type of the messages from the client and B is the type of the messages 
which are sent back to the client.


Hope this helps,



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