content: module Net.Wire where
  
  import Net.Concurrent
  import Net.Interface as Net
  
  type Wire m a = Interface m a a
  
  -- | An unbounded buffer
  --unbounded :: ChannelIO c m => m (Wire m a)
  unbounded () = 
     do channel <- newChan
        return Interface{rx=readChan channel,tx=writeChan channel}
  
  newWire () = bounded (unbounded ())
  newWire' n = bounded' n (unbounded ())
  
  bounded new = bounded' (10::Int) new
  
  
  -- | A bounded buffer that discards input when full
  bounded' buffersize newWire =
      do wire <- newWire
         size <- newMVar 0
         let tx p = do current <- takeMVar size
  		     if current<buffersize
  		       then do Net.tx wire p
  			       putMVar size (succ current)
  		       else putMVar size current -- discard p!
  	   rx   = do putMVar size . pred =<< takeMVar size
  		     Net.rx wire
         return Interface{rx=rx,tx=tx}
  
  
  timedWire () =
    do channel <- newChan
       let rxTimeout t =
  	     do u <- newRef () -- just something unique
  		t <- fork $ do delay t ; writeChan channel (Left u)
  		let read = do m <- readChan channel
  			      case m of
  				Right x -> return (Just x)
  				Left v | v==u -> return Nothing
  				       | otherwise -> read
  		x <- read
  		kill t
  		return x
           rxWait = do m <- readChan channel
  		     case m of
  		       Right x -> return (Just x)
  		       _ -> rxWait
  	 rx = maybe rxWait rxTimeout
  	 tx = writeChan channel . Right
       return (TimedInterface rx tx)
  