packages feed

gochan-0.0.1: weight/Main.hs

module Main where

import           Control.Concurrent             hiding (Chan)
import           Control.Concurrent.GoChan
import           Control.Monad
import           System.IO.Unsafe
import           Weigh

main :: IO ()
main =
    mainWith
        (do io "creating a channel" chanConstruction ()
            io "unbuffered send & recv" unbufferedSendRecv chanUnbuffered
            io "unbuffered select send & recv" unselectSendRecv chanUnbuffered
            io "unbuffered recv" simpleRecv chanUnbufferedAlreadySent
            io "unbuffered select recv" unbufferedSendRecv chanUnbufferedAlreadySent
            io "buffered send" simpleSend chanBufferedEmpty
            io "buffered recv" simpleRecv chanBufferedAlreadySent
            io "buffered select send" selectSend chanBufferedEmpty
            io "buffered select recv" selectRecv chanBufferedAlreadySent)

chanConstruction :: () -> IO ()
chanConstruction = const (void (chanMake 0 :: IO (Chan Int)))

unbufferedSendRecv :: Chan Int -> IO ()
unbufferedSendRecv c = do
    forkIO $ chanSend c 0
    chanRecv c
    return ()

unselectSendRecv :: Chan Int -> IO ()
unselectSendRecv c = do
    forkIO $ chanSelect [Send c 0 (return ())] Nothing
    chanSelect [Recv c (const (return ()))] Nothing
    return ()

simpleSend :: Chan Int -> IO ()
simpleSend c = chanSend c 0

simpleRecv :: Chan Int -> IO ()
simpleRecv c = void (chanRecv c)

selectSend :: Chan Int -> IO ()
selectSend c = chanSelect [Send c 0 (return ())] Nothing

selectRecv :: Chan Int -> IO ()
selectRecv c = chanSelect [Recv c (const (return ()))] Nothing

--------------------------------------------------------------------------------
-- We don't want these to show up in allocations, so carefully unsafePerformIO
-- here. The threading is scary, but I can't think of any other way to test
-- this, given the concurrent nature of this library.
{-# NOINLINE chanUnbuffered #-}

chanUnbuffered :: Chan Int
chanUnbuffered = unsafePerformIO (chanMake 0)

{-# NOINLINE chanUnbufferedAlreadySent #-}

chanUnbufferedAlreadySent :: Chan Int
chanUnbufferedAlreadySent =
    unsafePerformIO $
    do c <- chanMake 0
       forkIO $ chanSend c 0
       return c

{-# NOINLINE chanBufferedEmpty #-}

chanBufferedEmpty :: Chan Int
chanBufferedEmpty = unsafePerformIO (chanMake 1)

{-# NOINLINE chanBufferedAlreadySent #-}

chanBufferedAlreadySent :: Chan Int
chanBufferedAlreadySent =
    unsafePerformIO $
    do c <- chanMake 1
       chanSend c 0
       return c