diff --git a/Data/IVar.hs b/Data/IVar.hs
--- a/Data/IVar.hs
+++ b/Data/IVar.hs
@@ -37,7 +37,7 @@
 
 module Data.IVar 
     ( IVar, new, write, read
-    , Reader, nonblocking, blocking
+    , Reader, nonblocking, blocking, combo
     )
 where
 
@@ -176,10 +176,24 @@
     r <- runReader reader
     case r of
         Left x -> return x
-        Right log -> do
-            blocker <- newEmptyMVar
-            cleanup <- forM log $ \(LogEntry var action) -> do
-                ident <- addAction var (\v -> tryPutMVar blocker (action v) >> return ())
-                return $ deleteAction var ident
-            blocking =<< takeMVar blocker
+        Right log -> primBlocking log
 
+primBlocking :: [LogEntry (Reader a)] -> IO a
+primBlocking log = do
+    blocker <- newEmptyMVar
+    cleanup <- forM log $ \(LogEntry var action) -> do
+        ident <- addAction var (\v -> tryPutMVar blocker (action v) >> return ())
+        return $ deleteAction var ident
+    blocking =<< takeMVar blocker
+
+-- | Combination nonblocking and blocking read.  @combo r@ 
+-- Returns @Left x@ if the value is available now, otherwise 
+-- returns @Right (blocking r)@.  This is more efficient than
+-- using nonblocking and blocking in sequence (it only evaluates
+-- the Reader once).
+combo :: Reader a -> IO (Either a (IO a))
+combo reader = do
+    r <- runReader reader
+    case r of
+        Left x -> return (Left x)
+        Right log -> return . Right $ primBlocking log
diff --git a/data-ivar.cabal b/data-ivar.cabal
--- a/data-ivar.cabal
+++ b/data-ivar.cabal
@@ -3,7 +3,7 @@
     Write-once variables, with the ability to block
     on the first of a set of variables to become 
     available.
-Version: 0.11
+Version: 0.20
 Stability: experimental
 Synopsis: Write-once variables with concurrency support
 License: BSD3
