hotswap 0.1.9.3 → 0.1.9.12
raw patch · 2 files changed
+67/−11 lines, 2 filesPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
API changes (from Hackage documentation)
+ System.Plugins.Hotswap: runPlugin :: Plugin (IO a) -> IO a
Files
- hotswap.cabal +2/−2
- src/System/Plugins/Hotswap.hs +65/−9
hotswap.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: hotswap-version: 0.1.9.3+version: 0.1.9.12 synopsis: Simple code hotswapping. description: A simple, high-level interface to plugins. homepage: https://github.com/mikeplus64/hotswap@@ -20,4 +20,4 @@ hs-source-dirs: src exposed-modules: System.Plugins.Hotswap -- other-modules: - build-depends: base ==4.5.*, plugins ==1.5.*+ build-depends: base == 4.5.*, plugins == 1.5.*
src/System/Plugins/Hotswap.hs view
@@ -3,6 +3,7 @@ newPlugin, usePlugin, usePluginIO,+ runPlugin, reloadPlugin, readPlugin, withPlugin,@@ -11,7 +12,7 @@ ) where import System.Plugins.Load-import Data.IORef +import Data.IORef data Plugin a = Plugin { pluginObject :: FilePath, -- ^ Path to object@@ -24,16 +25,16 @@ -- | 'usePlugin' provides a simple way to use plugins of type 'Plugin (a -> b)', ie, only -- single argumented ones. usePlugin :: Plugin (a -> b) -> a -> IO b-usePlugin plug x = do- pf <- readPlugin plug- return (pf x)+usePlugin plug x = fmap ($ x) (readPlugin plug) -- | 'usePlugin' for plugins returning IO. usePluginIO :: Plugin (a -> IO b) -> a -> IO b-usePluginIO plug x = do- pf <- readPlugin plug- pf x+usePluginIO plug x = readPlugin plug >>= ($ x) +-- | 'runPlugin' runs an 'IO a' returning 'Plugin'.+runPlugin :: Plugin (IO a) -> IO a+runPlugin plug = readPlugin plug >>= id+ -- | 'withPlugin' provides a way to run a function on a plugin, modifying the plugin in-place. withPlugin :: Plugin a -> (a -> a) -> IO () withPlugin plug f = do@@ -47,11 +48,11 @@ r <- f pd putPlugin plug r --- | Create a new plugin. Don't use this to reload plugins.+-- | Create a new plugin, expecting a type. Don't use this to reload plugins. newPlugin :: FilePath -> [FilePath] -> String -> IO (Plugin a) newPlugin obj incs name = do plugin <- load_ obj incs name-+ case plugin of LoadSuccess m f -> do fref <- newIORef f@@ -69,6 +70,7 @@ LoadSuccess newm newf -> do writeIORef mref newm writeIORef fref newf+ _ -> error "no such module or function" -- | Read the 'pluginData' 'IORef'.@@ -78,3 +80,57 @@ -- | Replace the contents of the 'pluginData'. putPlugin :: Plugin a -> a -> IO () putPlugin = writeIORef . pluginData++{-+data Hotswap a = Hotswap {+ hotswapThread :: IORef (Maybe ThreadId),+ hotswapPlugin :: Plugin a -- something seems wrong about passing this around all the time, but alas...+}++-- | Automatically poll the filesystem for changes in the specified 'Plugin''s object file, and+-- reload the plugin if necessary.+newHotswap :: Plugin a -> IO (Hotswap a)+newHotswap plug = do+ ht <- forkHotswapThread plug+ ref <- newIORef (Just ht)+ return $ Hotswap ref plug++-- | 'newHotswap', only returning the ThreadId.+forkHotswapThread :: Plugin a -> IO ThreadId+forkHotswapThread plug = do+ md5 <- md5File $ pluginObject plug+ forkIO (loop md5)+ where+ md5File = fmap md5sum . B.readFile++ loop old = do+ threadDelay 100000+ new <- md5File $ pluginObject plug+ if new == old+ then loop new+ else do+ reloadPlugin plug+ loop new++-- | Restart a 'Hotswap' from one that was killed, otherwise, do nothing.+restartHotswap :: Hotswap a -> IO ()+restartHotswap (Hotswap h p) = do+ r <- readIORef h++ case r of+ Nothing -> do+ thread <- forkHotswapThread p+ writeIORef h (Just thread)++ _ -> return ()++killHotswap :: Hotswap a -> IO ()+killHotswap (Hotswap h _) = do+ r <- readIORef h++ case r of + Just thread -> do+ killThread thread+ writeIORef h Nothing+ _ -> return ()+-}