X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FResource%2FTree.hs;h=149fa9d92d3b5101a27f5ba6c334133a3921fe34;hb=0dc3d31312a12f2b085242841b29eb0d96e9c4ac;hp=d468d2b482baaa09da6af0289ba31e4067d1929a;hpb=46f1b85674e45e823f5b6c7a1f87b1faf8172b85;p=Lucu.git diff --git a/Network/HTTP/Lucu/Resource/Tree.hs b/Network/HTTP/Lucu/Resource/Tree.hs index d468d2b..149fa9d 100644 --- a/Network/HTTP/Lucu/Resource/Tree.hs +++ b/Network/HTTP/Lucu/Resource/Tree.hs @@ -14,7 +14,7 @@ module Network.HTTP.Lucu.Resource.Tree import Control.Concurrent import Control.Concurrent.STM import Control.Exception -import Control.Monad.Reader +import Control.Monad import Data.Dynamic import Data.List import qualified Data.Map as M @@ -22,7 +22,6 @@ import Data.Map (Map) import Data.Maybe import Network.HTTP.Lucu.Abortion import Network.HTTP.Lucu.Config -import Network.HTTP.Lucu.MIMEType import Network.HTTP.Lucu.Request import Network.HTTP.Lucu.Resource import Network.HTTP.Lucu.Response @@ -42,10 +41,12 @@ import Prelude hiding (catch) -- | 'ResourceDef' is basically a set of -- 'Network.HTTP.Lucu.Resource.Resource' monads for each HTTP methods. data ResourceDef = ResourceDef { - -- | Whether to run a 'Network.HTTP.Lucu.Resource.Resource' on a - -- native thread (spawned using @forkOS@) or to run it on a user - -- thread (spanwed using @forkIO@). Generally you don't - resUsesNativeThread :: Bool + -- |Whether to run a 'Network.HTTP.Lucu.Resource.Resource' on a + -- native thread (spawned by 'Control.Concurrent.forkOS') or to + -- run it on a user thread (spanwed by + -- 'Control.Concurrent.forkIO'). Generally you don't need to set + -- this field to 'Prelude.True'. + resUsesNativeThread :: !Bool -- | Whether to be greedy or not. -- -- Say a client is trying to access \/aaa\/bbb\/ccc. If there is a @@ -53,7 +54,7 @@ data ResourceDef = ResourceDef { -- there is another resource at \/aaa\/bbb\/ccc. If the resource -- at \/aaa\/bbb is not greedy, it is just ignored. Greedy -- resource is like a CGI script. - , resIsGreedy :: Bool + , resIsGreedy :: !Bool -- | A 'Network.HTTP.Lucu.Resource.Resource' to be run when a GET -- request comes for the resource path. If 'resGet' is Nothing, -- the system responds \"405 Method Not Allowed\" for GET @@ -62,35 +63,35 @@ data ResourceDef = ResourceDef { -- It also runs for HEAD request if the 'resHead' is Nothing. In -- this case 'Network.HTTP.Lucu.Resource.output' and such like -- don't actually write a response body. - , resGet :: Maybe (Resource ()) + , resGet :: !(Maybe (Resource ())) -- | A 'Network.HTTP.Lucu.Resource.Resource' to be run when a HEAD -- request comes for the resource path. If 'resHead' is Nothing, -- the system runs 'resGet' instead. If 'resGet' is also Nothing, -- the system responds \"405 Method Not Allowed\" for HEAD -- requests. - , resHead :: Maybe (Resource ()) + , resHead :: !(Maybe (Resource ())) -- | A 'Network.HTTP.Lucu.Resource.Resource' to be run when a POST -- request comes for the resource path. If 'resPost' is Nothing, -- the system responds \"405 Method Not Allowed\" for POST -- requests. - , resPost :: Maybe (Resource ()) + , resPost :: !(Maybe (Resource ())) -- | A 'Network.HTTP.Lucu.Resource.Resource' to be run when a PUT -- request comes for the resource path. If 'resPut' is Nothing, -- the system responds \"405 Method Not Allowed\" for PUT -- requests. - , resPut :: Maybe (Resource ()) + , resPut :: !(Maybe (Resource ())) -- | A 'Network.HTTP.Lucu.Resource.Resource' to be run when a -- DELETE request comes for the resource path. If 'resDelete' is -- Nothing, the system responds \"405 Method Not Allowed\" for -- DELETE requests. - , resDelete :: Maybe (Resource ()) + , resDelete :: !(Maybe (Resource ())) } -- | 'ResTree' is an opaque structure which is a map from resource -- path to 'ResourceDef'. type ResTree = ResNode -- root だから Map ではない type ResSubtree = Map String ResNode -data ResNode = ResNode (Maybe ResourceDef) ResSubtree +data ResNode = ResNode !(Maybe ResourceDef) !ResSubtree -- | 'mkResTree' converts a list of @(path, def)@ to a 'ResTree' e.g. -- @@ -100,7 +101,7 @@ data ResNode = ResNode (Maybe ResourceDef) ResSubtree -- ] -- @ mkResTree :: [ ([String], ResourceDef) ] -> ResTree -mkResTree list = processRoot list +mkResTree list = list `seq` processRoot list where processRoot :: [ ([String], ResourceDef) ] -> ResTree processRoot list @@ -167,13 +168,14 @@ findResource (ResNode rootDefM subtree) uri runResource :: ResourceDef -> Interaction -> IO ThreadId runResource def itr - = fork - $ catch ( runReaderT ( do req <- getRequest - fromMaybe notAllowed $ rsrc req - driftTo Done - ) itr - ) - $ \ exc -> processException exc + = def `seq` itr `seq` + fork + $! catch ( runRes ( do req <- getRequest + fromMaybe notAllowed $ rsrc req + driftTo Done + ) itr + ) + $ \ exc -> processException exc where fork :: IO () -> IO ThreadId fork = if (resUsesNativeThread def) @@ -227,7 +229,7 @@ runResource def itr reqM <- atomically $ readItr itr itrRequest id res <- atomically $ readItr itr itrResponse id if state <= DecidingHeader then - flip runReaderT itr + flip runRes itr $ do setStatus $ aboStatus abo -- FIXME: 同じ名前で複數の値があった時は、こ -- れではまずいと思ふ。 @@ -237,7 +239,7 @@ runResource def itr when (cnfDumpTooLateAbortionToStderr $ itrConfig itr) $ hPutStrLn stderr $ show abo - flip runReaderT itr $ driftTo Done + flip runRes itr $ driftTo Done formatIOE :: IOError -> String formatIOE ioE = if isUserError ioE then