packages feed

data-quotientref (empty) → 0.1

raw patch · 3 files changed

+106/−0 lines, 3 filesdep +basesetup-changed

Dependencies added: base

Files

+ Data/QuotientRef.hs view
@@ -0,0 +1,88 @@+----------------------------------------+-- |+-- Module    : Data.QuotientRef+-- Copyright : (c) Luke Palmer 2008+-- License   : BSD3+--+-- Maintainer : Luke Palmer <lrpalmer@gmail.com>+-- Stability : experimental+--+-- A Quotient Reference is a reference cell that needs two values to+-- dereference.  In a way it is a two-dimensional table indexed by references.+-- The trick is that if a cell is indexed by @a@ and @b@, then if /either/+-- @a@ or @b@ gets cleaned up by the garbage collector, then so does the+-- cell, because it would not be able to be accessed anymore.+--+-- There are two different types of indices, "LeftRef" and "RightRef".  You+-- need one of each, of the same type, to access a cell.+--+-- The name comes from the idea that the product of two indices is a reference,+-- so each index is a quotient.+--+-- Example usage:+--+-- > do+-- >   l_1 <- newLeft+-- >   l_2 <- newLeft+-- >   r_1 <- newRight+-- >   r_2 <- newRight+-- >   write l_1 r_1 "Foo"+-- >   write l_2 r_1 "Bar"+-- >   print =<< read l_1 r_1  -- Just "Foo"+-- >   print =<< read l_1 r_2  -- Nothing+-- >   print =<< read l_2 r_1  -- Just "Bar"+-- >   print =<< read l_2 r_2  -- Nothing+-- +module Data.QuotientRef +    ( LeftRef, RightRef+    , newLeft, newRight+    , read, write+    )+where++import Prelude hiding (read)+import qualified Data.HashTable as Hash+import Data.Unique+import Control.Applicative+import Control.Exception+import Control.Monad+import System.Mem.Weak++-- | The left half of a reference cell.  Combine this with a "RightRef" to+-- access a cell.+newtype LeftRef a+    = LeftRef (Hash.HashTable Unique a)++-- RightRef is data rather than newtype, so we have something real to make +-- a weak reference from.++-- | The right half of a reference cell.  Combine this with a "LeftRef" to+-- access a cell.+data RightRef a+    = RightRef Unique+++newLeft :: IO (LeftRef a)+newLeft = LeftRef <$> Hash.new (==) (fromIntegral . hashUnique)++newRight :: IO (RightRef a)+newRight = RightRef <$> newUnique++-- | Combine the two halves of a reference and return the result if+-- it exists.+read :: LeftRef a -> RightRef a -> IO (Maybe a)+read (LeftRef hash) (RightRef ident) = do+    Hash.lookup hash ident++-- | Combine the two halves of a reference and write a value to the+-- product.+write :: LeftRef a -> RightRef a -> a -> IO ()+write (LeftRef hash) right@(RightRef ident) val = block $ do+    existed <- Hash.update hash ident val+    unless existed $ do+        hashW <- mkWeakPtr hash Nothing+        addFinalizer right $ do+            h <- deRefWeak hashW+            case h of+                Nothing -> return ()+                Just h' -> Hash.delete h' ident
+ Setup.lhs view
@@ -0,0 +1,4 @@+#! /usr/bin/env runhaskell++> import Distribution.Simple+> main = defaultMain
+ data-quotientref.cabal view
@@ -0,0 +1,14 @@+Name: data-quotientref+Description:+    Reference cells that need two independent indices to be accessed.+Version: 0.1+Stability: experimental+Synopsis: Reference cells that need two independent indices to be accessed.+License: BSD3+Category: Data+Author: Luke Palmer+Maintainer: lrpalmer@gmail.com+Build-Type: Simple+Build-Depends: base+Exposed-Modules: Data.QuotientRef+Extensions: