mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-23 11:42:49 -06:00
Multithreaded gf.fcgi.
This commit is contained in:
@@ -104,21 +104,26 @@ restartIfModified =
|
|||||||
-- Utilities for getting and caching read-only data from disk.
|
-- Utilities for getting and caching read-only data from disk.
|
||||||
-- The data is reloaded when the file on disk has been modified.
|
-- The data is reloaded when the file on disk has been modified.
|
||||||
|
|
||||||
type DataRef a = IORef (Maybe (ClockTime, a))
|
data DataRef a = DataRef {
|
||||||
|
dataFile :: FilePath,
|
||||||
|
dataLoad :: FilePath -> IO a,
|
||||||
|
dataValue :: MVar (ClockTime, a)
|
||||||
|
}
|
||||||
|
|
||||||
newDataRef :: MonadIO m => m (DataRef a)
|
newDataRef :: (FilePath -> IO a) -> FilePath -> IO (DataRef a)
|
||||||
newDataRef = liftIO $ newIORef Nothing
|
newDataRef load file =
|
||||||
|
do t <- getModificationTime file
|
||||||
|
x <- load file
|
||||||
|
v <- newMVar (t,x)
|
||||||
|
return $ DataRef { dataFile = file, dataLoad = load, dataValue = v }
|
||||||
|
|
||||||
getData :: MonadIO m => (FilePath -> m a) -> DataRef a -> FilePath -> m a
|
getData :: DataRef a -> IO a
|
||||||
getData loadData ref file =
|
getData ref =
|
||||||
do t' <- liftIO $ getModificationTime file
|
do t' <- getModificationTime (dataFile ref)
|
||||||
m <- liftIO $ readIORef ref
|
(t,x) <- takeMVar (dataValue ref)
|
||||||
case m of
|
x' <- if t' == t then return x else (dataLoad ref) (dataFile ref)
|
||||||
Just (t,x) | t' == t -> return x
|
putMVar (dataValue ref) (t',x')
|
||||||
_ -> do logCGI $ "Loading " ++ show file ++ "..."
|
return x'
|
||||||
x <- loadData file
|
|
||||||
liftIO $ writeIORef ref (Just (t',x))
|
|
||||||
return x
|
|
||||||
|
|
||||||
-- Logging
|
-- Logging
|
||||||
|
|
||||||
|
|||||||
@@ -5,28 +5,29 @@ import qualified PGF
|
|||||||
import FastCGIUtils
|
import FastCGIUtils
|
||||||
import URLEncoding
|
import URLEncoding
|
||||||
|
|
||||||
import Network.CGI
|
import Network.FastCGI
|
||||||
import Text.JSON
|
import Text.JSON
|
||||||
import qualified Codec.Binary.UTF8.String as UTF8 (encodeString, decodeString)
|
import qualified Codec.Binary.UTF8.String as UTF8 (encodeString, decodeString)
|
||||||
|
|
||||||
|
import Control.Concurrent
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.Char
|
import Data.Char
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
|
import System.Environment
|
||||||
|
|
||||||
|
|
||||||
grammarFile :: FilePath
|
grammarFile :: IO FilePath
|
||||||
grammarFile = "grammar.pgf"
|
grammarFile = do env <- getEnvironment
|
||||||
|
return $ fromMaybe "grammar.pgf" $ lookup "PGF_FILE" env
|
||||||
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do initFastCGI
|
main = do initFastCGI
|
||||||
r <- newDataRef
|
ref <- grammarFile >>= newDataRef PGF.readPGF
|
||||||
loopFastCGI (handleErrors (handleCGIErrors (fcgiMain r)))
|
runFastCGIConcurrent' forkIO 100 (handleErrors (handleCGIErrors (fcgiMain ref)))
|
||||||
|
|
||||||
fcgiMain :: DataRef PGF -> CGI CGIResult
|
fcgiMain :: DataRef PGF -> CGI CGIResult
|
||||||
fcgiMain ref = getData (liftIO . PGF.readPGF) ref grammarFile >>= cgiMain
|
fcgiMain ref = liftIO (getData ref) >>= cgiMain
|
||||||
|
|
||||||
cgiMain :: PGF -> CGI CGIResult
|
cgiMain :: PGF -> CGI CGIResult
|
||||||
cgiMain pgf =
|
cgiMain pgf =
|
||||||
|
|||||||
@@ -20,3 +20,4 @@ executable gf.fcgi
|
|||||||
main-is: MainFastCGI.hs
|
main-is: MainFastCGI.hs
|
||||||
other-modules:
|
other-modules:
|
||||||
FastCGIUtils
|
FastCGIUtils
|
||||||
|
ghc-options: -threaded
|
||||||
Reference in New Issue
Block a user