packages feed

conjure-0.1: src/Conjure/Debug.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Conjure.Debug
-- Copyright   :  (c) ADEpt 2005
-- License     :  BSD-like
--
-- Maintainer  :  adept@gmail.com
-- Stability   :  experimental
-- Portability :  portable
--
-----------------------------------------------------------------------------
-- TODO: make it not THAT trivial
module Conjure.Debug
    ( debug
    , initSTMLogger
    , stmTransactionName
    , stmDebug
    ) where

import Control.Concurrent
import Control.Concurrent.STM
import Control.Exception
import Control.Monad
import System.IO.Unsafe
import GHC.Conc                   ( unsafeIOToSTM )

import qualified Data.Map as Map
import Data.Map ( Map )

import Conjure.Utils.Logger()

debug :: String -> IO ()
debug = putStrLn -- syslog Debug


--------------------------------------------------------------
-- Non-portable STM debugger
--------------------------------------------------------------

{-# NOINLINE stmLog #-}
stmLog :: TVar (Map ThreadId (String, [String]))
stmLog = unsafePerformIO (newTVarIO Map.empty)

initSTMLogger :: IO ()
initSTMLogger
    = do evaluate stmLog
         forkIO $ loop $
           do msgs <- atomically $
                      do msgs <- readTVar stmLog
                         when (Map.null msgs) retry
                         writeTVar stmLog Map.empty
                         return (Map.elems msgs)
              mapM_ printMsg msgs
         debug "STMLogger initialized"
    where loop fn = fn >> loop fn
          printMsg (name,strs)
              | null strs
                  = return ()
              | null name
                  = mapM_ putStrLn (reverse strs)
              | otherwise
                  = do putStrLn (name++":")
                       mapM_ (\str -> putStr "  " >> putStrLn str) (reverse strs)

stmTransactionName :: String -> STM ()
stmTransactionName name
    = do tid <- unsafeIOToSTM myThreadId
         msgs <- readTVar stmLog
         case Map.lookup tid msgs of
           Nothing -> writeTVar stmLog (Map.singleton tid (name,[]))
           Just (name',strs)
               | null name'
                   -> writeTVar stmLog (Map.singleton tid (name,strs))
               | otherwise
                   -> retry

stmDebug :: String -> STM ()
stmDebug str
    = do tid <- unsafeIOToSTM myThreadId
         msgs <- readTVar stmLog
         writeTVar stmLog (Map.insertWith joinInfo tid ("",[str]) msgs)
    where joinInfo ("",[string]) (name,strings) = (name,string:strings)
          joinInfo (name,strings) ("",[string]) = (name,string:strings)