diff --git a/alarmclock.cabal b/alarmclock.cabal
--- a/alarmclock.cabal
+++ b/alarmclock.cabal
@@ -1,5 +1,5 @@
 name:                alarmclock
-version:             0.2.0.7
+version:             0.2.0.8
 synopsis:            Wake up and perform an action at a certain time.
 description:         Wake up and perform an action at a certain time.
 homepage:            https://bitbucket.org/davecturner/alarmclock
diff --git a/src/Control/Concurrent/AlarmClock.hs b/src/Control/Concurrent/AlarmClock.hs
--- a/src/Control/Concurrent/AlarmClock.hs
+++ b/src/Control/Concurrent/AlarmClock.hs
@@ -10,7 +10,7 @@
 The alarm can be set multiple times, and in this case the alarm will go off at
 the earliest requested time. If the alarm is set in the past, the action will
 run immediately. When the action runs, it clears all future alarms; the action
-can itself return the time at which it should run again.
+can itself set the next alarm time.
 
 To perform time-based cache expiry, create an 'AlarmClock' whose action flushes
 any stale entries from the cache and then calls `setAlarm` for the next time
@@ -23,7 +23,9 @@
 module Control.Concurrent.AlarmClock
   ( AlarmClock()
   , newAlarmClock
+  , newAlarmClock'
   , destroyAlarmClock
+  , withAlarmClock
   , setAlarm
   , setAlarmSTM
   , setAlarmNow
@@ -35,7 +37,7 @@
 import Control.Concurrent (forkIO, newEmptyMVar, readMVar, putMVar)
 import Control.Concurrent.STM (STM, atomically, retry, TVar, newTVar, writeTVar, readTVar, modifyTVar')
 import Control.Concurrent.Timeout (timeout)
-import Control.Exception (finally)
+import Control.Exception (finally, bracket)
 import Control.Monad (void)
 import Data.Time (UTCTime, diffUTCTime, getCurrentTime)
 import GHC.Conc (labelThread, myThreadId)
@@ -77,6 +79,11 @@
 destroyAlarmClock :: AlarmClock -> IO ()
 destroyAlarmClock AlarmClock{..} = atomically (writeTVar acNewSetting AlarmDestroyed) >> acWaitForExit
 
+{-| The action @withAlarmClock onWakeUp inner@ runs @inner@ with a new 'AlarmClock' which
+is destroyed when @inner@ exits. -}
+withAlarmClock :: (AlarmClock -> UTCTime -> IO ()) -> (AlarmClock -> IO a) -> IO a
+withAlarmClock onWakeUp inner = bracket (newAlarmClock' onWakeUp) destroyAlarmClock inner
+
 {-| Make the 'AlarmClock' go off at (or shortly after) the given time.  This
 can be called more than once; in which case, the alarm will go off at the
 earliest given time. -}
@@ -133,7 +140,7 @@
       Nothing -> actAndContinue currentTime
       Just newSetting -> go newSetting
 
-  -- Times out immediately if the duration is negative (unlike 'timeout' which waits forever)
+  -- Times out immediately if the duration is nonpositive (unlike 'timeout' which waits forever)
   safeTimeout dt action
     | dt > 0    = timeout dt action
     | otherwise = return Nothing
