úÎ*ÿ%ýSafeSafeN  + !"#$%&'()*+,-./012   None 3456789:;<= 346789:;<= 3456789:;<=Safe >?@ABCDEFGH >?@ABCDEFGH >?@ABCDEFGHDE2013 Joey Hess <id@joeyh.name> BSD-2-clauseNone I.A shared global variable for the OutputHandle.JGets the global OutputHandle.™Holds a lock while performing an action that will display output. While this is running, other threads that try to lockOutput will block, and calls to  and c will result in that concurrent output being buffered and not displayed until the action is done.K%Blocks until we have the output lock.L0Tries to take the output lock, without blocking.M/Only safe to call after taking the output lock.(Use this around any IO actions that use  or nThis is necessary to ensure that buffered concurrent output actually gets displayed before the program exits.&Blocks until any processes started by 6 have finished, and any buffered output is displayed.@Displays a string to stdout, and flush output so it's displayed.~Uses locking to ensure that the whole string is output atomically even when other threads are concurrently generating output.¤When something else is writing to the console at the same time, this does not block. It buffers the string, so it will be displayed once the other writer is done.7This must be used to wait for processes started with .This is necessary because ­ has a race condition when two threads check the same process. If the race is triggered, one thread will successfully wait, but the other throws a DoesNotExist exception.Wrapper around r that prevents multiple processes that are running concurrently from writing to stdout/stderr at the same time.¡If the process does not output to stdout or stderr, it's run by createProcess entirely as usual. Only processes that can generate output are handled specially:xA process is allowed to write to stdout and stderr in the usual way, assuming it can successfully take the output lock.IWhen the output lock is held (by another concurrent process, or because à is being called at the same time), the process is instead run with its stdout and stderr redirected to a buffer. The buffered output will be displayed as soon as the output lock becomes free.NOPQRSTUVWXYIJKLZ[M\]^_`aNOPQRSTUVWXYIJKLZ[M\]^_`ab      !"#$%#$&#$'#$(#$)#$*#$+#$,#$-#$.#$/#$0#$1#$2#$3#$4#$5#$6#$7#$8#$9#$:#$;#$<#$=#$>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`aabcdefghijklmconcu_EPoWkOi3Fg3Jx6BzuFLPJJControl.Concurrent.Output Utility.DataUtility.ExceptionUtility.FileSystemEncoding Utility.MonadSystem.ProcesswaitForProcess createProcess lockOutputwithConcurrentOutputflushConcurrentOutputoutputConcurrentwaitForProcessConcurrentcreateProcessConcurrent firstJust eitherToMaybe catchBoolIO catchMaybeIOcatchDefaultIO catchMsgIOcatchIOtryIO bracketIO catchNonAsync tryNonAsync tryWhenExistscatchHardwareFaultbase GHC.Exception SomeExceptiondisplayException fromException toException Exceptionexcep_8GsEeHgaIks3pVGk6GaELJControl.Monad.CatchbracketOnErrorfinallybracket_bracket onExceptioncatchestryJusttry handleJusthandleIf handleAll handleIOErrorhandle catchJustcatchIf catchIOErrorcatchAlluninterruptibleMask_mask_throwM MonadThrowcatch MonadCatchuninterruptibleMaskmask MonadMask fileEncoding withFilePath_encodeFilePath md5FilePathdecodeBSencodeBSencodeW8decodeW8 encodeW8NUL decodeW8NULtruncateFilePathfirstMgetManyMallM untilTrueifM<||><&&>observeafternoopglobalOutputHandlegetOutputHandletakeOutputLocktryTakeOutputLockdropOutputLockBufferedActivity ReachedEndOutput InTempFileBufferLockLocked OutputHandle outputLock outputBuffer outputThreadswithLocktakeOutputLock' willOutput setupBuffer outputDrainer bufferWriter emitBuffer addBuffer