diff --git a/Control/Concurrent/Spawn.hs b/Control/Concurrent/Spawn.hs
--- a/Control/Concurrent/Spawn.hs
+++ b/Control/Concurrent/Spawn.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE
+    CPP #-}
 module Control.Concurrent.Spawn
   ( -- * Spawn 
     spawn
@@ -5,12 +7,18 @@
     -- * Spawn with @'try'@
   , Result
   , spawnTry
-  
+
+    -- * Higher-level functions
+  , parMapIO
+  , parMapIO_
+  , (|*|)
+
     -- * Limiting concurrency
   , pool ) where
 
 import Control.Concurrent
 import Control.Exception
+import Control.Monad
 
 -- | Two ways a computation of type @'IO' a@ can end.
 type Result a = Either SomeException a
@@ -18,14 +26,29 @@
 -- | Spawn a concurrent computation.  Produces an action which
 -- demands a @'Result'@.
 spawnTry :: IO a -> IO (IO (Result a))
+
+-- We block asynchronous exceptions around 'forkIO', then restore
+-- the parent thread's exception mask state inside 'try'. This
+-- prevents an exception from interrupting 'putMVar', which would
+-- deadlock the parent.
+--
+-- The API for doing this changed in base-4.3 with GHC 7.0.
+
+#if MIN_VERSION_base(4,3,0)
 spawnTry m = do
   v <- newEmptyMVar
-  -- block async exns, then unblock inside 'try' unless parent was blocked
-  -- avoids dropping an exception
+  _ <- mask $ \restore -> forkIO (try (restore m) >>= putMVar v)
+  return (readMVar v)
+
+#else
+spawnTry m = do
+  v <- newEmptyMVar
   b <- blocked
   _ <- block $ forkIO (try (if b then m else unblock m) >>= putMVar v)
   return (readMVar v)
 
+#endif
+
 -- | Spawn a concurrent computation.  Produces an action which
 -- demands the result.  Any exception from the original computation
 -- is re-thrown when and where the result is demanded.
@@ -34,6 +57,7 @@
   r <- spawnTry m
   return (r >>= either throwIO return)
 
+
 -- | Given /n/, produces a function to wrap @'IO'@ actions.
 -- No more than /n/ wrapped actions will be in progress at
 -- one time.
@@ -41,3 +65,31 @@
 pool n = do
   s <- newQSem n
   return $ bracket_ (waitQSem s) (signalQSem s)
+
+
+-- | Execute a separate thread of IO for each element of a list, and
+-- collect results.
+--
+-- The analogy to @parMap@ is misleading.  The concurrent execution
+-- of these actions is non-deterministic and can affect results.
+-- However, @'parMapIO'@ is expected to be most useful for actions
+-- which do not interact.
+parMapIO :: (a -> IO b) -> [a] -> IO [b]
+parMapIO f xs = mapM (spawn . f) xs >>= sequence
+
+-- | Execute a separate thread of IO for each element of a list.
+--
+-- Results are discarded, but the @'parMapIO_'@ action does not
+-- complete until all threads have finished.
+parMapIO_ :: (a -> IO b) -> [a] -> IO ()
+parMapIO_ f xs = mapM (spawn . f) xs >>= sequence_
+
+
+infixl 4 |*|
+
+-- | A concurrent version of @'ap'@ or @(\<*\>)@ for @'IO'@.
+--
+-- Spawns a thread for the right-hand action, while executing the
+-- left-hand action in the current thread.
+(|*|) :: IO (a -> b) -> IO a -> IO b
+mf |*| mx = spawn mx >>= (mf `ap`)
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) Keegan McAllister 2010
+Copyright (c) Keegan McAllister 2010, 2011
 
 All rights reserved.
 
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,9 @@
+spawn is a tiny Haskell library for concurrent computations.
+
+Documentation is hosted at http://hackage.haskell.org/package/spawn
+
+To build the documentation yourself, run
+
+  $ cabal configure && cabal haddock --hyperlink-source
+
+This will produce HTML documentation under dist/doc/html/spawn.
diff --git a/spawn.cabal b/spawn.cabal
--- a/spawn.cabal
+++ b/spawn.cabal
@@ -1,19 +1,40 @@
 name:                spawn
-version:             0.2
+version:             0.3
 license:             BSD3
 license-file:        LICENSE
-synopsis:            Tiny library for joinable computations / threads with results.
+synopsis:            Tiny library for concurrent computations
 category:            Concurrency, Concurrent, Control
 author:              Keegan McAllister <mcallister.keegan@gmail.com>
 maintainer:          Keegan McAllister <mcallister.keegan@gmail.com>
 build-type:          Simple
-cabal-version:       >=1.2
+cabal-version:       >=1.6
 description:
   Spawn a concurrent 'IO' computation and later demand its result.  Tiny API
   and implementation.
+  .
+  New in version 0.3:
+  .
+    * Added functions @parMapIO@, @parMapIO_@, and @(|*|)@, which capture
+      common use cases of @spawn@.
+  .
+    * Updated code to avoid using deprecated functions with @base-4.3@ and
+      later (GHC 7.0 and later).  The old code is still used with older
+      @base@ libraries.
+  .
+    * Added public GitHub repository.
 
+extra-source-files:
+  README
+
 library
   exposed-modules:   Control.Concurrent.Spawn
   ghc-options:       -Wall
   build-depends:
       base >= 3 && < 5
+
+  other-extensions:
+      CPP
+
+source-repository head
+    type:     git
+    location: git://github.com/kmcallister/spawn.git
