Permalink
Browse files

boot

  • Loading branch information...
0 parents commit f3ae00d9e460348908b441adbabef8d353fd1557 @paolino committed Mar 24, 2011
Showing with 190 additions and 0 deletions.
  1. +30 −0 LICENSE
  2. +2 −0 Setup.hs
  3. +92 −0 System/Timer/Updatable.hs
  4. +66 −0 timers-updatable.cabal
30 LICENSE
@@ -0,0 +1,30 @@
+Copyright (c)2011, Paolo Veronelli
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of Paolo Veronelli nor the names of other
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
@@ -0,0 +1,92 @@
+-- | An updatable timer is a timer for which it is possible to update the remaining time.
+--
+-- Any number of threads can be hanged on one timer and they will all continue when the timer rings or when it is destroyed.
+--
+-- Parallel and serial update politics are implemented.
+--
+-- In the example we start a timer with a time to wait of 10 seconds, hang 2 threads which will wait for it to finish and update
+-- it after 5 seconds to wait for 6 seconds.
+-- It will complete and run its action and the hanged threads after 11 seconds because of its parallel nature.
+-- The serial timer would have ringed after 16 seconds.
+--
+-- @
+-- import Control.Concurrent
+-- import System.Timer.Updatable
+-- import Data.Maybe
+-- main = do
+-- t <- parallel (return 5) $ 10^7
+-- forkIO $ wait t >>= print . (+1) . fromJust
+-- forkIO $ wait t >>= print . (+2) . fromJust
+-- threadDelay $ 5 * 10 ^ 6
+-- renew t $ 6 * 10 ^ 6
+-- wait t >>= print . fromJust
+-- @
+
+
+module System.Timer.Updatable (Updatable (..), parallel, serial, Delay) where
+
+import Data.Maybe
+import Control.Concurrent
+import Control.Monad (when, void)
+import Control.Concurrent.STM
+
+-- | A delay in microseconds
+type Delay = Int
+
+-- | Abstract timers that can be updated. Hanging via wait function can be done by any number of threads, which is sinchronization.
+data Updatable a = Updatable {
+ wait :: IO (Maybe a), -- ^ wait until the timer rings, or signal Nothing if timer is destroyed
+ renew :: Delay -> IO (), -- ^ update the delay in the timer
+ kill :: IO () -- ^ destoy the timer
+ }
+
+-- wrap the logic with a framework for signalling the time is over
+engine :: IO () -> (Delay -> IO ()) -> IO a -> Delay -> IO (Updatable a)
+engine k t w d0 = do
+ x <- newEmptyTMVarIO
+ t d0
+ p <- forkIO $ w >>= atomically . putTMVar x . Just
+ return $ Updatable (atomically $ takeTMVar x >>= \r -> putTMVar x r >> return r) t (k >> killThread p >> atomically (putTMVar x Nothing))
+
+-- | Create and start a parallel updatable timer. This timer renew actions will start parallel timers. Last timer that is over will compute the given action.
+parallel :: IO a -- ^ the action to run when timer rings
+ -> Delay -- ^ time to wait
+ -> IO (Updatable a) -- ^ the updatable parallel timer
+parallel a d0 = do
+ tz <- newTVarIO 0
+ tp <- newTVarIO []
+ let
+ t k = do
+ p <- forkIO $ atomically (readTVar tz >>= writeTVar tz . (+1)) >> threadDelay k >> atomically (readTVar tz >>= writeTVar tz . (subtract 1))
+ atomically $ readTVar tp >>= writeTVar tp . (p :)
+ w = do
+ atomically $ do
+ z <- readTVar tz
+ when (z > 0) retry
+ a
+ k = atomically (readTVar tp) >>= mapM_ killThread
+ engine k t w d0
+
+-- | Create and start a serial updatable timer. This timer renew action will schedule new timer after the running one. The timer will run the given action after the sum of all scheduled times is over.
+serial :: IO a -- ^ the action to run when timer rings
+ -> Delay -- ^ time to wait
+ -> IO (Updatable a) -- ^ the updatable parallel timer
+serial a d0 = do
+ tz <- newTChanIO
+ let
+ t = atomically . writeTChan tz
+ w = do
+ l <- atomically $ (Just `fmap` readTChan tz) `orElse` return Nothing
+ case l of
+ Nothing -> a
+ Just l -> threadDelay l >> w
+ engine (return ()) t w d0
+
+main = do
+ t <- parallel (return 5) $ 10^7
+ forkIO $ wait t >>= print . (+1) . fromJust
+ forkIO $ wait t >>= print . (+2) . fromJust
+ threadDelay $ 5 * 10 ^ 6
+ renew t $ 6 * 10 ^ 6
+ wait t >>= print . fromJust
+
@@ -0,0 +1,66 @@
+-- timer.cabal auto-generated by cabal init. For additional options,
+-- see
+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.
+-- The name of the package.
+Name: timers-updatable
+-- The package version. See the Haskell package versioning policy
+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for
+-- standards guiding when and how versions should be incremented.
+Version: 0.1
+
+-- A short (one-line) description of the package.
+Synopsis: timers which are updatable in the remaining time
+
+-- A longer description of the package.
+Description: Timers implemented in this package can be used to sinchronize threads to continue all together when the timer rings. While the timer is running it can be updated in the remaining time. A parallel and serial update policy is provided.
+
+-- URL for the project homepage or repository.
+Homepage: http://github.com/paolino/timers-updatable
+
+-- The license under which the package is released.
+License: BSD3
+
+-- The file containing the license text.
+License-file: LICENSE
+
+-- The package author(s).
+Author: Paolo Veronelli
+
+-- An email address to which users can send suggestions, bug reports,
+-- and patches.
+Maintainer: paolo.veronelli@gmail.com
+
+-- A copyright notice.
+-- Copyright:
+
+Category: Concurrency
+
+Build-type: Simple
+
+-- Extra files to be distributed with the package, such as examples or
+-- a README.
+-- Extra-source-files:
+
+-- Constraint on the version of Cabal needed to build this package.
+Cabal-version: >=1.6
+
+
+Library
+ -- Modules exported by the library.
+ Exposed-modules:
+ System.Timer.Updatable
+
+ -- Packages needed in order to build this package.
+ Build-depends:
+ base < 5,
+ stm
+
+ -- Modules not exported by this package.
+ -- Other-modules:
+
+ -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.
+ -- Build-tools:
+
+source-repository head
+ type: git
+ location: git://github.com/paolino/timers-updatable.git

0 comments on commit f3ae00d

Please sign in to comment.