From e1decb7eaedd14fe4ab8960cf3fed0b4154f1894 Mon Sep 17 00:00:00 2001
From: sheaf <sam.derbyshire@gmail.com>
Date: Thu, 27 Oct 2022 19:25:47 +0200
Subject: [PATCH] use semaphore-compat package

---
 Cabal/src/Distribution/Simple/Program/GHC.hs  |   2 +-
 cabal-install/cabal-install.cabal             |   4 +-
 .../src/Distribution/Client/JobControl.hs     |  20 +-
 .../Distribution/Client/ProjectBuilding.hs    |   4 +-
 .../src/Distribution/Client/ProjectConfig.hs  |   3 +-
 .../Client/ProjectConfig/Types.hs             |   1 -
 .../src/Distribution/Client/Semaphore.hs      | 174 ------------------
 cabal.project                                 |   2 +
 8 files changed, 18 insertions(+), 192 deletions(-)
 delete mode 100644 cabal-install/src/Distribution/Client/Semaphore.hs

diff --git a/Cabal/src/Distribution/Simple/Program/GHC.hs b/Cabal/src/Distribution/Simple/Program/GHC.hs
index b835497a50..89dfea4abc 100644
--- a/Cabal/src/Distribution/Simple/Program/GHC.hs
+++ b/Cabal/src/Distribution/Simple/Program/GHC.hs
@@ -649,7 +649,7 @@ renderGhcOptions comp _platform@(Platform _arch os) opts
       Just hpcdir -> ["-fhpc", "-hpcdir", hpcdir]
 
   , if parmakeSupported comp
-    then case traceShowId (ghcOptNumJobs opts) of
+    then case ghcOptNumJobs opts of
       NoFlag  -> []
       Flag Serial -> []
       Flag (UseSem name _) -> if jsemSupported comp then ["-jsem " ++ name] else []
diff --git a/cabal-install/cabal-install.cabal b/cabal-install/cabal-install.cabal
index cfe29399dd..0e31be2ca3 100644
--- a/cabal-install/cabal-install.cabal
+++ b/cabal-install/cabal-install.cabal
@@ -69,7 +69,6 @@ library
         Distribution.Deprecated.ReadP
         Distribution.Deprecated.ViewAsFieldDescr
 
-        Distribution.Client.Semaphore
         Distribution.Client.BuildReports.Anonymous
         Distribution.Client.BuildReports.Lens
         Distribution.Client.BuildReports.Storage
@@ -229,7 +228,8 @@ library
         parsec     >= 3.1.13.0 && < 3.2,
         regex-base  >= 0.94.0.0 && <0.95,
         regex-posix >= 0.96.0.0 && <0.97,
-        safe-exceptions >= 0.1.7.0 && < 0.2
+        safe-exceptions >= 0.1.7.0 && < 0.2,
+        semaphore-compat >= 1.0.0.0 && < 1.1
 
     if flag(native-dns)
       if os(windows)
diff --git a/cabal-install/src/Distribution/Client/JobControl.hs b/cabal-install/src/Distribution/Client/JobControl.hs
index c7fedb64c1..43a594aa8e 100644
--- a/cabal-install/src/Distribution/Client/JobControl.hs
+++ b/cabal-install/src/Distribution/Client/JobControl.hs
@@ -44,7 +44,7 @@ import Control.Concurrent.STM.TChan
 import Control.Exception (bracket_, try, finally)
 import Distribution.Compat.Stack
 import Distribution.Client.Compat.Semaphore
-import Distribution.Client.Semaphore
+import System.Semaphore
 
 
 -- | A simple concurrency abstraction. Jobs can be spawned and can complete
@@ -173,21 +173,21 @@ readAllTChan qvar = go []
 -- that have already been executed or are currently executing cannot be
 -- cancelled.
 --
-newSemaphoreJobControl :: WithCallStack (SemaphoreName -> Int -> IO (JobControl IO a))
+newSemaphoreJobControl :: WithCallStack (String -> Int -> IO (JobControl IO a))
 newSemaphoreJobControl _ n | n < 1 || n > 1000 =
   error $ "newParallelJobControl: not a sensible number of jobs: " ++ show n
-newSemaphoreJobControl semName maxJobLimit = do
-    sem   <- createSemaphore semName maxJobLimit
+newSemaphoreJobControl semPrefix maxJobLimit = do
+    sem      <- createSemaphore semPrefix maxJobLimit
     outqVar  <- newTChanIO
-    inqVar  <- newTChanIO
+    inqVar   <- newTChanIO
     countVar <- newTVarIO 0
     forkIO (worker sem inqVar outqVar)
     return JobControl {
-      spawnJob      = spawn   inqVar  countVar,
-      collectJob    = collect outqVar countVar,
-      remainingJobs = remaining       countVar,
-      cancelJobs    = cancel  inqVar  countVar,
-      cleanupJobControl       = destroySemaphore sem
+      spawnJob          = spawn   inqVar  countVar,
+      collectJob        = collect outqVar countVar,
+      remainingJobs     = remaining       countVar,
+      cancelJobs        = cancel  inqVar  countVar,
+      cleanupJobControl = destroySemaphore sem
     }
   where
     worker ::  Semaphore -> TChan (IO a) -> TChan (Either SomeException a) -> IO ()
diff --git a/cabal-install/src/Distribution/Client/ProjectBuilding.hs b/cabal-install/src/Distribution/Client/ProjectBuilding.hs
index d7b8227917..273ffcc4eb 100644
--- a/cabal-install/src/Distribution/Client/ProjectBuilding.hs
+++ b/cabal-install/src/Distribution/Client/ProjectBuilding.hs
@@ -103,9 +103,9 @@ import Control.Exception (Handler (..), SomeAsyncException, assert, catches, han
 import System.Directory  (canonicalizePath, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, removeFile, renameDirectory)
 import System.FilePath   (dropDrive, makeRelative, normalise, takeDirectory, (<.>), (</>))
 import System.IO         (IOMode (AppendMode), Handle, withFile)
+import System.Semaphore
 
 import Distribution.Compat.Directory (listDirectory)
-import Distribution.Client.Semaphore
 import Distribution.Client.ProjectConfig.Types
 
 
@@ -587,7 +587,7 @@ rebuildTargets verbosity
     let mkJobControl = case buildSettingNumJobs of
                     Serial -> newSerialJobControl
                     Old n  -> newParallelJobControl (fromMaybe numberOfProcessors n)
-                    UseSem sm n -> newSemaphoreJobControl (SemaphoreName sm) n
+                    UseSem sm n -> newSemaphoreJobControl sm n
 
     registerLock  <- newLock -- serialise registration
     cacheLock     <- newLock -- serialise access to setup exe cache
diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs
index 5afc3f5eed..675aeec139 100644
--- a/cabal-install/src/Distribution/Client/ProjectConfig.hs
+++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs
@@ -151,10 +151,9 @@ import System.FilePath hiding (combine)
 import System.IO
          ( withBinaryFile, IOMode(ReadMode) )
 import System.Directory
+import System.Semaphore
 import Network.URI
          ( URI(..), URIAuth(..), parseAbsoluteURI, uriToString )
-import Distribution.Client.Semaphore
-
 
 ----------------------------------------
 -- Resolving configuration to settings
diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs
index b0b92475ac..eff45d9234 100644
--- a/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs
+++ b/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs
@@ -68,7 +68,6 @@ import Distribution.Utils.NubList
          ( NubList )
 
 import qualified Data.Map as Map
-import Distribution.Client.Semaphore (SemaphoreName)
 import Distribution.Types.ParStrat
 
 -------------------------------
diff --git a/cabal-install/src/Distribution/Client/Semaphore.hs b/cabal-install/src/Distribution/Client/Semaphore.hs
deleted file mode 100644
index 38a82358df..0000000000
--- a/cabal-install/src/Distribution/Client/Semaphore.hs
+++ /dev/null
@@ -1,174 +0,0 @@
-{-# LANGUAGE CPP #-}
-module Distribution.Client.Semaphore
-  ( Semaphore(..), SemaphoreName(..)
-  , createSemaphore, openSemaphore
-  , waitOnSemaphore, tryWaitOnSemaphore
-  , getSemaphoreValue
-  , releaseSemaphore
-  , destroySemaphore
-
-  -- * Abstract semaphores
-  , AbstractSem(..)
-  , withAbstractSem
-  ) where
-
-import Control.Monad
-
-import qualified Control.Monad.Catch as MC
-
-#if defined(mingw32_HOST_OS)
-import qualified System.Win32.Event     as Win32
-  ( waitForSingleObject, wAIT_OBJECT_0 )
-import qualified System.Win32.File      as Win32
-  ( closeHandle )
-import qualified System.Win32.Process   as Win32
-  ( iNFINITE )
-import qualified System.Win32.Semaphore as Win32
-  ( Semaphore(..), sEMAPHORE_ALL_ACCESS
-  , createSemaphore, openSemaphore, releaseSemaphore )
-import qualified System.Win32.Types     as Win32
-  ( errorWin )
-#else
-import qualified System.Posix.Semaphore as Posix
-  ( Semaphore, OpenSemFlags(..)
-  , semOpen, semThreadWait, semTryWait
-  , semGetValue, semPost, semUnlink )
-import qualified System.Posix.Files     as Posix
-  ( stdFileMode )
-#endif
-
----------------------------------------
--- Abstract semaphores
-
--- | Abstraction over the operations of a semaphore,
--- allowing usage with -jN or a jobserver.
-data AbstractSem = AbstractSem { acquireSem :: IO ()
-                               , releaseSem :: IO ()
-                               }
-
-withAbstractSem :: AbstractSem -> IO b -> IO b
-withAbstractSem sem = MC.bracket_ (acquireSem sem) (releaseSem sem)
-
----------------------------------------
--- System-specific semaphores
-
-newtype SemaphoreName =
-  SemaphoreName { getSemaphoreName :: String }
-  deriving (Eq, Show)
-
--- | A semaphore (POSIX or Win32).
-data Semaphore =
-  Semaphore
-    { semaphoreName :: !SemaphoreName
-    , semaphore     ::
-#if defined(mingw32_HOST_OS)
-      !Win32.Semaphore
-#else
-      !Posix.Semaphore
-#endif
-    }
-
--- | Create a new semaphore with the given name and initial amount of
--- available resources.
---
--- Throws an error if a semaphore by this name already exists.
-createSemaphore :: SemaphoreName -> Int -> IO Semaphore
-createSemaphore nm@(SemaphoreName sem_name) init_toks = do
-#if defined(mingw32_HOST_OS)
-  let toks = fromIntegral init_toks
-  (sem, exists) <- Win32.createSemaphore Nothing toks toks (Just sem_name)
-  when exists $
-    Win32.errorWin ("jsem: semaphore " ++ sem_name ++ " already exists")
-#else
-  let flags =
-        Posix.OpenSemFlags
-          { Posix.semCreate    = True
-          , Posix.semExclusive = True }
-  sem <- Posix.semOpen sem_name flags Posix.stdFileMode init_toks
-#endif
-  return $
-    Semaphore
-      { semaphore     = sem
-      , semaphoreName = nm }
-
--- | Open a semaphore with the given name.
---
--- If no such semaphore exists, throws an error.
-openSemaphore :: SemaphoreName -> IO Semaphore
-openSemaphore nm@(SemaphoreName sem_name) = do
-#if defined(mingw32_HOST_OS)
-  sem <- Win32.openSemaphore Win32.sEMAPHORE_ALL_ACCESS True sem_name
-#else
-  let
-    flags = Posix.OpenSemFlags
-          { Posix.semCreate    = False
-          , Posix.semExclusive = False }
-  sem <- Posix.semOpen sem_name flags Posix.stdFileMode 0
-#endif
-  return $
-    Semaphore
-      { semaphore     = sem
-      , semaphoreName = nm }
-
--- | Indefinitely wait on a semaphore.
-waitOnSemaphore :: Semaphore -> IO ()
-waitOnSemaphore (Semaphore { semaphore = sem }) =
-#if defined(mingw32_HOST_OS)
-  void $ Win32.waitForSingleObject (Win32.semaphoreHandle sem) Win32.iNFINITE
-#else
-  Posix.semThreadWait sem
-#endif
-
--- | Try to obtain a token from the semaphore, without blocking.
---
--- Immediately returns 'False' if no resources are available.
-tryWaitOnSemaphore :: Semaphore -> IO Bool
-tryWaitOnSemaphore (Semaphore { semaphore = sem }) =
-#if defined(mingw32_HOST_OS)
-  (== Win32.wAIT_OBJECT_0) <$> Win32.waitForSingleObject (Win32.semaphoreHandle sem) 0
-#else
-  Posix.semTryWait sem
-#endif
-
--- | Release a semaphore: add @n@ to its internal counter,
--- and return the semaphore's count before the operation.
---
--- NB: the returned value should only be used for debugging,
--- not for the main jobserver logic.
-releaseSemaphore :: Semaphore -> Int -> IO Int
-releaseSemaphore (Semaphore { semaphore = sem }) n =
-#if defined(mingw32_HOST_OS)
-  fromIntegral <$> Win32.releaseSemaphore sem (fromIntegral n)
-#else
-  do
-    res <- Posix.semGetValue sem
-    replicateM_ n (Posix.semPost sem)
-    return res
-#endif
-
--- | Destroy the given semaphore.
-destroySemaphore :: Semaphore -> IO ()
-destroySemaphore sem =
-#if defined(mingw32_HOST_OS)
-  Win32.closeHandle (Win32.semaphoreHandle $ semaphore sem)
-#else
-  Posix.semUnlink (getSemaphoreName $ semaphoreName sem)
-#endif
-
--- | Query the current semaphore value (how many tokens it has available).
-getSemaphoreValue :: Semaphore -> IO Int
-getSemaphoreValue (Semaphore { semaphore = sem }) =
-#if defined(mingw32_HOST_OS)
-  do
-    wait_res <- Win32.waitForSingleObject (Win32.semaphoreHandle sem) (fromInteger 0)
-    if wait_res == Win32.wAIT_OBJECT_0
-      -- We were able to immediately acquire a resource from the semaphore:
-      -- release it immediately, thus obtaining the total number of available
-      -- resources.
-    then
-      (+1) . fromIntegral <$> Win32.releaseSemaphore sem 1
-    else
-      return 0
-#else
-  Posix.semGetValue sem
-#endif
diff --git a/cabal.project b/cabal.project
index aea54a32ef..bf0a9e4adc 100644
--- a/cabal.project
+++ b/cabal.project
@@ -16,6 +16,8 @@ optional-packages: ./vendored/*/*.cabal
 allow-newer:
   hackage-security:Cabal
 
+packages: ../semaphore-compat
+
 -- avoiding extra dependencies
 constraints: rere -rere-cfg
 constraints: these -assoc
-- 
GitLab