----------------------------------------------------------------------------
-- |
-- Module      :  Data.Emacs.Module.Value.Internal
-- Copyright   :  (c) Sergey Vinokurov 2018
-- License     :  Apache-2.0 (see LICENSE)
-- Maintainer  :  serg.foo@gmail.com
----------------------------------------------------------------------------

{-# LANGUAGE DeriveGeneric #-}

module Data.Emacs.Module.Value.Internal (Value(..)) where

import Control.DeepSeq
import Control.Monad.Trans.Resource

import GHC.Generics (Generic)

import Data.Emacs.Module.Raw.Value (GlobalRef(..))

-- | Value that is independent of environment ('Env') that produced it.
-- Incidentally, this implies that it's "protected" against Emacs GC and
-- thus will not unexpectedly go out of scope.
--
-- In order to prevent memory leaks, value is registered in the Emacs
-- monad than produced it and will be freed when the monad finishes.
-- To make the connection clear the value is tagged with parameter
-- @s@, which serves the same purpose as tag of the 'ST' monad. That
-- is, it ensures that value cannot leave the scope of the monad that
-- produced it.
data Value s = Value
  { Value s -> GlobalRef
valuePayload       :: {-# UNPACK #-} !GlobalRef
  , Value s -> ReleaseKey
valueReleaseHandle :: {-# UNPACK #-} !ReleaseKey
  } deriving ((forall x. Value s -> Rep (Value s) x)
-> (forall x. Rep (Value s) x -> Value s) -> Generic (Value s)
forall x. Rep (Value s) x -> Value s
forall x. Value s -> Rep (Value s) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall s x. Rep (Value s) x -> Value s
forall s x. Value s -> Rep (Value s) x
$cto :: forall s x. Rep (Value s) x -> Value s
$cfrom :: forall s x. Value s -> Rep (Value s) x
Generic)

instance NFData (Value s) where
  rnf :: Value s -> ()
rnf (Value GlobalRef
x ReleaseKey
y) = GlobalRef -> ()
forall a. NFData a => a -> ()
rnf GlobalRef
x () -> () -> ()
`seq` ReleaseKey
y ReleaseKey -> () -> ()
`seq` ()