From 1a5aa23f13285ac116443f22f0a7bd6523cb54e0 Mon Sep 17 00:00:00 2001 From: John Lenz Date: Thu, 12 Sep 2013 17:52:15 -0500 Subject: [PATCH] static: fix the build on GHC 7.4 There were two build issues on GHC 7.4: using atomicModifyIORef' and ByteString.Lazy.toStrict, both of which were missing. These are now fixed. In addition, looking at the IORef code more closely, we want the quite a bit of strictness in the IORef. The common case is that the widget content already exists in the map (every reload of a page will call embedStaticContent), but until we force the map the thunks holding the duplicated generated content will be kept around, leaking memory. This will be the common situation since the vast majority of the time the content already exists. Since the containers module does not have a strict map until 0.5, use unordered containers which does have a strict map. --- yesod-static/Yesod/EmbeddedStatic.hs | 2 +- yesod-static/Yesod/EmbeddedStatic/Internal.hs | 15 +++++++++++++-- yesod-static/test/EmbedProductionTest.hs | 5 +++-- yesod-static/yesod-static.cabal | 2 ++ 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/yesod-static/Yesod/EmbeddedStatic.hs b/yesod-static/Yesod/EmbeddedStatic.hs index 40345a10..e8196302 100644 --- a/yesod-static/Yesod/EmbeddedStatic.hs +++ b/yesod-static/Yesod/EmbeddedStatic.hs @@ -67,7 +67,7 @@ import Yesod.Core.Types ) import qualified Data.ByteString.Lazy as BL import qualified Data.Text as T -import qualified Data.Map as M +import qualified Data.HashMap.Strict as M import qualified WaiAppStatic.Storage.Embedded as Static import Yesod.EmbeddedStatic.Types diff --git a/yesod-static/Yesod/EmbeddedStatic/Internal.hs b/yesod-static/Yesod/EmbeddedStatic/Internal.hs index 8f8ad8ff..0882c16d 100644 --- a/yesod-static/Yesod/EmbeddedStatic/Internal.hs +++ b/yesod-static/Yesod/EmbeddedStatic/Internal.hs @@ -3,6 +3,7 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE CPP #-} module Yesod.EmbeddedStatic.Internal ( EmbeddedStatic(..) , Route(..) @@ -34,16 +35,26 @@ import Yesod.Core import qualified Data.ByteString.Lazy as BL import qualified Data.Text as T import qualified Data.Text.Encoding as T -import qualified Data.Map as M +import qualified Data.HashMap.Strict as M import qualified WaiAppStatic.Storage.Embedded as Static import Yesod.Static (base64md5) import Yesod.EmbeddedStatic.Types +#if !MIN_VERSION_base(4,6,0) +-- copied from base +atomicModifyIORef' :: IORef a -> (a -> (a,b)) -> IO b +atomicModifyIORef' ref f = do + b <- atomicModifyIORef ref + (\x -> let (a, b) = f x + in (a, a `seq` b)) + b `seq` return b +#endif + -- | The subsite for the embedded static file server. data EmbeddedStatic = EmbeddedStatic { stApp :: !Application - , widgetFiles :: !(IORef (M.Map T.Text File)) + , widgetFiles :: !(IORef (M.HashMap T.Text File)) } instance RenderRoute EmbeddedStatic where diff --git a/yesod-static/test/EmbedProductionTest.hs b/yesod-static/test/EmbedProductionTest.hs index 8fd407a3..d7fcbc1d 100644 --- a/yesod-static/test/EmbedProductionTest.hs +++ b/yesod-static/test/EmbedProductionTest.hs @@ -15,7 +15,8 @@ import Yesod.EmbeddedStatic import Yesod.Test import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL -import qualified Data.Text.Encoding as T +import qualified Data.Text.Lazy as TL +import qualified Data.Text.Lazy.Encoding as TL mkEmbeddedStatic False "eProduction" [testGen] @@ -110,7 +111,7 @@ embedProductionSpecs = yesodSpec (MyApp eProduction) $ do [script] <- htmlQuery "script" let src = BL.takeWhile (/= 34) $ BL.drop 1 $ BL.dropWhile (/= 34) script -- 34 is " - get $ T.decodeUtf8 $ BL.toStrict src + get $ TL.toStrict $ TL.decodeUtf8 src statusIs 200 hasCacheControl assertHeader "Content-Type" "application/javascript" diff --git a/yesod-static/yesod-static.cabal b/yesod-static/yesod-static.cabal index a5ccc0d7..9db09b9c 100644 --- a/yesod-static/yesod-static.cabal +++ b/yesod-static/yesod-static.cabal @@ -52,6 +52,7 @@ library , process-conduit >= 1.0 && < 1.1 , filepath >= 1.3 , resourcet >= 0.4 + , unordered-containers >= 0.2 exposed-modules: Yesod.Static Yesod.EmbeddedStatic @@ -101,6 +102,7 @@ test-suite tests , process-conduit , filepath , resourcet + , unordered-containers ghc-options: -Wall