[Haskell-cafe] [tryReadAdvChan :: AdvChan a -> IO (Maybe a)] problems

Belka lambda-belka at yandex.ru
Fri May 1 00:09:01 EDT 2009


Hi!

I need this function with requirement of heavy reads, *possibly under DDoS
attack*. 
Was trying to write such function, but discovered some serious problems of 
** possible racings, 
** possible starvations 
** unbalance: readAdvChan users may get better service than ones of
tryReadAdvChan
These are totally unacceptible for my case of DDoS risk.

Actually, am I wrong thinking, that it can't be helped - and the degradation
from cute concurency synchronization model of Chan is unavoidable? 

My (untested) code:
-------------------------------------------
-------------------------------------------
module AdvChan ( AdvChan
               , newAdvChan
               , readAdvChan
               , writeAdvChan
               , writeList2AdvChan
               , advChan2StrictList
               , withResourceFromAdvChan
               , tryReadAdvChan
               , isEmptyAdvChan
               ) where

import Control.Concurrent.Chan
import Control.Concurrent.MVar

data AdvChan a = AdvChan { 
        acInst    :: MVar Chan a
      , acWrite   :: a -> IO ()
      , acIsEmpty :: IO Bool
}

newAdvChan :: IO AdvChan a 
newAdvChan = do ch    <- newChan 
                mv_ch <- newMVar ch 
                return AdvChan {
                         acInst    = mv_ch
                       , acWrite   = writeChan ch
                       , acIsEmpty = isEmptyChan ch
                       }

readAdvChan :: AdvChan a -> IO a
readAdvChan ach = modifyMVar (acInst ach) 
                             (\ ch -> do a <- readChan ch
                                         return (ch, a)
                             )

writeAdvChan :: AdvChan a -> a -> IO ()
writeAdvChan = acWrite

writeList2AdvChan :: AdvChan a -> [a] -> IO ()
writeList2AdvChan ach    [] = return ()
writeList2AdvChan ach (h:t) = writeAdvChan ach h >> writeList2AdvChan ach t

advChan2StrictList :: AdvChan a -> IO [a]
advChan2StrictList ach = modifyMVar (acInst ach) 
                                    (\ ch -> let readLoop = do emp <-
isEmptyChan ch
                                                               case emp of
                                                                   True  ->
return []
                                                                   False ->
do _head <- readChan ch
                                                                              
_rest <- readLoop
                                                                              
return (_head : _rest)
                                              in liftTuple (return ch,
readLoop)
                                    )

withResourceFromAdvChan :: AdvChan a -> (\ a -> IO (a, b)) -> IO b
withResourceFromAdvChan ach f = do res <- readAdvChan ach
                                   (res_processed, result) <- f res
                                   writeAdvChan ach res_processed
                                   return result

isEmptyAdvChan :: AdvChan a -> IO Bool
isEmptyAdvChan = acIsEmpty

microDelta = 50

tryReadAdvChan :: AdvChan a -> IO (Maybe a)
tryReadAdvChan ach = emp2Maybeness $ do mb_inst <- tryTakeMVar (acInst ach)
                                        case mb_inst of
                                            Nothing   -> emp2Maybeness
(threadDelay microDelta >> tryReadAdvChan ach)
                                            Just chan -> do emp <-
isEmptyChan ch 
                                                            result <- case
emp of
                                                                         
True  -> return Nothing
                                                                         
False -> Just `liftM` readChan ch
                                                            putMVar (acInst
ach) chan
                                                            return result
      where emp2Maybeness f = do emp <- isEmptyAdvChan ach
                                 case emp of
                                     True  -> return Nothing
                                     False -> f

-------------------------------------------
-------------------------------------------

Later after writing my own code, and understanding the problem I checked
Hackage. Found "synchronous-channels" package there
(http://hackage.haskell.org/cgi-bin/hackage-scripts/package/synchronous-channels),
but it isn't any further in solving my the unbalacedness problems. 

Any suggestions on the fresh matter are welcome.
Belka.
-- 
View this message in context: http://www.nabble.com/-tryReadAdvChan-%3A%3A-AdvChan-a--%3E-IO-%28Maybe-a%29--problems-tp23328237p23328237.html
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.



More information about the Haskell-Cafe mailing list