diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2015 Edward Kmett
+Copyright 2015 Edward Kmett and Ted Cooper
 
 All rights reserved.
 
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -2,12 +2,17 @@
 
 [![Build Status](https://secure.travis-ci.org/ekmett/rcu.png?branch=master)](http://travis-ci.org/ekmett/rcu)
 
-This package is an exploration of read-copy-update in Haskell based loosely on the API in [Relativistic Programming in Haskell](http://web.cecs.pdx.edu/~walpole/papers/haskell2015.pdf) by Cooper and Walpole, but converted to using STM in the spirit of Howard and Walpole.
+This package is an exploration of Read-Copy Update in Haskell based on [Relativistic Programming in Haskell](http://web.cecs.pdx.edu/~walpole/papers/haskell2015.pdf) by Cooper and Walpole.  It includes a sound QSBR-based implementation and an attempt at an STM-based implementation.
 
+In the spirit of [A Relativistic Enhancement to Software Transactional Memory](https://www.usenix.org/legacy/events/hotpar11/tech/final_files/Howard.pdf)
+ by Howard and Walpole, we could extend the STM implementation to allow reads and writes on the same data in parallel, writes to disjoint data in parallel, and force readers to agree that writes before a `synchronize` happened before writes after it.
+
+Development on this project proceeded in a burst of enthusiasm after Edward saw Ted's poster presentation at ICFP 2015, and yet somehow he managed to shanghai Ted into helping maintain this copy of his own work.
+
 ## Contact Information
 
 Contributions and bug reports are welcome!
 
-Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.
+Please feel free to contact us through github or on the #haskell IRC channel on irc.freenode.net.
 
--Edward Kmett
+-Edward Kmett and Ted Cooper
diff --git a/examples/MoveStringQSBR.hs b/examples/MoveStringQSBR.hs
new file mode 100644
--- /dev/null
+++ b/examples/MoveStringQSBR.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE FlexibleContexts #-}
+import Control.Concurrent.RCU.QSBR
+import Control.Concurrent.RCU.Class
+import Control.Monad (forM, forM_, replicateM)
+import Data.List (group, intercalate)
+import Prelude hiding (read)
+
+data List s a = Nil | Cons a (SRef s (List s a))
+
+snapshot :: MonadReading (SRef s) (m s) => [a] -> List s a -> m s [a]
+snapshot acc Nil         = return $ reverse acc
+snapshot acc (Cons x rn) = snapshot (x : acc) =<< readSRef rn
+
+reader :: Int -> [[a]] -> SRef s (List s a) -> RCU s [[a]]
+reader 0 acc _  = return $ reverse acc
+reader n acc hd = do
+  l <- reading $ snapshot [] =<< readSRef hd
+  reader (n - 1) (l : acc) hd
+
+{-
+deleteMiddle :: SRef s (List s a) -> WritingRCU s ()
+deleteMiddle rl = do
+  Cons a rn <- readSRef rl
+  Cons _ rm <- readSRef rn
+  writeSRef rl $ Cons a rm 
+-}
+
+moveDback :: SRef s (List s Char) -> WritingRCU s ()
+moveDback rl = do
+  Cons _a rb <- readSRef rl
+  Cons _b rc <- readSRef rb
+  -- duplicate pointer to B
+  rb'       <- copySRef rb
+  Cons c rd <- readSRef rc
+  ne        <- readSRef rd
+  -- link in a new C after A
+  writeSRef rb $ Cons c rb'
+  -- any reader who starts during this grace period 
+  -- sees either "ABCDE" or "ACBCDE"
+  synchronize
+  -- unlink the old C
+  writeSRef rc ne
+
+testList :: RCU s (SRef s (List s Char))
+testList = do
+  tl <- newSRef Nil
+  c1   <- newSRef $ Cons 'E' tl
+  c2   <- newSRef $ Cons 'D' c1
+  c3   <- newSRef $ Cons 'C' c2
+  c4   <- newSRef $ Cons 'B' c3
+  newSRef $ Cons 'A' c4
+
+compactShow :: (Show a, Eq a) => [a] -> String
+compactShow xs = intercalate ", " $ map (\xs' -> show (length xs') ++ " x " ++ show (head xs')) $ group xs
+
+main :: IO ()
+main = do 
+  outs <- runRCU $ do
+    -- initialize list
+    hd <- testList
+    -- spawn 8 readers, each records 100000 snapshots of the list
+    rts <- replicateM 8 $ forking $ reader 100000 [] hd
+    -- spawn a writer to move a node from a later position to an earlier position
+    wt  <- forking $ writing $ moveDback hd
+    
+    -- wait for the readers to finish and print snapshots
+    outs <- forM rts $ \rt -> do 
+      v <- joining rt
+      return $ show (rcuThreadId rt) ++ ": " ++ compactShow v
+    -- wait for the writer to finish
+    joining wt
+    return outs
+  forM_ outs putStrLn
diff --git a/examples/MoveStringSTM.hs b/examples/MoveStringSTM.hs
new file mode 100644
--- /dev/null
+++ b/examples/MoveStringSTM.hs
@@ -0,0 +1,73 @@
+{-# LANGUAGE FlexibleContexts #-}
+import Control.Concurrent.MVar (takeMVar)
+import Control.Concurrent.RCU.STM
+import Control.Concurrent.RCU.Class
+import Control.Monad (forM, forM_, replicateM)
+import Data.List (group, intercalate)
+import Debug.Trace (trace)
+import Prelude hiding (read)
+
+data List s a = Nil | Cons a (SRef s (List s a))
+
+snapshot :: MonadReading (SRef s) (m s) => [a] -> List s a -> m s [a]
+snapshot acc Nil         = return $ reverse acc
+snapshot acc (Cons x rn) = snapshot (x : acc) =<< readSRef rn
+
+reader :: Int -> [[a]] -> SRef s (List s a) -> RCU s [[a]]
+reader 0 acc _    = return $ reverse acc
+reader n acc head = do
+  l <- reading $ snapshot [] =<< readSRef head
+  reader (n - 1) (l : acc) head
+
+deleteMiddle :: SRef s (List s a) -> WritingRCU s ()
+deleteMiddle rl = do
+  Cons a rn <- readSRef rl
+  Cons _ rm <- readSRef rn
+  writeSRef rl $ Cons a rm 
+
+moveDback :: SRef s (List s Char) -> WritingRCU s ()
+moveDback rl = do
+  Cons a rb <- readSRef rl
+  Cons b rc <- readSRef rb
+  -- duplicate pointer to B
+  rb'       <- copySRef rb
+  Cons c rd <- readSRef rc
+  ne        <- readSRef rd
+  -- link in a new C after A
+  writeSRef rb $ Cons c rb'
+  -- any reader who starts during this grace period 
+  -- sees either "ABCDE" or "ACBCDE"
+  synchronize
+  -- unlink the old C
+  writeSRef rc ne
+
+testList :: RCU s (SRef s (List s Char))
+testList = do
+  tail <- newSRef Nil
+  c1   <- newSRef $ Cons 'E' tail
+  c2   <- newSRef $ Cons 'D' c1
+  c3   <- newSRef $ Cons 'C' c2
+  c4   <- newSRef $ Cons 'B' c3
+  newSRef $ Cons 'A' c4
+
+compactShow :: (Show a, Eq a) => [a] -> String
+compactShow xs = intercalate ", " $ map (\xs -> show (length xs) ++ " x " ++ show (head xs)) $ group xs
+
+main :: IO ()
+main = do 
+  outs <- runRCU $ do
+    -- initialize list
+    head <- testList
+    -- spawn 8 readers, each records 100000 snapshots of the list
+    rts <- replicateM 8 $ forking $ reader 100000 [] head
+    -- spawn a writer to move a node from a later position to an earlier position
+    wt  <- forking $ writing $ moveDback head
+    
+    -- wait for the readers to finish and print snapshots
+    outs <- forM rts $ \rt -> do 
+      v <- joining rt
+      return $ show (rcuThreadId rt) ++ ": " ++ compactShow v
+    -- wait for the writer to finish
+    joining wt
+    return outs
+  forM_ outs putStrLn
diff --git a/examples/RPManyListMoveTest.hs b/examples/RPManyListMoveTest.hs
deleted file mode 100644
--- a/examples/RPManyListMoveTest.hs
+++ /dev/null
@@ -1,162 +0,0 @@
-{-# LANGUAGE NamedFieldPuns #-}
-import Control.Concurrent.RCU
-import Control.Concurrent.MVar (takeMVar)
-import Control.Monad (foldM, forM, forM_, replicateM, when)
-import Data.List ((\\), foldl1', group, intercalate)
-import Debug.Trace (trace)
-
-data RPList s a = Nil
-                | Cons a (SRef s (RPList s a))
-
-data ReaderStats = ReaderStats { total   :: !Integer
-                               , full    :: !Integer
-                               , missing :: !Integer }
-                   deriving Show
-
-sappend' s1 s2 = 
-  s1 `seq` s2 `seq` ReaderStats { total   = total   s1 + total   s2
-                                , full    = full    s1 + full    s2
-                                , missing = missing s1 + missing s2 }
-
-
-snapshot :: Show a => RPList s a -> RPR s [a]
-snapshot Nil         = return []
-snapshot (Cons x rn) = do 
-  l    <- readSRef rn
-  --writeSRef rn (Cons undefined rn)
-  rest <- snapshot l
-  return $ x : rest
-
-readSection :: Show a => SRef s (RPList s a) -> RPR s [a]
-readSection head = do
-  snapshot =<< readSRef head
-
-readThread :: [Char] -> Int -> SRef s (RPList s Char) -> RPE s ReaderStats
-readThread ls n head = 
-  let st = ReaderStats { total = 0, full = 0, missing = 0 }
-      ft = ReaderStats { total = 1, full = 1, missing = 0 }
-      et = ReaderStats { total = 1, full = 0, missing = 1 }
-      trav st _ = do
-        xs <- st `seq` reading $ readSection head
-        -- use a strict append operation to avoid building up a giant thunk
-        return $ st `sappend'` if null $ ls \\ xs then ft else et
-      res = foldM trav st [1..n]
-  in res `seq` res
-
-testList :: RP s (SRef s (RPList s Char))
-testList = do
-  tail <- newSRef Nil
-  c4   <- newSRef $ Cons 'E' tail
-  c3   <- newSRef $ Cons 'D' c4
-  c2   <- newSRef $ Cons 'C' c3
-  c1   <- newSRef $ Cons 'B' c2
-  newSRef $ Cons 'A' c1
-
-compactShow :: (Show a, Eq a) => [a] -> String
-compactShow xs = intercalate ", " $ map (\xs -> show (length xs) ++ " x " ++ show (head xs)) $ group xs
-
--- left half of a zipper
--- n = 0 gets the first element
--- n = 1 gets the second elemnt, followed by the first
--- ...
-nNext :: (Monad (m s), RPRead m s) => Int -> SRef s (RPList s a) -> m s [(RPList s a)]
-nNext n head = return . snd =<< foldM scroll (head, []) [1..(max n 0)]
-  where scroll (r,ns) _ = do
-          node <- readSRef r
-          return $ case node of (Cons _ r') -> (r', node:ns)
-                                _           -> error "nNext tried to go past the end of the list"
-
-moveNodeForward :: Int -> Int -> SRef s (RPList s a) -> RPW s ()
-moveNodeForward i n head = do
-  when (n <= 0) $ error "nullary move operation not allowed"
-  -- get relevant references at earlier position
-  (Cons ep rep):_   <- nNext i head
-  (Cons x rx)       <- readSRef rep
-  esn               <- readSRef rx
-  -- get relevant references at later position
-  (Cons lp rlp):_   <- nNext n rep
-  -- the new node will need a reference to the new predecessor's current successor
-  rlp'              <- copySRef rlp
-  -- link in a new copy of the node after its new predecessor
-  writeSRef rlp $! Cons x rlp'
-  -- we're writing against traversal order, so we don't need to synchronize here.
-  -- unlink the old copy of the node at its original position
-  writeSRef rep $! esn
-
-moveBforward :: SRef s (RPList s a) -> RPW s ()
-moveBforward head = do
-  (Cons a ra)    <- readSRef head  -- [A,B,C,D,E]
-  bn@(Cons b rb) <- readSRef ra
-  (Cons c rc)    <- readSRef rb
-  (Cons d rd)    <- readSRef rc
-  -- duplicate the reference to E
-  rd'            <- copySRef rd
-  -- link in a new B after D
-  writeSRef rd $! Cons b rd'        -- [A,B,C,D,B,E]
-  --synchronizeRP -- interaction of write order and traversal order means you don't need this
-  -- unlink the old B
-  writeSRef ra bn                  -- [A,C,D,B,E]
-
-moveCback :: SRef s (RPList s a) -> RPW s ()
-moveCback head = do
-  (Cons a rb)    <- readSRef head
-  (Cons b rc)    <- readSRef rb
-  -- duplicate pointer to B
-  rb'            <- copySRef rb
-  (Cons c rd)    <- readSRef rc
-  de             <- readSRef rd
-  -- link in a new C after A
-  writeSRef rb $ Cons c rb'
-  -- any reader who starts during this grace period 
-  -- sees either "ABCD" or "ACBCD"
-  synchronizeRP
-  -- unlink the old C
-  writeSRef rc de
-  -- any reader who starts during this grace period 
-  -- sees either "ACBCD" or "ACBD" 
-
-moveCbackNoSync :: SRef s (RPList s a) -> RPW s ()
-moveCbackNoSync head = do
-  (Cons a rb)    <- readSRef head
-  (Cons b rc)    <- readSRef rb
-  -- duplicate reference to B
-  rb'            <- copySRef rb
-  (Cons c rd)    <- readSRef rc
-  de             <- readSRef rd
-  -- link in a new C after A
-  writeSRef rb $! Cons c rb'
-  -- any reader who starts after this write is issued
-  -- sees either "ABCD" or "ACBCD"
-  --synchronizeRP -- this operation is NOT safe to omit, 
-                  -- because write order and traversal order are the same
-  -- unlink the old C
-  writeSRef rc de
-  -- any reader who starts after this write is issued
-  -- sees "ABD", "ACBCD", or "ACBD" 
-
-main :: IO ()
-main = do 
-  let n = 100
-  rsts <- replicateM n $ do
-    runRP $ do
-      -- initialize list
-      head <- testList
-      -- spawn 8 readers, each records 10000 snapshots of the list
-      --rts  <- replicateM 8 $ forking $ replicateM 400000 $ reading $ readSection head
-      rts  <- replicateM 29 $ forking $ readThread "ABCDE" 400000 head
-      -- spawn a writer to delete the middle node
-      --wt   <- forking $ writing $ moveCback head
-      --wt   <- forking $ writing $ moveCbackNoSync head
-      wt   <- forking $ writing $ moveBforward head
-      --wt   <- forking $ writing $ moveNodeForward 1 1 head
-      --wt <- forking $ writing $ return ()
-      
-      -- wait for the readers to finish and print snapshots
-      rsts <- forM rts $ \rt -> do 
-        rst <- joining rt
-        rst `seq` return $ rst
-      -- wait for the writer to finish
-      joining wt
-      return $ foldl1' sappend' rsts
-  let rst = foldl1' sappend' rsts
-  putStrLn $ "n: " ++ show n ++ ", " ++ show rst
diff --git a/rcu.cabal b/rcu.cabal
--- a/rcu.cabal
+++ b/rcu.cabal
@@ -1,19 +1,19 @@
 name:          rcu
 category:      Data
-version:       0
+version:       0.1
 license:       BSD3
 cabal-version: >= 1.22
 license-file:  LICENSE
-author:        Edward A. Kmett
-maintainer:    Edward A. Kmett <ekmett@gmail.com>
+author:        Ted Cooper and Edward A. Kmett
+maintainer:    Edward A. Kmett <ekmett@gmail.com>, Ted Cooper <anthezium@gmail.com>
 stability:     provisional
 homepage:      http://github.com/ekmett/rcu/
 bug-reports:   http://github.com/ekmett/rcu/issues
-copyright:     Copyright (C) 2015 Edward A. Kmett
+copyright:     Copyright (C) 2015 Edward A. Kmett, Theodore Rhys Cooper
 build-type:    Custom
 tested-with:   GHC == 7.10.1, GHC == 7.10.2
-synopsis:      STM-based Read-Copy-Update
-description:   STM-based Read-Copy-Update
+synopsis:      Read-Copy-Update for Haskell
+description:   Read-Copy-Update for Haskell
 
 extra-source-files:
   examples/*.hs
@@ -34,20 +34,60 @@
   default: True
   manual: True
 
+-- Include unstable and/or potentially incorrect implementations.
+flag unstable
+  default: False
+  manual: True
+
 library
   build-depends:
+    atomic-primops,
     base >= 4.8 && < 5,
-    stm >= 2.4.4 && < 2.5,
+    parallel >= 3.2 && < 3.3,
+    primitive,
     transformers >= 0.4 && < 0.5
 
   exposed-modules:
-    Control.Concurrent.RCU
     Control.Concurrent.RCU.Class
-    Control.Concurrent.RCU.Internal
+    Control.Concurrent.RCU.QSBR
+    Control.Concurrent.RCU.QSBR.Internal
 
   ghc-options: -Wall -fwarn-tabs
-
   hs-source-dirs: src
+  default-language: Haskell2010
+
+  if flag(unstable)
+    hs-source-dirs: unstable
+    build-depends: stm >= 2.4.4 && < 2.5
+    exposed-modules:
+      Control.Concurrent.RCU.STM
+      Control.Concurrent.RCU.STM.Internal
+
+executable MoveStringSTM
+  main-is: MoveStringSTM.hs
+  if !flag(unstable)
+    buildable: False
+  else
+    build-depends:
+      base >= 4.8 && < 5,
+      rcu,
+      stm >= 2.4.4 && < 2.5,
+      transformers >= 0.4 && < 0.5
+
+    hs-source-dirs: examples
+    ghc-options: -threaded -Wall -fwarn-tabs "-with-rtsopts=-N"
+    default-language: Haskell2010
+
+executable MoveStringQSBR
+  main-is: MoveStringQSBR.hs
+  build-depends:
+    base >= 4.8 && < 5,
+    rcu,
+    stm >= 2.4.4 && < 2.5,
+    transformers >= 0.4 && < 0.5
+
+  hs-source-dirs: examples
+  ghc-options: -threaded -Wall -fwarn-tabs "-with-rtsopts=-N"
   default-language: Haskell2010
 
 test-suite doctests
diff --git a/src/Control/Concurrent/RCU.hs b/src/Control/Concurrent/RCU.hs
deleted file mode 100644
--- a/src/Control/Concurrent/RCU.hs
+++ /dev/null
@@ -1,24 +0,0 @@
-{-# LANGUAGE Trustworthy #-}
------------------------------------------------------------------------------
--- |
--- Copyright   :  (C) 2015 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
------------------------------------------------------------------------------
-module Control.Concurrent.RCU
-  ( SRef
-  , RCU, runRCU
-  , MonadNew(..)
-  , MonadReading(..)
-  , MonadWriting(..)
-  , MonadRCU(..)
-  -- * Implementation Details
-  , ReadingRCU
-  , WritingRCU
-  , RCUThread(rcuThreadId)
-  ) where
-
-import Control.Concurrent.RCU.Internal
diff --git a/src/Control/Concurrent/RCU/Class.hs b/src/Control/Concurrent/RCU/Class.hs
--- a/src/Control/Concurrent/RCU/Class.hs
+++ b/src/Control/Concurrent/RCU/Class.hs
@@ -1,19 +1,234 @@
-{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE Safe #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# OPTIONS_HADDOCK not-home #-}
 -----------------------------------------------------------------------------
 -- |
--- Copyright   :  (C) 2015 Edward Kmett
+-- Copyright   :  (C) 2015 Edward Kmett and Ted Cooper
 -- License     :  BSD-style (see the file LICENSE)
 -- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+--                Ted Cooper <anthezium@gmail.com>
 -- Stability   :  experimental
 -- Portability :  non-portable
 --
 -----------------------------------------------------------------------------
 module Control.Concurrent.RCU.Class
-  ( SRef
-  , MonadNew(..)
+  ( MonadNew(..)
   , MonadReading(..)
   , MonadWriting(..)
   , MonadRCU(..)
+  , copySRef
   ) where
 
-import Control.Concurrent.RCU.Internal
+import Control.Applicative
+import Control.Monad
+import Control.Monad.Trans.Class
+import Control.Monad.Trans.Except
+import Control.Monad.Trans.Identity
+import Control.Monad.Trans.Maybe
+import Control.Monad.Trans.Reader
+import Prelude hiding (read, Read)
+import qualified Control.Monad.Trans.RWS.Lazy as Lazy
+import qualified Control.Monad.Trans.RWS.Strict as Strict
+import qualified Control.Monad.Trans.State.Lazy as Lazy
+import qualified Control.Monad.Trans.State.Strict as Strict
+import qualified Control.Monad.Trans.Writer.Lazy as Lazy
+import qualified Control.Monad.Trans.Writer.Strict as Strict
+
+--------------------------------------------------------------------------------
+-- * MonadNew
+--------------------------------------------------------------------------------
+
+class Monad m => MonadNew s m | m -> s where
+  -- | Build a new shared reference
+  newSRef :: a -> m (s a)
+  default newSRef :: (m ~ t n, MonadTrans t, MonadNew s n) => a -> m (s a)
+  newSRef a = lift (newSRef a)
+
+instance MonadNew s m => MonadNew s (ReaderT e m)
+instance (MonadNew s m, Monoid w) => MonadNew s (Strict.WriterT w m)
+instance (MonadNew s m, Monoid w) => MonadNew s (Lazy.WriterT w m)
+instance MonadNew s' m => MonadNew s' (Strict.StateT s m)
+instance MonadNew s' m => MonadNew s' (Lazy.StateT s m)
+instance (MonadNew s' m, Monoid w) => MonadNew s' (Strict.RWST r w s m)
+instance (MonadNew s' m, Monoid w) => MonadNew s' (Lazy.RWST r w s m)
+instance MonadNew s m => MonadNew s (ExceptT e m)
+instance MonadNew s m => MonadNew s (MaybeT m)
+instance MonadNew s m => MonadNew s (IdentityT m)
+
+--------------------------------------------------------------------------------
+-- * MonadReading
+--------------------------------------------------------------------------------
+
+-- | This is a read-side critical section
+class MonadNew s m => MonadReading s m | m -> s where
+  -- | Read a shared reference.
+  readSRef :: s a -> m a
+  default readSRef :: (m ~ t n, MonadTrans t, MonadReading s n) => s a -> m a
+  readSRef r = lift (readSRef r)
+  {-# INLINE readSRef #-}
+
+-- | Copy a shared reference.
+copySRef :: MonadReading s m => s a -> m (s a)
+copySRef r = do
+  a <- readSRef r
+  newSRef a
+{-# INLINE copySRef #-}
+
+instance MonadReading s m => MonadReading s (ReaderT e m)
+instance (MonadReading s m, Monoid w) => MonadReading s (Strict.WriterT w m)
+instance (MonadReading s m, Monoid w) => MonadReading s (Lazy.WriterT w m)
+instance MonadReading s' m => MonadReading s' (Strict.StateT s m)
+instance MonadReading s' m => MonadReading s' (Lazy.StateT s m)
+instance (MonadReading s' m, Monoid w) => MonadReading s' (Strict.RWST r w s m)
+instance (MonadReading s' m, Monoid w) => MonadReading s' (Lazy.RWST r w s m)
+instance MonadReading s m => MonadReading s (ExceptT e m)
+instance MonadReading s m => MonadReading s (MaybeT m)
+instance MonadReading s m => MonadReading s (IdentityT m)
+
+--------------------------------------------------------------------------------
+-- * MonadWriting
+--------------------------------------------------------------------------------
+
+-- | This is a write-side critical section
+class MonadReading s m => MonadWriting s m | m -> s where
+  -- | Write to a shared reference.
+  writeSRef :: s a -> a -> m ()
+  default writeSRef :: (m ~ t n, MonadTrans t, MonadWriting s n) => s a -> a -> m ()
+  writeSRef r a = lift (writeSRef r a)
+
+  -- | Synchronize with other writers.
+  --
+  -- No other writer can straddle this time bound. It will either see writes from before, or writes after, but never 
+  -- some of both!
+  synchronize :: m ()
+  default synchronize :: (m ~ t n, MonadTrans t, MonadWriting s n) => m ()
+  synchronize = lift synchronize
+
+instance MonadWriting s m => MonadWriting s (ReaderT e m)
+instance (MonadWriting s m, Monoid w) => MonadWriting s (Strict.WriterT w m)
+instance (MonadWriting s m, Monoid w) => MonadWriting s (Lazy.WriterT w m)
+instance MonadWriting s' m => MonadWriting s' (Strict.StateT s m)
+instance MonadWriting s' m => MonadWriting s' (Lazy.StateT s m)
+instance (MonadWriting s' m, Monoid w) => MonadWriting s' (Strict.RWST r w s m)
+instance (MonadWriting s' m, Monoid w) => MonadWriting s' (Lazy.RWST r w s m)
+instance MonadWriting s m => MonadWriting s (IdentityT m)
+instance MonadWriting s m => MonadWriting s (ExceptT e m)
+instance MonadWriting s m => MonadWriting s (MaybeT m)
+
+--------------------------------------------------------------------------------
+-- * MonadRCU
+--------------------------------------------------------------------------------
+
+-- | This is the executor service that can fork, join and execute critical sections.
+class
+  ( MonadReading s (Reading m)
+  , MonadWriting s (Writing m)
+  , MonadNew s m
+  ) => MonadRCU s m | m -> s where
+
+  -- | A read-side critical section
+  type Reading m :: * -> *
+
+  -- | A write-side critical section
+  type Writing m :: * -> *
+
+  -- | Threads we can fork and join
+  type Thread m :: * -> *
+
+  -- | Fork a thread
+  forking :: m a -> m (Thread m a)
+
+  -- | Join a thread
+  joining :: Thread m a -> m a
+
+  -- | Run a read-side critical section
+  reading :: Reading m a -> m a
+
+  -- | Run a write-side critical section
+  writing :: Writing m a -> m a
+
+instance MonadRCU s m => MonadRCU s (ReaderT e m) where
+  type Reading (ReaderT e m) = ReaderT e (Reading m)
+  type Writing (ReaderT e m) = ReaderT e (Writing m)
+  type Thread (ReaderT e m) = Thread m
+  forking (ReaderT f)  = ReaderT $ \a -> forking (f a)
+  joining = lift . joining
+  reading (ReaderT f) = ReaderT $ \a -> reading (f a)
+  writing (ReaderT f) = ReaderT $ \a -> writing (f a)
+  {-# INLINE forking #-}
+  {-# INLINE joining #-}
+  {-# INLINE reading #-}
+  {-# INLINE writing #-}
+
+instance MonadRCU s m => MonadRCU s (IdentityT m) where
+  type Reading (IdentityT m) = Reading m
+  type Writing (IdentityT m) = Writing m
+  type Thread (IdentityT m) = Thread m
+  forking (IdentityT m) = IdentityT (forking m)
+  joining = lift . joining
+  reading m = IdentityT (reading m)
+  writing m = IdentityT (writing m)
+  {-# INLINE forking #-}
+  {-# INLINE joining #-}
+  {-# INLINE reading #-}
+  {-# INLINE writing #-}
+
+instance MonadRCU s m => MonadRCU s (ExceptT e m) where
+  type Reading (ExceptT e m) = ExceptT e (Reading m)
+  type Writing (ExceptT e m) = ExceptT e (Writing m)
+  type Thread (ExceptT e m) = ExceptT e (Thread m)
+  forking (ExceptT m) = lift $ ExceptT <$> forking m
+  joining (ExceptT m) = ExceptT $ joining m
+  reading (ExceptT m) = ExceptT $ reading m
+  writing (ExceptT m) = ExceptT $ writing m
+  {-# INLINE forking #-}
+  {-# INLINE joining #-}
+  {-# INLINE reading #-}
+  {-# INLINE writing #-}
+
+instance MonadRCU s m => MonadRCU s (MaybeT m) where
+  type Reading (MaybeT m) = MaybeT (Reading m)
+  type Writing (MaybeT m) = MaybeT (Writing m)
+  type Thread (MaybeT m) = MaybeT (Thread m)
+  forking (MaybeT m) = lift $ MaybeT <$> forking m
+  joining (MaybeT m) = MaybeT $ joining m
+  reading (MaybeT m) = MaybeT $ reading m
+  writing (MaybeT m) = MaybeT $ writing m
+  {-# INLINE forking #-}
+  {-# INLINE joining #-}
+  {-# INLINE reading #-}
+  {-# INLINE writing #-}
+
+instance (MonadRCU s m, Monoid e) => MonadRCU s (Strict.WriterT e m) where
+  type Reading (Strict.WriterT e m) = Strict.WriterT e (Reading m)
+  type Writing (Strict.WriterT e m) = Strict.WriterT e (Writing m)
+  type Thread (Strict.WriterT e m) = Strict.WriterT e (Thread m)
+  forking (Strict.WriterT m) = lift $ Strict.WriterT <$> forking m
+  joining (Strict.WriterT m) = Strict.WriterT $ joining m
+  reading (Strict.WriterT m) = Strict.WriterT $ reading m
+  writing (Strict.WriterT m) = Strict.WriterT $ writing m
+  {-# INLINE forking #-}
+  {-# INLINE joining #-}
+  {-# INLINE reading #-}
+  {-# INLINE writing #-}
+
+instance (MonadRCU s m, Monoid e) => MonadRCU s (Lazy.WriterT e m) where
+  type Reading (Lazy.WriterT e m) = Lazy.WriterT e (Reading m)
+  type Writing (Lazy.WriterT e m) = Lazy.WriterT e (Writing m)
+  type Thread (Lazy.WriterT e m) = Lazy.WriterT e (Thread m)
+  forking (Lazy.WriterT m) = lift $ Lazy.WriterT <$> forking m
+  joining (Lazy.WriterT m) = Lazy.WriterT $ joining m
+  reading (Lazy.WriterT m) = Lazy.WriterT $ reading m
+  writing (Lazy.WriterT m) = Lazy.WriterT $ writing m
+  {-# INLINE forking #-}
+  {-# INLINE joining #-}
+  {-# INLINE reading #-}
+  {-# INLINE writing #-}
diff --git a/src/Control/Concurrent/RCU/Internal.hs b/src/Control/Concurrent/RCU/Internal.hs
deleted file mode 100644
--- a/src/Control/Concurrent/RCU/Internal.hs
+++ /dev/null
@@ -1,374 +0,0 @@
-{-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE DeriveFunctor #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE DefaultSignatures #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# OPTIONS_HADDOCK not-home #-}
------------------------------------------------------------------------------
--- |
--- Copyright   :  (C) 2015 Edward Kmett
--- License     :  BSD-style (see the file LICENSE)
--- Maintainer  :  Edward Kmett <ekmett@gmail.com>
--- Stability   :  experimental
--- Portability :  non-portable
---
--- STM-based RCU with concurrent writers
------------------------------------------------------------------------------
-module Control.Concurrent.RCU.Internal
-  ( SRef(..)
-  , RCUThread(..)
-  , RCU(..)
-  , runRCU
-  , ReadingRCU(..)
-  , WritingRCU(..)
-  , MonadNew(..)
-  , MonadReading(..)
-  , copySRef
-  , MonadWriting(..)
-  , MonadRCU(..)
-  ) where
-
-import Control.Applicative
-import Control.Concurrent
-import Control.Concurrent.STM
-import Control.Monad
-import Control.Monad.IO.Class
-import Control.Monad.Trans.Class
-import Control.Monad.Trans.Except
-import Control.Monad.Trans.Identity
-import Control.Monad.Trans.Maybe
-import Control.Monad.Trans.Reader
-import Data.Coerce
-import Data.Int
-import Prelude hiding (read, Read)
-import qualified Control.Monad.Trans.RWS.Lazy as Lazy
-import qualified Control.Monad.Trans.RWS.Strict as Strict
-import qualified Control.Monad.Trans.State.Lazy as Lazy
-import qualified Control.Monad.Trans.State.Strict as Strict
-import qualified Control.Monad.Trans.Writer.Lazy as Lazy
-import qualified Control.Monad.Trans.Writer.Strict as Strict
-
---------------------------------------------------------------------------------
--- * Shared References
---------------------------------------------------------------------------------
-
--- | Shared references
-newtype SRef s a = SRef { unSRef :: TVar a }
-  deriving Eq
-
---------------------------------------------------------------------------------
--- * MonadNew
---------------------------------------------------------------------------------
-
-class Monad m => MonadNew s m | m -> s where
-  -- | Build a new shared reference
-  newSRef :: a -> m (SRef s a)
-  default newSRef :: (m ~ t n, MonadTrans t, MonadNew s n) => a -> m (SRef s a)
-  newSRef a = lift (newSRef a)
-
-instance MonadNew s m => MonadNew s (ReaderT e m)
-instance (MonadNew s m, Monoid w) => MonadNew s (Strict.WriterT w m)
-instance (MonadNew s m, Monoid w) => MonadNew s (Lazy.WriterT w m)
-instance MonadNew s' m => MonadNew s' (Strict.StateT s m)
-instance MonadNew s' m => MonadNew s' (Lazy.StateT s m)
-instance (MonadNew s' m, Monoid w) => MonadNew s' (Strict.RWST r w s m)
-instance (MonadNew s' m, Monoid w) => MonadNew s' (Lazy.RWST r w s m)
-instance MonadNew s m => MonadNew s (ExceptT e m)
-instance MonadNew s m => MonadNew s (MaybeT m)
-instance MonadNew s m => MonadNew s (IdentityT m)
-
---------------------------------------------------------------------------------
--- * MonadReading
---------------------------------------------------------------------------------
-
--- | This is a read-side critical section
-class MonadNew s m => MonadReading s m | m -> s where
-  -- | Read a shared reference.
-  readSRef :: SRef s a -> m a
-  default readSRef :: (m ~ t n, MonadTrans t, MonadReading s n) => SRef s a -> m a
-  readSRef r = lift (readSRef r)
-  {-# INLINE readSRef #-}
-
--- | Copy a shared reference.
-copySRef :: MonadReading s m => SRef s a -> m (SRef s a)
-copySRef r = do
-  a <- readSRef r
-  newSRef a
-{-# INLINE copySRef #-}
-
-instance MonadReading s m => MonadReading s (ReaderT e m)
-instance (MonadReading s m, Monoid w) => MonadReading s (Strict.WriterT w m)
-instance (MonadReading s m, Monoid w) => MonadReading s (Lazy.WriterT w m)
-instance MonadReading s' m => MonadReading s' (Strict.StateT s m)
-instance MonadReading s' m => MonadReading s' (Lazy.StateT s m)
-instance (MonadReading s' m, Monoid w) => MonadReading s' (Strict.RWST r w s m)
-instance (MonadReading s' m, Monoid w) => MonadReading s' (Lazy.RWST r w s m)
-instance MonadReading s m => MonadReading s (ExceptT e m)
-instance MonadReading s m => MonadReading s (MaybeT m)
-instance MonadReading s m => MonadReading s (IdentityT m)
-
---------------------------------------------------------------------------------
--- * MonadWriting
---------------------------------------------------------------------------------
-
--- | This is a write-side critical section
-class MonadReading s m => MonadWriting s m | m -> s where
-  -- | Write to a shared reference.
-  writeSRef :: SRef s a -> a -> m ()
-  default writeSRef :: (m ~ t n, MonadTrans t, MonadWriting s n) => SRef s a -> a -> m ()
-  writeSRef r a = lift (writeSRef r a)
-
-  -- | Synchronize with other writers.
-  --
-  -- No other writer can straddle this time bound. It will either see writes from before, or writes after, but never 
-  -- some of both!
-  synchronize :: m ()
-  default synchronize :: (m ~ t n, MonadTrans t, MonadWriting s n) => m ()
-  synchronize = lift synchronize
-
-instance MonadWriting s m => MonadWriting s (ReaderT e m)
-instance (MonadWriting s m, Monoid w) => MonadWriting s (Strict.WriterT w m)
-instance (MonadWriting s m, Monoid w) => MonadWriting s (Lazy.WriterT w m)
-instance MonadWriting s m => MonadWriting s (Strict.StateT s m)
-instance MonadWriting s m => MonadWriting s (Lazy.StateT s m)
-instance (MonadWriting s m, Monoid w) => MonadWriting s (Strict.RWST r w s m)
-instance (MonadWriting s m, Monoid w) => MonadWriting s (Lazy.RWST r w s m)
-instance MonadWriting s m => MonadWriting s (IdentityT m)
-instance MonadWriting s m => MonadWriting s (ExceptT e m)
-instance MonadWriting s m => MonadWriting s (MaybeT m)
-
---------------------------------------------------------------------------------
--- * MonadRCU
---------------------------------------------------------------------------------
-
--- | This is the executor service that can fork, join and execute critical sections.
-class
-  ( MonadReading s (Reading m)
-  , MonadWriting s (Writing m)
-  , MonadNew s m
-  ) => MonadRCU s m | m -> s where
-
-  -- | A read-side critical section
-  type Reading m :: * -> *
-
-  -- | A write-side critical section
-  type Writing m :: * -> *
-
-  -- | Threads we can fork and join
-  type Thread m :: * -> *
-
-  -- | Fork a thread
-  forking  :: m a -> m (Thread m a)
-
-  -- | Join a thread
-  joining  :: Thread m a -> m a
-
-  -- | Run a read-side critical section
-  reading :: Reading m a -> m a
-
-  -- | Run a write-side critical section
-  writing :: Writing m a -> m a
-
-instance MonadRCU s m => MonadRCU s (ReaderT e m) where
-  type Reading (ReaderT e m) = ReaderT e (Reading m)
-  type Writing (ReaderT e m) = ReaderT e (Writing m)
-  type Thread (ReaderT e m) = Thread m
-  forking (ReaderT f)  = ReaderT $ \a -> forking (f a)
-  joining = lift . joining
-  reading (ReaderT f) = ReaderT $ \a -> reading (f a)
-  writing (ReaderT f) = ReaderT $ \a -> writing (f a)
-  {-# INLINE forking #-}
-  {-# INLINE joining #-}
-  {-# INLINE reading #-}
-  {-# INLINE writing #-}
-
-instance MonadRCU s m => MonadRCU s (IdentityT m) where
-  type Reading (IdentityT m) = Reading m
-  type Writing (IdentityT m) = Writing m
-  type Thread (IdentityT m) = Thread m
-  forking (IdentityT m) = IdentityT (forking m)
-  joining = lift . joining
-  reading m = IdentityT (reading m)
-  writing m = IdentityT (writing m)
-  {-# INLINE forking #-}
-  {-# INLINE joining #-}
-  {-# INLINE reading #-}
-  {-# INLINE writing #-}
-
-instance MonadRCU s m => MonadRCU s (ExceptT e m) where
-  type Reading (ExceptT e m) = ExceptT e (Reading m)
-  type Writing (ExceptT e m) = ExceptT e (Writing m)
-  type Thread (ExceptT e m) = ExceptT e (Thread m)
-  forking (ExceptT m) = lift $ ExceptT <$> forking m
-  joining (ExceptT m) = ExceptT $ joining m
-  reading (ExceptT m) = ExceptT $ reading m
-  writing (ExceptT m) = ExceptT $ writing m
-  {-# INLINE forking #-}
-  {-# INLINE joining #-}
-  {-# INLINE reading #-}
-  {-# INLINE writing #-}
-
-instance MonadRCU s m => MonadRCU s (MaybeT m) where
-  type Reading (MaybeT m) = MaybeT (Reading m)
-  type Writing (MaybeT m) = MaybeT (Writing m)
-  type Thread (MaybeT m) = MaybeT (Thread m)
-  forking (MaybeT m) = lift $ MaybeT <$> forking m
-  joining (MaybeT m) = MaybeT $ joining m
-  reading (MaybeT m) = MaybeT $ reading m
-  writing (MaybeT m) = MaybeT $ writing m
-  {-# INLINE forking #-}
-  {-# INLINE joining #-}
-  {-# INLINE reading #-}
-  {-# INLINE writing #-}
-
-instance (MonadRCU s m, Monoid e) => MonadRCU s (Strict.WriterT e m) where
-  type Reading (Strict.WriterT e m) = Strict.WriterT e (Reading m)
-  type Writing (Strict.WriterT e m) = Strict.WriterT e (Writing m)
-  type Thread (Strict.WriterT e m) = Strict.WriterT e (Thread m)
-  forking (Strict.WriterT m) = lift $ Strict.WriterT <$> forking m
-  joining (Strict.WriterT m) = Strict.WriterT $ joining m
-  reading (Strict.WriterT m) = Strict.WriterT $ reading m
-  writing (Strict.WriterT m) = Strict.WriterT $ writing m
-  {-# INLINE forking #-}
-  {-# INLINE joining #-}
-  {-# INLINE reading #-}
-  {-# INLINE writing #-}
-
-instance (MonadRCU s m, Monoid e) => MonadRCU s (Lazy.WriterT e m) where
-  type Reading (Lazy.WriterT e m) = Lazy.WriterT e (Reading m)
-  type Writing (Lazy.WriterT e m) = Lazy.WriterT e (Writing m)
-  type Thread (Lazy.WriterT e m) = Lazy.WriterT e (Thread m)
-  forking (Lazy.WriterT m) = lift $ Lazy.WriterT <$> forking m
-  joining (Lazy.WriterT m) = Lazy.WriterT $ joining m
-  reading (Lazy.WriterT m) = Lazy.WriterT $ reading m
-  writing (Lazy.WriterT m) = Lazy.WriterT $ writing m
-  {-# INLINE forking #-}
-  {-# INLINE joining #-}
-  {-# INLINE reading #-}
-  {-# INLINE writing #-}
-
---------------------------------------------------------------------------------
--- * Read-Side Critical Sections
---------------------------------------------------------------------------------
-
--- | This is the basic read-side critical section for an RCU computation
-newtype ReadingRCU s a = ReadingRCU { runReadingRCU :: IO a } deriving (Functor, Applicative, Monad)
-
-instance MonadNew s (ReadingRCU s) where
-  newSRef = r where
-    r :: forall a. a -> ReadingRCU s (SRef s a)
-    r = coerce (newTVarIO :: a -> IO (TVar a))
-
-instance MonadReading s (ReadingRCU s) where
-  readSRef = r where
-    r :: forall a. SRef s a -> ReadingRCU s a
-    r = coerce (readTVarIO :: TVar a -> IO a)
-  {-# INLINE readSRef #-}
-
---------------------------------------------------------------------------------
--- * Write-Side Critical Sections
---------------------------------------------------------------------------------
-
--- | This is the basic write-side critical section for an RCU computation
-newtype WritingRCU s a = WritingRCU { runWritingRCU :: TVar Int64 -> STM a }
-  deriving Functor
-
-instance Applicative (WritingRCU s) where
-  pure a = WritingRCU $ \ _ -> pure a
-  WritingRCU mf <*> WritingRCU ma = WritingRCU $ \c -> mf c <*> ma c
-
-instance Monad (WritingRCU s) where
-  return a = WritingRCU $ \ _ -> pure a
-  WritingRCU m >>= f = WritingRCU $ \ c -> do
-    a <- m c
-    runWritingRCU (f a) c
-  fail s = WritingRCU $ \ _ -> fail s
-
-instance Alternative (WritingRCU s) where
-  empty = WritingRCU $ \ _ -> empty
-  WritingRCU ma <|> WritingRCU mb = WritingRCU $ \c -> ma c <|> mb c
-
-instance MonadPlus (WritingRCU s) where
-  mzero = WritingRCU $ \ _ -> mzero
-  WritingRCU ma `mplus` WritingRCU mb = WritingRCU $ \c -> ma c `mplus` mb c
-
-instance MonadNew s (WritingRCU s) where
-  newSRef a = WritingRCU $ \_ -> SRef <$> newTVar a
-
-instance MonadReading s (WritingRCU s) where
-  readSRef (SRef r) = WritingRCU $ \ _ -> readTVar r
-  {-# INLINE readSRef #-}
-
-instance MonadWriting s (WritingRCU s) where
-  writeSRef (SRef r) a = WritingRCU $ \ _ -> writeTVar r a
-  synchronize = WritingRCU $ \ c -> modifyTVar' c (+1)
-
---------------------------------------------------------------------------------
--- * RCU Context
---------------------------------------------------------------------------------
-
--- | This is an RCU computation. It can use 'forking' and 'joining' to form
--- new threads, and then you can use 'reading' and 'writing' to run classic
--- read-side and write-side RCU computations. Contention between multiple
--- write-side computations is managed by STM.
-newtype RCU s a = RCU { unRCU :: TVar Int64 -> IO a }
-  deriving Functor
-
-instance Applicative (RCU s) where
-  pure = return
-  (<*>) = ap
-
-instance Monad (RCU s) where
-  return a = RCU $ \ _ -> return a
-  RCU m >>= f = RCU $ \s -> do
-    a <- m s
-    unRCU (f a) s
-
-instance MonadNew s (RCU s) where
-  newSRef a = RCU $ \_ -> SRef <$> newTVarIO a
-
--- | This is a basic 'RCU' thread. It may be embellished when running in a more
--- exotic context.
-data RCUThread s a = RCUThread
-  { rcuThreadId :: {-# UNPACK #-} !ThreadId
-  , rcuThreadVar :: {-# UNPACK #-} !(MVar a)
-  }
-
-instance MonadRCU s (RCU s) where
-  type Reading (RCU s) = ReadingRCU s
-  type Writing (RCU s) = WritingRCU s
-  type Thread (RCU s) = RCUThread s
-  forking (RCU m) = RCU $ \ c -> do
-    result <- newEmptyMVar
-    tid <- forkIO $ do
-      x <- m c
-      putMVar result x
-    return (RCUThread tid result)
-  joining (RCUThread _ m) = RCU $ \ _ -> readMVar m
-  reading (ReadingRCU m) = RCU $ \ _ -> m
-  writing (WritingRCU m) = RCU $ \ c -> atomically $ do
-    _ <- readTVar c -- deliberately incur a data dependency!
-    m c
-  {-# INLINE forking #-}
-  {-# INLINE joining #-}
-  {-# INLINE reading #-}
-  {-# INLINE writing #-}
-
-instance MonadIO (RCU s) where
-  liftIO m = RCU $ \ _ -> m
-  {-# INLINE liftIO #-}
-
--- | Run an RCU computation.
-runRCU :: (forall s. RCU s a) -> IO a
-runRCU m = do
-  c <- newTVarIO 0
-  unRCU m c
-{-# INLINE runRCU #-}
-
diff --git a/src/Control/Concurrent/RCU/QSBR.hs b/src/Control/Concurrent/RCU/QSBR.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/RCU/QSBR.hs
@@ -0,0 +1,27 @@
+{-# LANGUAGE Trustworthy #-}
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (C) 2015 Edward Kmett and Ted Cooper
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+--                Ted Cooper <anthezium@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- Quiescent-State-Based Reclamation
+-----------------------------------------------------------------------------
+module Control.Concurrent.RCU.QSBR
+  ( SRef
+  , RCU, runRCU
+  , MonadNew(..)
+  , MonadReading(..)
+  , MonadWriting(..)
+  , MonadRCU(..)
+  -- * Implementation Details
+  , ReadingRCU
+  , WritingRCU
+  , RCUThread(rcuThreadId)
+  ) where
+
+import Control.Concurrent.RCU.Class
+import Control.Concurrent.RCU.QSBR.Internal
diff --git a/src/Control/Concurrent/RCU/QSBR/Internal.hs b/src/Control/Concurrent/RCU/QSBR/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/RCU/QSBR/Internal.hs
@@ -0,0 +1,339 @@
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# OPTIONS_HADDOCK not-home #-}
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (C) 2015 Edward Kmett and Ted Cooper
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>, 
+--                Ted Cooper <anthezium@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- QSBR-based RCU
+-----------------------------------------------------------------------------
+module Control.Concurrent.RCU.QSBR.Internal
+  ( SRef(..)
+  , RCUThread(..)
+  , RCU(..)
+  , runRCU
+  , ReadingRCU(..)
+  , WritingRCU(..)
+  , RCUState(..)
+  ) where
+
+import Control.Applicative
+import Control.Concurrent
+import Control.Concurrent.RCU.Class
+import Control.Monad
+import Control.Monad.IO.Class
+import Control.Parallel
+import Data.Atomics 
+import Data.List
+import Data.IORef 
+import Data.Word
+import Prelude hiding (read, Read)
+
+--------------------------------------------------------------------------------
+-- * Shared References
+--------------------------------------------------------------------------------
+
+-- | Shared references
+newtype SRef s a = SRef { unSRef :: IORef a }
+  deriving Eq
+
+newSRefIO :: a -> IO (IORef a)
+newSRefIO = newIORef
+{-# INLINE newSRefIO #-}
+
+readSRefIO :: IORef a -> IO a
+readSRefIO = readIORef
+{-# INLINE readSRefIO #-}
+
+writeSRefIO :: IORef a -> a ->  IO ()
+writeSRefIO r a = do a `pseq` writeBarrier
+                     writeIORef r a
+{-# INLINE writeSRefIO #-}
+
+--------------------------------------------------------------------------------
+-- * Shared state
+--------------------------------------------------------------------------------
+
+-- | Counter for causal ordering.
+type Counter = IORef Word64
+
+offline :: Word64
+offline = 0
+
+online :: Word64
+online  = 1
+
+-- counterInc :: Word64
+-- counterInc = 2 -- online threads will never overflow to 1
+
+newCounter :: IO Counter
+newCounter = newIORef online
+
+readCounter :: Counter -> IO Word64
+readCounter = readIORef
+{-# INLINE readCounter #-}
+
+writeCounter :: Counter -> Word64 -> IO ()
+writeCounter c !i = writeIORef c i
+{-# INLINE writeCounter #-}
+
+incCounter :: Counter -> IO Word64
+incCounter c = do !x <- succ <$> readIORef c
+                  writeCounter c x
+                  return x
+{-# INLINE incCounter #-}
+  
+
+-- | State for an RCU computation.
+data RCUState = RCUState
+  { rcuStateGlobalCounter   :: {-# UNPACK #-} !Counter
+  , rcuStateMyCounter       :: {-# UNPACK #-} !Counter  -- each thread's state gets its own counter
+  , rcuStateThreadCountersV :: {-# UNPACK #-} !(MVar [Counter])
+  , rcuStateWriterLockV     :: {-# UNPACK #-} !(MVar ())
+  }
+
+--------------------------------------------------------------------------------
+-- * Read-Side Critical Sections
+--------------------------------------------------------------------------------
+
+-- | This is the basic read-side critical section for an RCU computation
+newtype ReadingRCU s a = ReadingRCU { runReadingRCU :: RCUState -> IO a } 
+  deriving Functor
+
+instance Applicative (ReadingRCU s) where
+  pure a = ReadingRCU $ \ _ -> pure a
+  ReadingRCU mf <*> ReadingRCU ma = ReadingRCU $ \ s -> mf s <*> ma s
+
+instance Monad (ReadingRCU s) where
+  return a = ReadingRCU $ \ _ -> pure a
+  ReadingRCU m >>= f = ReadingRCU $ \ s -> do
+    a <- m s
+    runReadingRCU (f a) s
+  fail s = ReadingRCU $ \ _ -> fail s
+
+instance Alternative (ReadingRCU s) where
+  empty = ReadingRCU $ \ _ -> empty
+  ReadingRCU ma <|> ReadingRCU mb = ReadingRCU $ \s -> ma s <|> mb s
+
+instance MonadPlus (ReadingRCU s) where
+  mzero = ReadingRCU $ \ _ -> mzero
+  ReadingRCU ma `mplus` ReadingRCU mb = ReadingRCU $ \s -> ma s `mplus` mb s
+
+instance MonadNew (SRef s) (ReadingRCU s) where
+  newSRef a = ReadingRCU $ \_ -> SRef <$> newSRefIO a
+
+instance MonadReading (SRef s) (ReadingRCU s) where
+  readSRef (SRef r) = ReadingRCU $ \ _ -> readSRefIO r
+  {-# INLINE readSRef #-}
+
+--------------------------------------------------------------------------------
+-- * Write-Side Critical Sections
+--------------------------------------------------------------------------------
+
+-- | This is the basic write-side critical section for an RCU computation
+newtype WritingRCU s a = WritingRCU { runWritingRCU :: RCUState -> IO a }
+  deriving Functor
+
+instance Applicative (WritingRCU s) where
+  pure a = WritingRCU $ \ _ -> pure a
+  WritingRCU mf <*> WritingRCU ma = WritingRCU $ \ s -> mf s <*> ma s
+
+instance Monad (WritingRCU s) where
+  return a = WritingRCU $ \ _ -> pure a
+  WritingRCU m >>= f = WritingRCU $ \ s -> do
+    a <- m s
+    runWritingRCU (f a) s
+  fail s = WritingRCU $ \ _ -> fail s
+
+instance Alternative (WritingRCU s) where
+  empty = WritingRCU $ \ _ -> empty
+  WritingRCU ma <|> WritingRCU mb = WritingRCU $ \s -> ma s <|> mb s
+
+instance MonadPlus (WritingRCU s) where
+  mzero = WritingRCU $ \ _ -> mzero
+  WritingRCU ma `mplus` WritingRCU mb = WritingRCU $ \s -> ma s `mplus` mb s
+
+instance MonadNew (SRef s) (WritingRCU s) where
+  newSRef a = WritingRCU $ \_ -> SRef <$> newSRefIO a
+
+instance MonadReading (SRef s) (WritingRCU s) where
+  readSRef (SRef r) = WritingRCU $ \ _ -> readSRefIO r
+  {-# INLINE readSRef #-}
+
+instance MonadWriting (SRef s) (WritingRCU s) where
+  writeSRef (SRef r) a = WritingRCU $ \ _ -> writeSRefIO r a
+  {-# INLINE writeSRef #-}
+  synchronize = WritingRCU synchronizeIO
+
+synchronizeIO :: RCUState -> IO () 
+synchronizeIO RCUState { rcuStateGlobalCounter
+                       , rcuStateMyCounter
+                       , rcuStateThreadCountersV } = do
+  -- Get this thread's counter.
+  mc <- readCounter rcuStateMyCounter
+  storeLoadBarrier
+  -- If this thread is not offline already, take it offline.
+  when (mc /= offline) $ writeCounter rcuStateMyCounter offline
+
+  -- Loop through thread counters, waiting for online threads to catch up
+  -- and skipping offline threads.  
+  -- TODO: urcu acquires rcu_gp_lock here, and holds it until the writer has 
+  -- updated the global counter AND finished waiting for readers. I think we may be able
+  -- to avoid holding the lock while waiting for readers as long as we
+  -- allow thread counters to exceed gc' (this is the case currently).     
+  -- Maybe urcu holds the lock to prevent multiple readers from busy-waiting
+  -- on the same shared array?  All they're doing is loading, so I'm not sure
+  -- why that would be a bad thing...  This issue, (and having a lock here at all)
+  -- is moot until we remove the big lock around write-side critical sections.
+  -- This is worth pinging Mathieu about.
+  -- So, TODO: Remove this lock, add a storeLoadBarrier after rcuStateMyCounter update.
+  gc' <- withMVar rcuStateThreadCountersV $ \ threadCounters -> do
+    -- Increment the global counter.
+    gc' <- incCounter rcuStateGlobalCounter
+    writeBarrier
+    -- Wait for each online reader to copy the new global counter.
+    let waitForThread i threadCounter = do
+          tc <- readCounter threadCounter
+          when (tc /= offline && tc < gc') $ do 
+            -- urcu puts the thread on a futex wait queue once per Int32 overflow
+            -- in this loop.  
+            threadDelay 1    -- TODO: Busy-wait for a while before sleeping.
+
+            storeLoadBarrier -- This works on all systems, even those with 
+                             -- incoherent caches, but slows down writers 
+                             -- unnecessarily on cache-coherent systems.  
+                             -- TODO: On cache-coherent systems, 
+                             -- figure out how to make GHC emit e.g. "rep; nop"
+                             -- to tell the CPU we're in a busy-wait loop.  
+                             -- urcu uses "caa_cpu_relax()" decorated with a compiler
+                             -- reordering barrier in this case.
+            waitForThread (i + 1) threadCounter
+    forM_ threadCounters (waitForThread (0 :: Int))
+    return gc'
+  when (mc /= offline) $ writeCounter rcuStateMyCounter gc'
+  storeLoadBarrier
+
+--------------------------------------------------------------------------------
+-- * RCU Context
+--------------------------------------------------------------------------------
+
+-- | This is an RCU computation. It can use 'forking' and 'joining' to form
+-- new threads, and then you can use 'reading' and 'writing' to run classic
+-- read-side and write-side RCU computations. Writers are
+-- serialized using an MVar, readers are able to proceed while writers are
+-- updating.
+newtype RCU s a = RCU { unRCU :: RCUState -> IO a }
+  deriving Functor
+
+instance Applicative (RCU s) where
+  pure = return
+  (<*>) = ap
+
+instance Monad (RCU s) where
+  return a = RCU $ \ _ -> return a
+  RCU m >>= f = RCU $ \s -> do
+    a <- m s
+    unRCU (f a) s
+
+instance MonadNew (SRef s) (RCU s) where
+  newSRef a = RCU $ \_ -> SRef <$> newSRefIO a
+
+-- | This is a basic 'RCU' thread. It may be embellished when running in a more
+-- exotic context.
+data RCUThread s a = RCUThread
+  { rcuThreadId  :: {-# UNPACK #-} !ThreadId
+  , rcuThreadVar :: {-# UNPACK #-} !(MVar a)
+  }
+
+instance MonadRCU (SRef s) (RCU s) where
+  type Reading (RCU s) = ReadingRCU s
+  type Writing (RCU s) = WritingRCU s
+  type Thread (RCU s) = RCUThread s
+  forking (RCU m) = RCU $ \ s@RCUState { rcuStateThreadCountersV } -> do
+    -- Create an MVar the new thread can use to return a result.
+    result <- newEmptyMVar
+
+    -- Create a counter for the new thread, and add it to the list.
+    threadCounter <- newCounter
+    -- Wouldn't <$$> be nice here...
+    modifyMVar_ rcuStateThreadCountersV $ return . (threadCounter :)
+
+    -- Spawn the new thread, whose return value goes in @result@.
+    tid <- forkIO $ do
+      x <- m $ s { rcuStateMyCounter = threadCounter }
+      putMVar result x
+
+      -- After the new thread has completed, mark its counter as offline
+      -- and remove this counter from the list writers poll.
+      writeBarrier
+      writeCounter threadCounter offline
+      modifyMVar_ rcuStateThreadCountersV $ return . delete threadCounter
+    return (RCUThread tid result)
+  {-# INLINE forking #-}
+
+  joining (RCUThread _ m) = RCU $ \ _ -> readMVar m
+  {-# INLINE joining #-}
+
+  reading (ReadingRCU m) = RCU $ \ s@RCUState { rcuStateMyCounter
+                                              , rcuStateGlobalCounter } -> do
+    mc <- readCounter rcuStateMyCounter
+    -- If this thread was offline, take a snapshot of the global counter so
+    -- writers will wait.
+    when (mc == offline) $ do
+      writeCounter rcuStateMyCounter =<< readCounter rcuStateGlobalCounter   
+      -- Make sure that the counter goes online before reads begin.
+      storeLoadBarrier
+    
+    -- Run a read-side critical section.
+    x <- m s
+    
+    -- Announce a quiescent state after the read-side critical section.
+    -- TODO: Make this tunable/optional.
+    storeLoadBarrier
+    writeCounter rcuStateMyCounter =<< readCounter rcuStateGlobalCounter
+    storeLoadBarrier
+    
+    -- Return the result of the read-side critical section.
+    return x
+  {-# INLINE reading #-}
+
+  writing (WritingRCU m) = RCU $ \ s@RCUState { rcuStateWriterLockV } -> do
+    -- Acquire the writer-serializing lock.
+    takeMVar rcuStateWriterLockV
+
+    -- Run a write-side critical section.
+    x <- m s
+
+    -- Guarantee that writes in this critical section happen before writes in
+    -- subsequent critical sections.
+    synchronizeIO s
+
+    -- Release the writer-serializing lock.
+    putMVar rcuStateWriterLockV ()
+    return x
+  {-# INLINE writing #-}
+
+instance MonadIO (RCU s) where
+  liftIO m = RCU $ \ _ -> m
+  {-# INLINE liftIO #-}
+
+-- | Run an RCU computation.
+runRCU :: (forall s. RCU s a) -> IO a
+runRCU m = do
+  unRCU m =<< RCUState <$> newCounter <*> newCounter <*> newMVar [] <*> newMVar ()
+{-# INLINE runRCU #-}
diff --git a/unstable/Control/Concurrent/RCU/STM.hs b/unstable/Control/Concurrent/RCU/STM.hs
new file mode 100644
--- /dev/null
+++ b/unstable/Control/Concurrent/RCU/STM.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE Trustworthy #-}
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (C) 2015 Edward Kmett and Ted Cooper
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+--                Ted Cooper <anthezium@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-----------------------------------------------------------------------------
+module Control.Concurrent.RCU.STM
+  ( SRef
+  , RCU, runRCU
+  , MonadNew(..)
+  , MonadReading(..)
+  , MonadWriting(..)
+  , MonadRCU(..)
+  -- * Implementation Details
+  , ReadingRCU
+  , WritingRCU
+  , RCUThread(rcuThreadId)
+  ) where
+
+import Control.Concurrent.RCU.Class
+import Control.Concurrent.RCU.STM.Internal
diff --git a/unstable/Control/Concurrent/RCU/STM/Internal.hs b/unstable/Control/Concurrent/RCU/STM/Internal.hs
new file mode 100644
--- /dev/null
+++ b/unstable/Control/Concurrent/RCU/STM/Internal.hs
@@ -0,0 +1,166 @@
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE DefaultSignatures #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# OPTIONS_HADDOCK not-home #-}
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (C) 2015 Edward Kmett and Ted Cooper
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
+--                Ted Cooper <anthezium@gmail.com>
+-- Stability   :  experimental
+-- Portability :  non-portable
+--
+-- STM-based RCU with concurrent writers
+-----------------------------------------------------------------------------
+module Control.Concurrent.RCU.STM.Internal
+  ( SRef(..)
+  , RCUThread(..)
+  , RCU(..)
+  , runRCU
+  , ReadingRCU(..)
+  , WritingRCU(..)
+  ) where
+
+import Control.Applicative
+import Control.Concurrent
+import Control.Concurrent.STM
+import Control.Concurrent.RCU.Class
+import Control.Monad
+import Control.Monad.IO.Class
+import Data.Coerce
+import Data.Int
+import Prelude hiding (read, Read)
+
+--------------------------------------------------------------------------------
+-- * Shared References
+--------------------------------------------------------------------------------
+
+-- | Shared references
+newtype SRef s a = SRef { unSRef :: TVar a }
+  deriving Eq
+
+--------------------------------------------------------------------------------
+-- * Read-Side Critical Sections
+--------------------------------------------------------------------------------
+
+-- | This is the basic read-side critical section for an RCU computation
+newtype ReadingRCU s a = ReadingRCU { runReadingRCU :: IO a } deriving (Functor, Applicative, Monad)
+
+instance MonadNew (SRef s) (ReadingRCU s) where
+  newSRef = r where
+    r :: forall a. a -> ReadingRCU s (SRef s a)
+    r = coerce (newTVarIO :: a -> IO (TVar a))
+
+instance MonadReading (SRef s) (ReadingRCU s) where
+  readSRef = r where
+    r :: forall a. SRef s a -> ReadingRCU s a
+    r = coerce (readTVarIO :: TVar a -> IO a)
+  {-# INLINE readSRef #-}
+
+--------------------------------------------------------------------------------
+-- * Write-Side Critical Sections
+--------------------------------------------------------------------------------
+
+-- | This is the basic write-side critical section for an RCU computation
+newtype WritingRCU s a = WritingRCU { runWritingRCU :: TVar Int64 -> STM a }
+  deriving Functor
+
+instance Applicative (WritingRCU s) where
+  pure a = WritingRCU $ \ _ -> pure a
+  WritingRCU mf <*> WritingRCU ma = WritingRCU $ \c -> mf c <*> ma c
+
+instance Monad (WritingRCU s) where
+  return a = WritingRCU $ \ _ -> pure a
+  WritingRCU m >>= f = WritingRCU $ \ c -> do
+    a <- m c
+    runWritingRCU (f a) c
+  fail s = WritingRCU $ \ _ -> fail s
+
+instance Alternative (WritingRCU s) where
+  empty = WritingRCU $ \ _ -> empty
+  WritingRCU ma <|> WritingRCU mb = WritingRCU $ \c -> ma c <|> mb c
+
+instance MonadPlus (WritingRCU s) where
+  mzero = WritingRCU $ \ _ -> mzero
+  WritingRCU ma `mplus` WritingRCU mb = WritingRCU $ \c -> ma c `mplus` mb c
+
+instance MonadNew (SRef s) (WritingRCU s) where
+  newSRef a = WritingRCU $ \_ -> SRef <$> newTVar a
+
+instance MonadReading (SRef s) (WritingRCU s) where
+  readSRef (SRef r) = WritingRCU $ \ _ -> readTVar r
+  {-# INLINE readSRef #-}
+
+instance MonadWriting (SRef s) (WritingRCU s) where
+  writeSRef (SRef r) a = WritingRCU $ \ _ -> writeTVar r a
+  synchronize = WritingRCU $ \ c -> modifyTVar' c (+1)
+
+--------------------------------------------------------------------------------
+-- * RCU Context
+--------------------------------------------------------------------------------
+
+-- | This is an RCU computation. It can use 'forking' and 'joining' to form
+-- new threads, and then you can use 'reading' and 'writing' to run classic
+-- read-side and write-side RCU computations. Contention between multiple
+-- write-side computations is managed by STM.
+newtype RCU s a = RCU { unRCU :: TVar Int64 -> IO a }
+  deriving Functor
+
+instance Applicative (RCU s) where
+  pure = return
+  (<*>) = ap
+
+instance Monad (RCU s) where
+  return a = RCU $ \ _ -> return a
+  RCU m >>= f = RCU $ \s -> do
+    a <- m s
+    unRCU (f a) s
+
+instance MonadNew (SRef s) (RCU s) where
+  newSRef a = RCU $ \_ -> SRef <$> newTVarIO a
+
+-- | This is a basic 'RCU' thread. It may be embellished when running in a more
+-- exotic context.
+data RCUThread s a = RCUThread
+  { rcuThreadId :: {-# UNPACK #-} !ThreadId
+  , rcuThreadVar :: {-# UNPACK #-} !(MVar a)
+  }
+
+instance MonadRCU (SRef s) (RCU s) where
+  type Reading (RCU s) = ReadingRCU s
+  type Writing (RCU s) = WritingRCU s
+  type Thread (RCU s) = RCUThread s
+  forking (RCU m) = RCU $ \ c -> do
+    result <- newEmptyMVar
+    tid <- forkIO $ do
+      x <- m c
+      putMVar result x
+    return (RCUThread tid result)
+  joining (RCUThread _ m) = RCU $ \ _ -> readMVar m
+  reading (ReadingRCU m) = RCU $ \ _ -> m
+  writing (WritingRCU m) = RCU $ \ c -> atomically $ do
+    _ <- readTVar c -- deliberately incur a data dependency!
+    m c
+  {-# INLINE forking #-}
+  {-# INLINE joining #-}
+  {-# INLINE reading #-}
+  {-# INLINE writing #-}
+
+instance MonadIO (RCU s) where
+  liftIO m = RCU $ \ _ -> m
+  {-# INLINE liftIO #-}
+
+-- | Run an RCU computation.
+runRCU :: (forall s. RCU s a) -> IO a
+runRCU m = do
+  c <- newTVarIO 0
+  unRCU m c
+{-# INLINE runRCU #-}
