packages feed

discord-haskell-voice-2.2.0: src/Discord/Internal/Voice/CommonUtils.hs

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE LambdaCase #-}
{-|
Module      : Discord.Internal.Voice.CommonUtils
Description : Strictly for internal use only. See Discord.Voice for the public interface.
Copyright   : (c) Yuto Takano (2021)
License     : MIT
Maintainer  : moa17stock@gmail.com

= WARNING

This module is considered __internal__.

The Package Versioning Policy __does not apply__.

The contents of this module may change __in any way whatsoever__ and __without__
__any warning__ between minor versions of this package.

= Description

This module provides useful utility functions used in discord-haskell-voice.
-}
module Discord.Internal.Voice.CommonUtils where

import Control.Concurrent
import Control.Concurrent.Async ( race )
import Control.Lens
import Data.Text qualified as T
import Data.Time.Clock.POSIX
import Data.Time
import GHC.Weak

-- | @tshow@ is a shorthand alias for @T.pack . show@.
tshow :: Show a => a -> T.Text
tshow = T.pack . show

-- | @maybeToRight@ puts the maybe value into the right hand side of the Either,
-- with a default value provided for the Left as the first argument.
maybeToRight :: a -> Maybe b -> Either a b
maybeToRight a = maybe (Left a) Right

-- | @doOrTimeout@ performs an IO action for a maximum of @millisec@ milliseconds.
doOrTimeout :: Int -> IO a -> IO (Maybe a)
doOrTimeout millisec longAction = (^? _Right) <$> race waitSecs longAction
  where
    waitSecs :: IO (Maybe b)
    waitSecs = threadDelay (millisec * 10^(3 :: Int)) >> pure Nothing

-- | @killWkThread@ kills a thread referenced by Weak ThreadId. If the thread is
-- no longer alive (that is, if @deRefWeak@ is Nothing), this function will do
-- nothing.
killWkThread :: Weak ThreadId -> IO ()
killWkThread tid = deRefWeak tid >>= \case
    Nothing -> pure ()
    Just x  -> killThread x