<commit_before>{-# LANGUAGE Unsafe #-}
module Concurrent.Promise where

import Concurrent.Exception
import Concurrent.Par
import Control.Concurrent.MVar
import Control.Exception
import Control.Monad
import GHC.IO

-- | An 'Promise' can be fulfilled multiple times, but must be always be fulfilled with the same answer.
data Promise s a
  = Promise {-# UNPACK #-} !(MVar a) a

newEmptyPromise :: MonadPar d i s m => m (Promise s a)
newEmptyPromise = unsafeParIO $ do
  x <- newEmptyMVar
  Promise x <$> unsafeDupableInterleaveIO (readMVar x)

-- | Build a filled Promise out of a known value
newPromise :: a -> Promise s a
newPromise a = unsafeDupablePerformIO $ do
  x <- newMVar a
  return $ Promise x a

readPromise :: Promise s a -> a
readPromise (Promise _ a)     = a

writePromise :: (MonadPar d i s m, Eq a) => Promise s a -> a -> m ()
writePromise (Promise m _) a = unsafeParIO $ do
  a' <- evaluate a
  t <- tryPutMVar m a'
  unless t $ do
     b <- readMVar m
     unless (a' == b) $ throwIO Contradiction

-- | Like 'writePromise' but assumes (without checking) that the write is always consistent.
unsafeWritePromise :: MonadPar d i s m => Promise s a -> a -> m ()
unsafeWritePromise (Promise m _) a = unsafeParIO $ do
  a' <- evaluate a
  () <$ tryPutMVar m a'<commit_msg>document readPromise<commit_after>{-# LANGUAGE Unsafe #-}
module Concurrent.Promise where

import Concurrent.Exception
import Concurrent.Par
import Control.Concurrent.MVar
import Control.Exception
import Control.Monad
import GHC.IO

-- | An 'Promise' can be fulfilled multiple times, but must be always be fulfilled with the same answer.
data Promise s a
  = Promise {-# UNPACK #-} !(MVar a) a

newEmptyPromise :: MonadPar d i s m => m (Promise s a)
newEmptyPromise = unsafeParIO $ do
  x <- newEmptyMVar
  Promise x <$> unsafeDupableInterleaveIO (readMVar x)

-- | Build a filled Promise out of a known value
newPromise :: a -> Promise s a
newPromise a = unsafeDupablePerformIO $ do
  x <- newMVar a
  return $ Promise x a

-- | Fulfilling the promise is tied to the region parameter, but reading the value is not.
readPromise :: Promise s a -> a
readPromise (Promise _ a) = a

writePromise :: (MonadPar d i s m, Eq a) => Promise s a -> a -> m ()
writePromise (Promise m _) a = unsafeParIO $ do
  a' <- evaluate a
  t <- tryPutMVar m a'
  unless t $ do
     b <- readMVar m
     unless (a' == b) $ throwIO Contradiction

-- | Like 'writePromise' but assumes (without checking) that the write is always consistent.
unsafeWritePromise :: MonadPar d i s m => Promise s a -> a -> m ()
unsafeWritePromise (Promise m _) a = unsafeParIO $ do
  a' <- evaluate a
  () <$ tryPutMVar m a'
{'fraction_non_alphanumeric': 0.09954921111945905, 'fraction_numerical': 0.0, 'mean_word_length': 3.4089403973509933, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3069381', 'n_tokens_mistral': 865, 'n_tokens_neox': 841, 'n_words': 355}