       hyperclientDestroy hc
       mapM_ (\(HandleCallback cont) -> cont Nothing) $ Map.elems handles 
       putMVar c (Nothing, Map.empty)
+
+-- | Wait for graceful termination of all outstanding requests and
+-- then close the connection.
+--
+-- /Note:/ If it is necessary to have this operation complete quickly
+-- and outstanding requests are not needed, then use 'forceClose'.
+close :: Client -> IO ()
+close client@(getClient -> c) = do
+  clientData <- takeMVar c
+  case clientData of
+    (Nothing, _)        -> error "HyperDex client error - cannot close a client connection twice."
+    (Just hc, handles)  -> do
+      case Map.null handles of
+        True  -> do
+          hyperclientDestroy hc
+          putMVar c (Nothing, Map.empty)
+        False -> do
+          -- Have to put it back in order to run loopClient
+          (_, newHandles) <- handleLoop hc handles
+          putMVar c (Just hc, newHandles)
+          close client
 
 doExponentialBackoff :: Int -> Double -> (Int, BackoffMethod)
 doExponentialBackoff b x = 

-- is closed ought to return a 'ReturnCode' indicating the failure
-- condition, but the behavior is ultimately undefined. Any pending
-- requests should be disregarded. 
close :: Client -> IO ()
close (getClient -> c) = do
  clientData <- takeMVar c
  case clientData of
    (Nothing, _)        -> error "HyperDex client error - cannot close a client connection twice."

  doDelay >> return nextDelay
{-# INLINE performBackoff #-}

-- | Runs a single iteration of hyperclient_loop, returning whether
-- or not a handle was completed and a new set of callbacks.
--
-- This function does not use locking around the client.
handleLoop :: Hyperclient -> Map Handle HandleCallback -> IO (Maybe Handle, Map Handle HandleCallback)
handleLoop hc handles = do
  -- TODO: Examine returnCode for things that might matter.
  (handle, returnCode) <- hyperclientLoop hc 0
  case returnCode of
    HyperclientSuccess -> do
      let clearedMap = Map.delete handle handles
      resultMap <- do
        case Map.lookup handle handles of
          Just (HandleCallback entry) -> do
            cont <- entry $ Just returnCode
            case cont of
              Nothing     -> return clearedMap
              Just (h, e) -> return $ Map.insert h e clearedMap
          Nothing -> return clearedMap
      return $ (Just handle, resultMap)
    HyperclientTimeout -> do
      handleLoop hc handles
    HyperclientNonepending -> do
      mapM_ (\(HandleCallback cont) -> cont Nothing) $ Map.elems handles
      return $ (Just handle, Map.empty)
    _ -> do
      handleLoop hc handles

{-# INLINE handleLoop #-}

-- | Runs hyperclient_loop exactly once, setting the appropriate MVar.
loopClient :: Client -> IO (Maybe Handle)
loopClient (getClient -> c) = do
  clientData <- takeMVar c
  case clientData of
    (Nothing, _)       -> error "HyperDex client error - client has been closed."
    (Just hc, handles) -> do
      (maybeHandle, newHandles) <- handleLoop hc handles
      putMVar c (Just hc, newHandles)
      return maybeHandle
{-# INLINE loopClient #-}

-- | Run hyperclient_loop at most N times or forever until a handle
