diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2011, Mikhail Vorozhtsov
+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 names of the copyright owners nor the names of the 
+  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
diff --git a/data-timeout.cabal b/data-timeout.cabal
new file mode 100644
--- /dev/null
+++ b/data-timeout.cabal
@@ -0,0 +1,35 @@
+Name: data-timeout
+Version: 0.1
+Category: Data, Concurrency
+Stability: experimental
+Synopsis: 64-bit timeouts of nanosecond precision
+Description:
+  This package provides data types and functions for working with 64-bit
+  timeouts of nanosecond precision.
+
+Homepage: https://github.com/mvv/data-timeout
+Bug-Reports: https://github.com/mvv/data-timeout/issues
+
+Author: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+Maintainer: Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+Copyright: 2011 Mikhail Vorozhtsov <mikhail.vorozhtsov@gmail.com>
+License: BSD3
+License-File: LICENSE
+
+Cabal-Version: >= 1.6.0
+Build-Type: Simple
+
+Source-Repository head
+  Type: git
+  Location: https://github.com/mvv/data-timeout.git
+
+Library
+  Build-Depends:
+    base              >= 4 && < 5,
+    transformers-base >= 0.1
+  Hs-Source-Dirs: src
+  GHC-Options: -Wall
+  Exposed-Modules:
+    Data.Timeout
+    Control.Concurrent.Timeout
+
diff --git a/src/Control/Concurrent/Timeout.hs b/src/Control/Concurrent/Timeout.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/Timeout.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE UnicodeSyntax #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleContexts #-}
+-- Do no complain about the System.Timeout import.
+{-# OPTIONS_GHC -fno-warn-unused-imports #-}
+
+module Control.Concurrent.Timeout (
+    timeout,
+    threadDelay
+  ) where
+
+import Data.Typeable
+import Data.Timeout
+import Data.Unique
+import Control.Applicative
+import Control.Monad.Base
+import Control.Exception
+import qualified Control.Concurrent as C
+-- Imported for Haddock.
+import qualified System.Timeout as C
+
+data TimeoutException = TimeoutException Unique
+  deriving (Typeable, Eq)
+
+instance Show TimeoutException where
+  show _ = "<<timeout>>"
+
+instance Exception TimeoutException
+
+-- | A version of 'C.timeout' that takes 'Timeout' instead of number of
+--   microseconds.
+timeout ∷ MonadBase μ IO ⇒ Timeout → IO α → μ (Maybe α)
+timeout tt _ | tt == instantly = return Nothing
+timeout tt io = liftBase $ do
+  pid <- C.myThreadId
+  ex  <- TimeoutException <$> newUnique
+  handleJust (\e -> if e == ex then Just () else Nothing)
+             (\_ -> return Nothing)
+             (bracket (C.forkIO (threadDelay tt >> C.throwTo pid ex))
+                      (C.killThread)
+                      (\_ -> Just <$> io))
+
+-- | A version of 'C.threadDelay' that takes 'Timeout' instead of number of
+--   microseconds.
+threadDelay ∷ MonadBase μ IO ⇒ Timeout → μ ()
+threadDelay tt | tt == instantly = return ()
+threadDelay tt = liftBase $ C.threadDelay (fromIntegral us') >> go us'
+  where us = tt #> MicroSecond
+        maxUs = fromIntegral (maxBound ∷ Int)
+        us' = maxUs `min` us
+        go passed = case us - passed of
+          0    → return ()
+          left → C.threadDelay (fromIntegral us'') >> go us''
+            where us'' = maxUs `min` left
+
diff --git a/src/Data/Timeout.hs b/src/Data/Timeout.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Timeout.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE UnicodeSyntax #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+module Data.Timeout (
+    TimeoutUnit(..),
+    timeoutUnitNanos,
+    Timeout(..),
+    (#),
+    (#>),
+    (#<),
+    instantly
+  ) where
+
+import Data.Typeable (Typeable)
+import Data.Ix (Ix)
+import Data.Word (Word64)
+import Data.List (intercalate)
+
+-- | Timeout unit.
+data TimeoutUnit = NanoSecond
+                 | MicroSecond
+                 | MilliSecond
+                 | Second
+                 | Minute
+                 | Hour
+                 | Day
+                 | Week
+                 deriving (Typeable, Eq, Ord, Bounded, Ix, Enum)
+
+-- | Amount of nanoseconds in a timeout unit.
+timeoutUnitNanos ∷ TimeoutUnit → Word64
+timeoutUnitNanos NanoSecond  = 1
+timeoutUnitNanos MicroSecond = 1000
+timeoutUnitNanos MilliSecond = 1000000
+timeoutUnitNanos Second      = 1000000000
+timeoutUnitNanos Minute      = 60 * 1000000000
+timeoutUnitNanos Hour        = 60 * 60 * 1000000000
+timeoutUnitNanos Day         = 24 * 60 * 60 * 1000000000
+timeoutUnitNanos Week        = 7 * 24 * 60 * 60 * 1000000000
+{-# INLINE timeoutUnitNanos #-}
+
+-- | Timeout in nanoseconds.
+newtype Timeout = Timeout Word64
+  deriving (Typeable, Eq, Ord, Bounded, Ix, Enum, Num, Real, Integral)
+
+infix 9 #
+infix 8 #>, #<
+
+-- | Convert the given number of timeout units to 'Timeout'.
+(#) ∷ Word64 → TimeoutUnit → Timeout
+n # u = Timeout $ n * timeoutUnitNanos u
+{-# INLINE (#) #-}
+
+-- | Extract number of units (rounding up).
+(#>) ∷ Timeout → TimeoutUnit → Word64
+(Timeout tt) #> u = if r == 0 then q else q + 1
+  where (q, r) = tt `quotRem` timeoutUnitNanos u
+{-# INLINE (#>) #-}
+
+-- | Extract number of units (rounding down).
+(#<) ∷ Timeout → TimeoutUnit → Word64
+(Timeout tt) #< u = tt `quot` timeoutUnitNanos u
+{-# INLINE (#<) #-}
+
+timeoutUnitAbbr ∷ TimeoutUnit → String
+timeoutUnitAbbr NanoSecond  = "ns"
+timeoutUnitAbbr MicroSecond = "us"
+timeoutUnitAbbr MilliSecond = "ms"
+timeoutUnitAbbr Second      = "s"
+timeoutUnitAbbr Minute      = "m"
+timeoutUnitAbbr Hour        = "h"
+timeoutUnitAbbr Day         = "d"
+timeoutUnitAbbr Week        = "w"
+
+instance Show Timeout where
+  show (Timeout tt) =
+      if null ss then "instant" else intercalate " " (reverse ss)
+    where
+      ss = snd $ ($ enumFrom NanoSecond) $ (`foldr` (tt, [])) $ \u (t, ss') →
+        let (q, r) = t `quotRem` timeoutUnitNanos u
+            abbr   = timeoutUnitAbbr u in
+          (r, if q == 0 then ss' else (show q ++ " " ++ abbr) : ss')
+
+-- | Zero timeout. The event in question should occur immediately.
+instantly ∷ Timeout
+instantly = 0 # NanoSecond
+{-# INLINE instantly #-}
+
