registerFd_ :: EventManager -> IOCallback -> Fd -> Event
            -> IO (FdKey, Bool)
registerFd_ mgr@(EventManager{..}) cb fd evs = do
  u <- newUnique emUniqueSource
  let fd'  = fromIntegral fd
      reg  = FdKey fd u
      !fdd = FdData reg evs cb
  (modify,ok) <- withMVar (callbackTableVar mgr fd) $ \tbl ->
    if haveOneShot && emOneShot
    then do
      oldFdd <- IT.insertWith (++) fd' [fdd] tbl
      let evs' = maybe evs (combineEvents evs) oldFdd
      ok <- I.modifyFdOnce emBackend fd evs'
      if ok
        then return (False, True)
        else IT.reset fd' oldFdd tbl >> return (False, False)
    else do
      oldFdd <- IT.insertWith (++) fd' [fdd] tbl
      let (oldEvs, newEvs) =
            case oldFdd of
              Nothing   -> (mempty, evs)
              Just prev -> (eventsOf prev, combineEvents evs prev)
          modify = oldEvs /= newEvs
      ok <- if modify
            then I.modifyFd emBackend fd oldEvs newEvs
            else return True
      if ok
        then return (modify, True)
        else IT.reset fd' oldFdd tbl >> return (False, False)
  -- this simulates behavior of old IO manager:
  -- i.e. just call the callback if the registration fails.
  when (not ok) (cb reg evs)
  return (reg,modify)

registerFd_ :: EventManager -> IOCallback -> Fd -> Event
            -> IO (FdKey, Bool)
registerFd_ mgr@(EventManager{..}) cb fd evs = do
  u <- newUnique emUniqueSource
  let fd'  = fromIntegral fd
      reg  = FdKey fd u
      !fdd = FdData reg evs cb
  (modify,ok) <- withMVar (callbackTableVar mgr fd) $ \tbl ->
    if haveOneShot && emOneShot
    then do
      oldFdd <- IT.insertWith (++) fd' [fdd] tbl
      let evs' = maybe evs (combineEvents evs) oldFdd
      ok <- I.modifyFdOnce emBackend fd evs'
      if ok
        then return (False, True)
        else IT.reset fd' oldFdd tbl >> return (False, False)
    else do
      oldFdd <- IT.insertWith (++) fd' [fdd] tbl
      let (oldEvs, newEvs) =
            case oldFdd of
              Nothing   -> (mempty, evs)
              Just prev -> (eventsOf prev, combineEvents evs prev)
          modify = oldEvs /= newEvs
      ok <- if modify
            then I.modifyFd emBackend fd oldEvs newEvs
            else return True
      if ok
        then return (modify, True)
        else IT.reset fd' oldFdd tbl >> return (False, False)
  -- this simulates behavior of old IO manager:
  -- i.e. just call the callback if the registration fails.
  when (not ok) (cb reg evs)
  return (reg,modify)

registerFd_ mgr@(EventManager{..}) cb fd evs = do
  u <- newUnique emUniqueSource
  let fd'  = fromIntegral fd
      reg  = FdKey fd u
      !fdd = FdData reg evs cb
  (modify,ok) <- withMVar (callbackTableVar mgr fd) $ \tbl ->
    if haveOneShot && emOneShot
    then do
      oldFdd <- IT.insertWith (++) fd' [fdd] tbl
      let evs' = maybe evs (combineEvents evs) oldFdd
      ok <- I.modifyFdOnce emBackend fd evs'
      if ok
        then return (False, True)
        else IT.reset fd' oldFdd tbl >> return (False, False)
    else do
      oldFdd <- IT.insertWith (++) fd' [fdd] tbl
      let (oldEvs, newEvs) =
            case oldFdd of
              Nothing   -> (mempty, evs)
              Just prev -> (eventsOf prev, combineEvents evs prev)
          modify = oldEvs /= newEvs
      ok <- if modify
            then I.modifyFd emBackend fd oldEvs newEvs
            else return True
      if ok
        then return (modify, True)
        else IT.reset fd' oldFdd tbl >> return (False, False)
  -- this simulates behavior of old IO manager:
  -- i.e. just call the callback if the registration fails.
  when (not ok) (cb reg evs)
  return (reg,modify)
