packages feed

io-memoize (empty) → 1.0.0.0

raw patch · 4 files changed

+167/−0 lines, 4 filesdep +basedep +spawnsetup-changed

Dependencies added: base, spawn

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2012, Dan Burton++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 Dan Burton 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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ io-memoize.cabal view
@@ -0,0 +1,44 @@+name:                io-memoize+version:             1.0.0.0+synopsis:            Memoize IO actions+description:+  Transform an IO action into a similar IO action+  that performs the original action only once.+  .+  You can choose to perform the original action+  in one of three ways:+  .+  (1) lazily (might never be performed)+  .+  (2) eagerly+  .+  (3) concurrently (eager)+  .+  Special thanks to shachaf and headprogrammingczar from #haskell irc+  for helping me reason about the behavior of this library.+++license:             BSD3+license-file:        LICENSE+author:              Dan Burton+maintainer:          danburton.email@gmail.com+copyright:           (c) 2012 Dan Burton++category:            System+build-type:          Simple+cabal-version:       >=1.8++library+  hs-source-dirs:    src+  exposed-modules:   System.IO.Memoize+  build-depends:     base == 4.*, spawn+  ghc-options:       -Wall++source-repository head+  type:     git+  location: git://github.com/DanBurton/io-memoize++source-repository this+  type:     git+  location: git://github.com/DanBurton/io-memoize+  tag:      io-memoize-1.0.0.0
+ src/System/IO/Memoize.hs view
@@ -0,0 +1,91 @@+-- | Memoize IO actions,+-- performing them at most once,+-- but recalling their result for subsequent invocations.+-- This library provides three sequencing strategies:+-- lazy ('ioMemo'), eager ('ioMemo''), and concurrent ('ioMemoPar').+-- +-- The lazy and eager approaches give stronger sequencing guarantees.+-- +-- The following property holds: @join . ioMemo === id@.+-- The same is true for @ioMemo'@ and @ioMemoPar@.+-- +-- Also, for the three memoizers in this library,+-- the memory allocated for the result will not+-- be available for garbage collection until the corresponding+-- memoized action is also available for garbage collection,+-- unless your compiler performs deep magicks.+module System.IO.Memoize (+    ioMemo+  , ioMemo'+  , ioMemoPar+  ) where++import Control.Concurrent.Spawn+import Control.Concurrent.MVar+import Data.IORef++-- | Memoize an IO action.+-- The action will be performed+-- the first time that it its value is demanded;+-- all subsequent invocations+-- will simply recall the value acquired+-- from the first call.+-- If the value is never demanded,+-- then the action will never be performed.+-- +-- This is basically a safe version of+-- 'System.IO.Unsafe.unsafeInterleaveIO'.+-- This function is also thread-safe:+-- it is guaranteed that the action passed in+-- will be performed exactly 0 or 1 times+-- by this code. Exceptions will be propagated+-- to the caller.+-- +-- Example usage:+-- +-- >>> getLine' <- ioMemo getLine+-- +-- >>> replicateM 3 getLine'+-- Hello+-- ["Hello", "Hello", "Hello"]+ioMemo :: IO a -> IO (IO a)+ioMemo action = do+  memo <- newIOMemoizer+  return (memo action)++-- | Memoize an IO action.+-- The action will be performed immediately;+-- all subsequent invocations+-- will recall the value acquired.+ioMemo' :: IO a -> IO (IO a)+ioMemo' action = do+  v <- action+  return (return v)++-- | Memoize an IO action.+-- The action will be performed immediately+-- in a spawned thread.+-- Attempts to access the result+-- will block until the action is finished.+-- +-- This is simply a synonym for 'Control.Concurrent.Spawn.spawn'+ioMemoPar :: IO a -> IO (IO a)+ioMemoPar = spawn++++newIOMemoizer :: IO (IO a -> IO a)+newIOMemoizer = do+  b <- newMVar True+  r <- newIORef undefined+  return (ioMemoizer b r)++ioMemoizer :: MVar Bool -> IORef a -> IO a -> IO a+ioMemoizer b r action = do+  modifyMVar_ b $ \isEmpty ->+    if isEmpty+      then do v <- action+              writeIORef r v+              return False+      else return False+  readIORef r