diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for Concurrent-Cache
+
+## 0.1.0.0  -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/Concurrent-Cache.cabal b/Concurrent-Cache.cabal
new file mode 100644
--- /dev/null
+++ b/Concurrent-Cache.cabal
@@ -0,0 +1,29 @@
+-- Initial Concurrent-Cache.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                Concurrent-Cache
+version:             0.1.0.0
+synopsis:            A Cached variable for IO functions.
+description:         This package allows for caching IO functions, either on a
+                     timeout or designed to only fetch once.
+license:             BSD3
+license-file:        LICENSE
+author:              Marcus Ofenhed
+maintainer:          marcus@conditionraise.se
+-- copyright:           
+category:            Concurrency
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Control.Concurrent.Cache
+  -- other-modules:       
+  -- other-extensions:    
+  build-depends:       base >=4.9 && <4.10
+  -- hs-source-dirs:      
+  default-language:    Haskell2010
+
+Source-Repository head
+  Type:       git
+  Location:   git://github.com/Ofenhed/Concurrent-Cache.git
diff --git a/Control/Concurrent/Cache.hs b/Control/Concurrent/Cache.hs
new file mode 100644
--- /dev/null
+++ b/Control/Concurrent/Cache.hs
@@ -0,0 +1,58 @@
+module Control.Concurrent.Cache (CachedData, fetch, createCache) where
+
+import Data.Maybe (isNothing)
+import Control.Concurrent (forkIO, threadDelay, killThread, MVar, modifyMVar_, readMVar, ThreadId, newMVar)
+import Control.Monad (when, liftM)
+
+data CachedData a = TimedCachedData (Int, (MVar (Maybe ThreadId, IO a, Maybe a))) | ReadOnceCachedData (MVar (Either (IO a) a))
+
+-- |Fetch data from a cache
+fetch :: CachedData a
+      -- ^ @Cache@, the cache to fetch a value from
+      -> IO (a)
+fetch (ReadOnceCachedData mvar) = go where
+  go = readMVar mvar >>= \cached -> do
+    case cached of
+      Left _ -> do
+        modifyMVar_ mvar $ \cached' -> case cached' of
+                                          Left x -> do liftM Right x
+                                          Right x -> return $ Right x
+        go
+      Right value -> return value
+
+fetch (TimedCachedData (timeout, mvar)) = go where
+  go = readMVar mvar >>= \(thread,_,value) -> do
+    case value of
+      Nothing -> do
+        modifyMVar_ mvar $ \mvar'@(threadId', action', value') -> case value' of
+                                          Nothing -> do newVal <- action'
+                                                        return (threadId', action', Just newVal)
+                                          Just x -> return $ mvar'
+        go
+      Just value' -> do 
+        when (not $ isNothing thread) $ let Just thread' = thread in killThread thread'
+        modifyMVar_ mvar $ \(_, action', value') -> do
+          newThreadId <- forkIO $ do
+            threadDelay timeout
+            putStrLn "Deleting"
+            modifyMVar_ mvar $ \(_, action'', _) -> return (Nothing, action'', Nothing)
+          return (Just newThreadId, action', value')
+        return value'
+
+
+-- |Create a cache with a timeout from an (IO ()) function.
+createCache :: Int
+            -- ^ @Timeout@ in microseconds before the cache is erased, 0 to
+            -- disable emptying of the cache
+            -> IO (a)
+            -- ^ @Fetcher@, the function that returns the data which should
+            -- be cached. If @Timeout@ is not set to zero, this function
+            -- must be allowed to be called more than once.
+            -> IO (CachedData a)
+createCache 0 action = do
+  var <- newMVar $ Left action
+  return $ ReadOnceCachedData var
+
+createCache timeout action = do
+  var <- newMVar (Nothing, action, Nothing)
+  return $ TimedCachedData (timeout, var)
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2016, Marcus Ofenhed
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Marcus Ofenhed nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
