diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,36 @@
 # Revision history for zeolite-lang
 
+## 0.16.1.0  -- 2021-04-02
+
+### Language
+
+* **[fix]** Fixes a regression where a race condition in function dispatching
+  would cause an error saying that a category does not implement the function
+  that was being called.
+
+* **[behavior]** Optimizes calls to `@type` functions when made from `@value`
+  functions of the same type.
+
+* **[behavior]** Optimizes `@value` initialization (e.g., `Type{ }`) when done
+  from `@type` functions of the same type.
+
+### Libraries
+
+* **[new]** Moves `Mutex`, `SimpleMutex`, and `MutexLock` from `lib/thread`
+  to `lib/util`. This is because they provide basic concurrency protection to
+  objects that should not need to depend on `-lpthread`.
+
+  Note that this change *is not* breaking because `lib/util` was already a
+  public dependency of `lib/thread`. In other words, if a module already used
+  `lib/thread` then it got `lib/util` for free. This means that modules only
+  needing mutex functionality from `lib/thread` can instead use `lib/util`.
+
+* **[new]** Adds `getForward` and `getReverse` to `SearchTree`, to allow the
+  caller to iterate after looking up an entry.
+
+* **[new]** Adds `checkEmpty`, `checkPresent`, and `checkOptional` to `Testing`
+  in `lib/testing`.
+
 ## 0.16.0.0  -- 2021-04-01
 
 ### Language
diff --git a/base/Category_Bool.cpp b/base/Category_Bool.cpp
--- a/base/Category_Bool.cpp
+++ b/base/Category_Bool.cpp
@@ -96,7 +96,8 @@
       DispatchSingle<CallType>(&GetCategory_Formatted(), &Type_Bool::Params_Formatted),
       DispatchSingle<CallType>(),
     };
-    const DispatchSingle<CallType>* const call = DispatchSelect(&category, all_calls);
+    std::atomic_bool table_lock{0};
+    const DispatchSingle<CallType>* const call = DispatchSelect(table_lock, &category, all_calls);
     if (call) {
       (this->*call->value)(args);
       return true;
@@ -122,7 +123,8 @@
       DispatchTable<CallType>(Functions_Equals,  Table_Equals),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
@@ -162,7 +164,8 @@
       DispatchTable<CallType>(Functions_Formatted, Table_Formatted),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
diff --git a/base/Category_Char.cpp b/base/Category_Char.cpp
--- a/base/Category_Char.cpp
+++ b/base/Category_Char.cpp
@@ -102,7 +102,8 @@
       DispatchSingle<CallType>(&GetCategory_Formatted(), &Type_Char::Params_Formatted),
       DispatchSingle<CallType>(),
     };
-    const DispatchSingle<CallType>* const call = DispatchSelect(&category, all_calls);
+    std::atomic_bool table_lock{0};
+    const DispatchSingle<CallType>* const call = DispatchSelect(table_lock, &category, all_calls);
     if (call) {
       (this->*call->value)(args);
       return true;
@@ -132,7 +133,8 @@
       DispatchTable<CallType>(Functions_LessThan, Table_LessThan),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
@@ -177,7 +179,8 @@
       DispatchTable<CallType>(Functions_Formatted, Table_Formatted),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
diff --git a/base/Category_Float.cpp b/base/Category_Float.cpp
--- a/base/Category_Float.cpp
+++ b/base/Category_Float.cpp
@@ -97,7 +97,8 @@
       DispatchSingle<CallType>(&GetCategory_Formatted(), &Type_Float::Params_Formatted),
       DispatchSingle<CallType>(),
     };
-    const DispatchSingle<CallType>* const call = DispatchSelect(&category, all_calls);
+    std::atomic_bool table_lock{0};
+    const DispatchSingle<CallType>* const call = DispatchSelect(table_lock, &category, all_calls);
     if (call) {
       (this->*call->value)(args);
       return true;
@@ -127,7 +128,8 @@
       DispatchTable<CallType>(Functions_LessThan, Table_LessThan),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
@@ -168,7 +170,8 @@
       DispatchTable<CallType>(Functions_Formatted, Table_Formatted),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
diff --git a/base/Category_Int.cpp b/base/Category_Int.cpp
--- a/base/Category_Int.cpp
+++ b/base/Category_Int.cpp
@@ -102,7 +102,8 @@
       DispatchSingle<CallType>(&GetCategory_Int(),       &Type_Int::Params_Int),
       DispatchSingle<CallType>(),
     };
-    const DispatchSingle<CallType>* const call = DispatchSelect(&category, all_calls);
+    std::atomic_bool table_lock{0};
+    const DispatchSingle<CallType>* const call = DispatchSelect(table_lock, &category, all_calls);
     if (call) {
       (this->*call->value)(args);
       return true;
@@ -132,7 +133,8 @@
       DispatchTable<CallType>(Functions_LessThan, Table_LessThan),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
@@ -177,7 +179,8 @@
       DispatchTable<CallType>(Functions_Formatted, Table_Formatted),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
diff --git a/base/Category_String.cpp b/base/Category_String.cpp
--- a/base/Category_String.cpp
+++ b/base/Category_String.cpp
@@ -109,7 +109,8 @@
       DispatchSingle<CallType>(&GetCategory_DefaultOrder(), &Type_String::Params_DefaultOrder),
       DispatchSingle<CallType>(),
     };
-    const DispatchSingle<CallType>* const call = DispatchSelect(&category, all_calls);
+    std::atomic_bool table_lock{0};
+    const DispatchSingle<CallType>* const call = DispatchSelect(table_lock, &category, all_calls);
     if (call) {
       (this->*call->value)(args);
       return true;
@@ -143,7 +144,8 @@
       DispatchTable<CallType>(Functions_String,   Table_String),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
@@ -197,7 +199,8 @@
       DispatchTable<CallType>(Functions_SubSequence,  Table_SubSequence),
       DispatchTable<CallType>(),
     };
-    const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);
+    std::atomic_bool table_lock{0};
+    const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);
     if (table) {
       if (label.function_num < 0 || label.function_num >= table->size) {
         FAIL() << "Bad function call " << label;
diff --git a/base/category-source.hpp b/base/category-source.hpp
--- a/base/category-source.hpp
+++ b/base/category-source.hpp
@@ -20,6 +20,7 @@
 #define CATEGORY_SOURCE_HPP_
 
 #include <algorithm>
+#include <atomic>
 #include <iostream>  // For occasional debugging output in generated code.
 #include <map>
 #include <mutex>
@@ -269,11 +270,13 @@
 };
 
 template<class T, int S>
-const T* DispatchSelect(const void* key, T(&table)[S]) {
+const T* DispatchSelect(std::atomic_bool& lock, const void* key, T(&table)[S]) {
   if (S < 2) return nullptr;
+  while (lock.exchange(true));
   if (table[0].key != nullptr) {
     std::sort(table, table+S);
   }
+  lock.exchange(false);
   int i = 1, j = S;
   while (j-i > 1) {
     const int k = (i+j)/2;
diff --git a/lib/container/search-tree.0rp b/lib/container/search-tree.0rp
--- a/lib/container/search-tree.0rp
+++ b/lib/container/search-tree.0rp
@@ -30,22 +30,36 @@
   // Create an empty tree.
   @type new () -> (#self)
 
-  // Traverse the tree in the reverse order of defaultOrder().
+  // Traverse in the default order.
   //
   // Notes:
+  // - This is from DefaultOrder, but is made explicit for documentation.
   // - Traversal of the entire tree is amortized O(n); however, the cost of any
   //   particular iteration could be up to O(log n).
   // - The overall memory cost is O(log n).
-  @value reverseOrder () -> (optional Order<KeyValue<#k,#v>>)
+  @value defaultOrder () -> (optional Order<KeyValue<#k,#v>>)
 
-  // Traverse in the default order.
+  // Traverse the tree in the reverse order of defaultOrder().
   //
   // Notes:
-  // - This is from DefaultOrder, but is made explicit for documentation.
   // - Traversal of the entire tree is amortized O(n); however, the cost of any
   //   particular iteration could be up to O(log n).
   // - The overall memory cost is O(log n).
-  @value defaultOrder () -> (optional Order<KeyValue<#k,#v>>)
+  @value reverseOrder () -> (optional Order<KeyValue<#k,#v>>)
+
+  // Start forward traversal (same as defaultOrder()) from the specified key.
+  //
+  // Notes:
+  // - If the key does not exist in the SearchTree, the position right after
+  //   where it would be (in the forward direction) is returned.
+  @value getForward (#k) -> (optional Order<KeyValue<#k,#v>>)
+
+  // Start reverse traversal (same as reverseOrder()) from the specified key.
+  //
+  // Notes:
+  // - If the key does not exist in the SearchTree, the position right after
+  //   where it would be (in the reverse direction) is returned.
+  @value getReverse (#k) -> (optional Order<KeyValue<#k,#v>>)
 }
 
 // A validated binary search tree for key-value storage.
diff --git a/lib/container/search-tree.0rt b/lib/container/search-tree.0rt
--- a/lib/container/search-tree.0rt
+++ b/lib/container/search-tree.0rt
@@ -23,20 +23,16 @@
 unittest integrationTest {
   [KVWriter<Int,Int>&KVReader<Int,Int>] tree <- ValidatedTree<Int,Int>.new()
   Int count <- 30
+  $ReadOnly[count]$
 
   // Insert values.
-  scoped {
-    Int i <- 0
-  } in while (i < count) {
+  traverse (Counter.zeroIndexed(count) -> Int i) {
     Int new <- ((i + 13) * 3547) % count
     \ tree.set(new,i)
-  } update {
-    i <- i+1
   }
 
-  scoped {
-    Int i <- 0
-  } in while (i < count) {
+  // Check and remove values.
+  traverse (Counter.zeroIndexed(count) -> Int i) {
     Int new <- ((i + 13) * 3547) % count
     scoped {
       optional Int value <- tree.get(new)
@@ -58,8 +54,6 @@
           .writeTo(SimpleOutput.error())
     }
     \ tree.remove(new)
-  } update {
-    i <- i+1
   }
 }
 
@@ -105,4 +99,88 @@
   }
 
   \ Testing.checkEquals<?>(index,0)
+}
+
+unittest getForward {
+  SearchTree<Int,Int> tree <- SearchTree<Int,Int>.new()
+  Int hash <- 13
+  Int max  <- 20
+  $ReadOnly[hash,max]$
+
+  // Populate the tree in a pseudo-random order.
+  traverse (Counter.zeroIndexed(max) -> Int i) {
+    \ ((i*hash)%max) `tree.set` i
+  }
+
+  // Validate the traversal order from every starting point.
+  traverse (Counter.zeroIndexed(max) -> Int i) {
+    Int index <- i
+    traverse (tree.getForward(index) -> KeyValue<Int,Int> entry) {
+      \ Testing.checkEquals<?>(entry.getKey(),index)
+      \ Testing.checkEquals<?>((entry.getValue()*hash)%max,entry.getKey())
+      index <- index+1
+    }
+    \ Testing.checkEquals<?>(index,20)
+  }
+}
+
+unittest getForwardNotFound {
+  SearchTree<Int,Int> tree <- SearchTree<Int,Int>.new()
+  \ tree.set(1,1).set(3,3).set(5,5)
+
+  scoped {
+    optional Order<KeyValue<Int,Int>> start <- tree.getForward(4)
+  } in if (!present(start)) {
+    fail("Failed")
+  } else {
+    \ Testing.checkEquals<?>(require(start).get().getKey(),5)
+  }
+
+  scoped {
+    optional Order<KeyValue<Int,Int>> start <- tree.getForward(6)
+  } in if (present(start)) {
+    fail("Failed")
+  }
+}
+
+unittest getReverse {
+  SearchTree<Int,Int> tree <- SearchTree<Int,Int>.new()
+  Int hash <- 13
+  Int max  <- 20
+  $ReadOnly[hash,max]$
+
+  // Populate the tree in a pseudo-random order.
+  traverse (Counter.zeroIndexed(max) -> Int i) {
+    \ ((i*hash)%max) `tree.set` i
+  }
+
+  // Validate the traversal order from every starting point.
+  traverse (Counter.zeroIndexed(max) -> Int i) {
+    Int index <- i
+    traverse (tree.getReverse(index) -> KeyValue<Int,Int> entry) {
+      \ Testing.checkEquals<?>(entry.getKey(),index)
+      \ Testing.checkEquals<?>((entry.getValue()*hash)%max,entry.getKey())
+      index <- index-1
+    }
+    \ Testing.checkEquals<?>(index,-1)
+  }
+}
+
+unittest getReverseNotFound {
+  SearchTree<Int,Int> tree <- SearchTree<Int,Int>.new()
+  \ tree.set(1,1).set(3,3).set(5,5)
+
+  scoped {
+    optional Order<KeyValue<Int,Int>> start <- tree.getReverse(2)
+  } in if (!present(start)) {
+    fail("Failed")
+  } else {
+    \ Testing.checkEquals<?>(require(start).get().getKey(),1)
+  }
+
+  scoped {
+    optional Order<KeyValue<Int,Int>> start <- tree.getReverse(0)
+  } in if (present(start)) {
+    fail("Failed")
+  }
 }
diff --git a/lib/container/search-tree.0rx b/lib/container/search-tree.0rx
--- a/lib/container/search-tree.0rx
+++ b/lib/container/search-tree.0rx
@@ -44,6 +44,14 @@
   reverseOrder () {
     return ReverseTreeOrder:create<?,?>(root)
   }
+
+  getForward (k) {
+    return ForwardTreeOrder:seek<?,?>(k,root)
+  }
+
+  getReverse (k) {
+    return ReverseTreeOrder:seek<?,?>(k,root)
+  }
 }
 
 define ValidatedTree {
@@ -85,6 +93,8 @@
 }
 
 define Node {
+  $ReadOnly[key]$
+
   @value Int height
   @value #k key
   @value #v value
@@ -334,13 +344,15 @@
   setHigher (h) { higher <- h }
 }
 
-concrete TreeKeyValue<#k,#v> {
+concrete TreeKeyValue<|#k,#v> {
   refines KeyValue<#k,#v>
 
   @category create<#k,#v> (#k,#v) -> (TreeKeyValue<#k,#v>)
 }
 
 define TreeKeyValue {
+  $ReadOnly[key,value]$
+
   @value #k key
   @value #v value
 
@@ -357,13 +369,14 @@
   }
 }
 
-concrete ForwardTreeOrder<#k,#v> {
+concrete ForwardTreeOrder<|#k,#v> {
   refines Order<KeyValue<#k,#v>>
-  #k defines LessThan<#k>
 
-  @category create<#k,#v>
+  @category create<#k,#v> (optional Node<#k,#v>) -> (optional ForwardTreeOrder<#k,#v>)
+
+  @category seek<#k,#v>
     #k defines LessThan<#k>
-  (optional Node<#k,#v>) -> (optional ForwardTreeOrder<#k,#v>)
+  (#k,optional Node<#k,#v>) -> (optional ForwardTreeOrder<#k,#v>)
 }
 
 define ForwardTreeOrder {
@@ -372,27 +385,42 @@
   @value Node<#k,#v> node
   @value optional ForwardTreeOrder<#k,#v> prev
 
-  create (node) {
+  create (node) (current) {
     optional Node<#k,#v> node2 <- node
-    optional ForwardTreeOrder<#k,#v> current <- empty
+    current <- empty
     while (present(node2)) {
       current <- ForwardTreeOrder<#k,#v>{ require(node2), current }
       node2 <- require(node2).getLower()
     }
-    return current
   }
 
-  next () {
+  seek (key,node) (current) {
+    optional Node<#k,#v> node2 <- node
+    current <- empty
+    while (present(node2)) {
+      if (require(node2).getKey() `#k.lessThan` key) {
+        // Skip node2 in the traversal, since it's before key.
+        node2 <- require(node2).getHigher()
+      } elif (key `#k.lessThan` require(node2).getKey()) {
+        current <- ForwardTreeOrder<#k,#v>{ require(node2), current }
+        node2 <- require(node2).getLower()
+      } else {
+        current <- ForwardTreeOrder<#k,#v>{ require(node2), current }
+        break
+      }
+    }
+  }
+
+  next () (current) {
     // Algorithm:
     // 1. Pop self from the stack.
     // 2. Traverse lower to the bottom starting from the higher child of self.
     optional Node<#k,#v> node2 <- node.getHigher()
-    optional ForwardTreeOrder<#k,#v> current <- prev
+    current <- prev
     while (present(node2)) {
       current <- ForwardTreeOrder<#k,#v>{ require(node2), current }
       node2 <- require(node2).getLower()
     }
-    return current
   }
 
   get () {
@@ -400,13 +428,14 @@
   }
 }
 
-concrete ReverseTreeOrder<#k,#v> {
+concrete ReverseTreeOrder<|#k,#v> {
   refines Order<KeyValue<#k,#v>>
-  #k defines LessThan<#k>
 
-  @category create<#k,#v>
+  @category create<#k,#v> (optional Node<#k,#v>) -> (optional ReverseTreeOrder<#k,#v>)
+
+  @category seek<#k,#v>
     #k defines LessThan<#k>
-  (optional Node<#k,#v>) -> (optional ReverseTreeOrder<#k,#v>)
+  (#k,optional Node<#k,#v>) -> (optional ReverseTreeOrder<#k,#v>)
 }
 
 define ReverseTreeOrder {
@@ -415,27 +444,42 @@
   @value Node<#k,#v> node
   @value optional ReverseTreeOrder<#k,#v> prev
 
-  create (node) {
+  create (node) (current) {
     optional Node<#k,#v> node2 <- node
-    optional ReverseTreeOrder<#k,#v> current <- empty
+    current <- empty
     while (present(node2)) {
       current <- ReverseTreeOrder<#k,#v>{ require(node2), current }
       node2 <- require(node2).getHigher()
     }
-    return current
   }
 
-  next () {
+  seek (key,node) (current) {
+    optional Node<#k,#v> node2 <- node
+    current <- empty
+    while (present(node2)) {
+      if (require(node2).getKey() `#k.lessThan` key) {
+        current <- ReverseTreeOrder<#k,#v>{ require(node2), current }
+        node2 <- require(node2).getHigher()
+      } elif (key `#k.lessThan` require(node2).getKey()) {
+        // Skip node2 in the traversal, since it's after key.
+        node2 <- require(node2).getLower()
+      } else {
+        current <- ReverseTreeOrder<#k,#v>{ require(node2), current }
+        break
+      }
+    }
+  }
+
+  next () (current) {
     // Algorithm:
     // 1. Pop self from the stack.
     // 2. Traverse higher to the bottom starting from the lower child of self.
     optional Node<#k,#v> node2 <- node.getLower()
-    optional ReverseTreeOrder<#k,#v> current <- prev
+    current <- prev
     while (present(node2)) {
       current <- ReverseTreeOrder<#k,#v>{ require(node2), current }
       node2 <- require(node2).getHigher()
     }
-    return current
   }
 
   get () {
diff --git a/lib/container/type-map.0rt b/lib/container/type-map.0rt
--- a/lib/container/type-map.0rt
+++ b/lib/container/type-map.0rt
@@ -27,21 +27,21 @@
   TypeKey<String> keyString <- TypeKey<String>.new()
   TypeKey<Value>  keyValue  <- TypeKey<Value>.new()
 
-  \ Helper.check<?>(tree,keyInt,empty)
-  \ Helper.check<?>(tree,keyString,empty)
-  \ Helper.check<?>(tree,keyValue,empty)
+  \ Testing.checkOptional<?>(tree.get<?>(keyInt),   empty)
+  \ Testing.checkOptional<?>(tree.get<?>(keyString),empty)
+  \ Testing.checkOptional<?>(tree.get<?>(keyValue), empty)
 
   \ tree.set<?>(keyInt,1)
   \ tree.set<?>(keyString,"a")
   \ tree.set<?>(keyValue,Value.new())
 
-  \ Helper.check<?>(tree,keyInt,1)
-  \ Helper.check<?>(tree,keyString,"a")
-  \ Helper.check<?>(tree,keyValue,Value.new())
+  \ Testing.checkOptional<?>(tree.get<?>(keyInt),   1)
+  \ Testing.checkOptional<?>(tree.get<?>(keyString),"a")
+  \ Testing.checkOptional<?>(tree.get<?>(keyValue), Value.new())
 
   \ tree.remove(keyString)
 
-  \ Helper.check<?>(tree,keyString,empty)
+  \ Testing.checkOptional<?>(tree.get<?>(keyString),empty)
 }
 
 unittest wrongReturnType {
@@ -51,10 +51,10 @@
 
   // Added as Formatted, which means it cannot be retrieved as String later.
   \ tree.set<Formatted>(keyString,"a")
-  \ Helper.check<String>(tree,keyString,empty)
+  \ Testing.checkOptional<?>(tree.get<String>(keyString),empty)
 
   \ tree.set<String>(keyString,"a")
-  \ Helper.check<String>(tree,keyString,"a")
+  \ Testing.checkOptional<?>(tree.get<String>(keyString),"a")
 }
 
 concrete Value {
@@ -75,26 +75,5 @@
 
   equals (_,_) {
     return true
-  }
-}
-
-concrete Helper {
-  @type check<#x>
-    #x requires Formatted
-    #x defines Equals<#x>
-  (TypeMap,TypeKey<#x>,optional #x) -> ()
-}
-
-define Helper {
-  check (tree,key,expected) {
-    scoped {
-      optional #x value <- tree.get<#x>(key)
-    } in if (present(value) && present(expected)) {
-      \ Testing.checkEquals<?>(require(value),require(expected))
-    } elif (!present(value) && present(expected)) {
-      fail(key.formatted() + " was expected but not found")
-    } elif (present(value) && !present(expected)) {
-      fail(key.formatted() + " was found but not expected")
-    }
   }
 }
diff --git a/lib/container/type-map.0rx b/lib/container/type-map.0rx
--- a/lib/container/type-map.0rx
+++ b/lib/container/type-map.0rx
@@ -45,12 +45,18 @@
 }
 
 define TypeKey {
-  // TODO: Protect the counter with a mutex.
-  @category Int counter <- 0
+  $ReadOnly[counterMutex,index]$
+
+  @category Mutex counterMutex <- SimpleMutex.new()
+  @category Int   counter      <- 0
   @value Int index
 
   new () {
-    return TypeKey<#x>{ (counter <- counter+1) }
+    scoped {
+      MutexLock lock <- MutexLock.lock(counterMutex)
+    } cleanup {
+      \ lock.freeResource()
+    } in return TypeKey<#x>{ (counter <- counter+1) }
   }
 
   formatted () {
diff --git a/lib/file/src/Extension_RawFileReader.cpp b/lib/file/src/Extension_RawFileReader.cpp
--- a/lib/file/src/Extension_RawFileReader.cpp
+++ b/lib/file/src/Extension_RawFileReader.cpp
@@ -35,7 +35,7 @@
 
   ReturnTuple Call_open(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {
     TRACE_FUNCTION("RawFileReader.open")
-    return ReturnTuple(CreateValue_RawFileReader(CreateType_RawFileReader(Params<0>::Type()), args));
+    return ReturnTuple(CreateValue_RawFileReader(shared_from_this(), args));
   }
 };
 
diff --git a/lib/file/src/Extension_RawFileWriter.cpp b/lib/file/src/Extension_RawFileWriter.cpp
--- a/lib/file/src/Extension_RawFileWriter.cpp
+++ b/lib/file/src/Extension_RawFileWriter.cpp
@@ -35,7 +35,7 @@
 
   ReturnTuple Call_open(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {
     TRACE_FUNCTION("RawFileWriter.open")
-    return ReturnTuple(CreateValue_RawFileWriter(CreateType_RawFileWriter(Params<0>::Type()), args));
+    return ReturnTuple(CreateValue_RawFileWriter(shared_from_this(), args));
   }
 };
 
diff --git a/lib/file/tests.0rt b/lib/file/tests.0rt
--- a/lib/file/tests.0rt
+++ b/lib/file/tests.0rt
@@ -28,16 +28,12 @@
   } cleanup {
     \ writer.freeResource()
   } in {
-    if (present(writer.getFileError())) {
-      fail(require(writer.getFileError()))
-    }
+    \ Testing.checkEmpty(writer.getFileError())
     Int writeSize <- writer.writeBlock(data)
     if (writeSize != data.size()) {
       fail(writeSize)
     }
-    if (present(writer.getFileError())) {
-      fail(require(writer.getFileError()))
-    }
+    \ Testing.checkEmpty(writer.getFileError())
   }
 
   scoped {
@@ -45,9 +41,7 @@
   } cleanup {
     \ reader.freeResource()
   } in {
-    if (present(reader.getFileError())) {
-      fail(require(reader.getFileError()))
-    }
+    \ Testing.checkEmpty(reader.getFileError())
 
     scoped {
       String data2 <- reader.readBlock(8)
@@ -59,9 +53,7 @@
     } in if (data2 != "some\x00data") {
       fail("\"" + data2 + "\"")
     }
-    if (present(reader.getFileError())) {
-      fail(require(reader.getFileError()))
-    }
+    \ Testing.checkEmpty(reader.getFileError())
 
     if (!reader.pastEnd()) {
       fail("more data in file")
@@ -89,9 +81,7 @@
   if (data != "") {
     fail("\"" + data + "\"")
   }
-  if (present(reader.getFileError())) {
-    fail(require(reader.getFileError()))
-  }
+  \ Testing.checkEmpty(reader.getFileError())
   if (!reader.pastEnd()) {
     fail("more data in file")
   }
@@ -99,17 +89,13 @@
 
 unittest readMissing {
   RawFileReader reader <- RawFileReader.open("do-not-create-this-file")
-  if (!present(reader.getFileError())) {
-    fail("expected file error")
-  }
+  \ Testing.checkPresent(reader.getFileError())
 }
 
 unittest unwritable {
   RawFileWriter writer <- RawFileWriter.open("testfile")
   \ writer.freeResource()
-  if (!present(writer.getFileError())) {
-    fail("expected file error")
-  }
+  \ Testing.checkPresent(writer.getFileError())
 }
 
 
diff --git a/lib/testing/helpers.0rp b/lib/testing/helpers.0rp
--- a/lib/testing/helpers.0rp
+++ b/lib/testing/helpers.0rp
@@ -30,6 +30,28 @@
     #x defines Equals<#x>
   (#x,#x) -> ()
 
+  // Check the value for empty. Crashes if present.
+  //
+  // Args:
+  // - optional Formatted: Actual value.
+  @type checkEmpty (optional Formatted) -> ()
+
+  // Check the value for present. Crashes if empty.
+  //
+  // Args:
+  // - optional any: Actual value.
+  @type checkPresent (optional any) -> ()
+
+  // Check the optional values for equality. Crashes if they are not equal.
+  //
+  // Args:
+  // - optional #x: Actual value.
+  // - optional #x: Expected value.
+  @type checkOptional<#x>
+    #x requires Formatted
+    #x defines Equals<#x>
+  (optional #x,optional #x) -> ()
+
   // Check that the value is within a range. Crashes if it is not in the range.
   //
   // Args:
diff --git a/lib/testing/helpers.0rx b/lib/testing/helpers.0rx
--- a/lib/testing/helpers.0rx
+++ b/lib/testing/helpers.0rx
@@ -22,30 +22,57 @@
   checkEquals (x,y) {
     if (!#x.equals(x,y)) {
       fail(String.builder()
-        .append(x.formatted())
-        .append(" is not equal to ")
-        .append(y.formatted())
-        .build())
+          .append(x.formatted())
+          .append(" is not equal to ")
+          .append(y.formatted())
+          .build())
     }
   }
 
+  checkEmpty (x) {
+    if (present(x)) {
+      fail(String.builder()
+          .append(require(x).formatted())
+          .append(" is not empty")
+          .build())
+    }
+  }
+
+  checkPresent (x) {
+    if (!present(x)) {
+      fail(String.builder()
+          .append("expected non-empty value")
+          .build())
+    }
+  }
+
+  checkOptional (x,y) {
+    if (present(x) && present(y)) {
+      \ checkEquals<?>(require(x),require(y))
+    } elif (!present(x) && present(y)) {
+      fail("empty is not equal to " + require(y).formatted())
+    } elif (present(x) && !present(y)) {
+      fail(require(x).formatted() + " is not equal to empty")
+    }
+  }
+
   checkBetween (x,l,h) {
     if (!lessEquals<?>(l,h)) {
       fail(String.builder()
-        .append("Upper limit ")
-        .append(l.formatted())
-        .append(" is not at or above lower limit ")
-        .append(h.formatted())
-        .build())
+          .append("Upper limit ")
+          .append(l.formatted())
+          .append(" is not at or above lower limit ")
+          .append(h.formatted())
+          .build())
     }
     if (!lessEquals<?>(l,x) || !lessEquals<?>(x,h)) {
       fail(String.builder()
-        .append(x.formatted())
-        .append(" is not between ")
-        .append(l.formatted())
-        .append(" and ")
-        .append(h.formatted())
-        .build())
+          .append(x.formatted())
+          .append(" is not between ")
+          .append(l.formatted())
+          .append(" and ")
+          .append(h.formatted())
+          .build())
     }
   }
 
diff --git a/lib/testing/tests.0rt b/lib/testing/tests.0rt
--- a/lib/testing/tests.0rt
+++ b/lib/testing/tests.0rt
@@ -36,6 +36,77 @@
 }
 
 
+testcase "checkEmpty success" {
+  success
+}
+
+unittest test {
+  \ Testing.checkEmpty(empty)
+}
+
+
+testcase "checkEmpty fail" {
+  crash
+  require stderr "13"
+  require stderr "empty"
+}
+
+unittest test {
+  \ Testing.checkEmpty(13)
+}
+
+
+testcase "checkPresent success" {
+  success
+}
+
+unittest test {
+  \ Testing.checkPresent(13)
+}
+
+
+testcase "checkPresent fail" {
+  crash
+  require stderr "empty"
+}
+
+unittest test {
+  \ Testing.checkPresent(empty)
+}
+
+
+testcase "checkOptional success" {
+  success
+}
+
+unittest test {
+  \ Testing.checkOptional<Int>(empty,empty)
+  \ Testing.checkOptional<?>(13,13)
+}
+
+
+testcase "checkOptional fail empty" {
+  crash
+  require stderr "13"
+  require stderr "empty"
+}
+
+unittest test {
+  \ Testing.checkOptional<?>(13,empty)
+}
+
+
+testcase "checkOptional fail present" {
+  crash
+  require stderr "13"
+  require stderr "empty"
+}
+
+unittest test {
+  \ Testing.checkOptional<?>(empty,13)
+}
+
+
 testcase "checkBetween success" {
   success
 }
diff --git a/lib/thread/.zeolite-module b/lib/thread/.zeolite-module
--- a/lib/thread/.zeolite-module
+++ b/lib/thread/.zeolite-module
@@ -4,15 +4,10 @@
   "lib/util"
 ]
 private_deps: [
-  "lib/container"
   "lib/testing"
 ]
 extra_files: [
   category_source {
-    source: "lib/thread/src/Extension_MutexLock.cpp"
-    categories: [MutexLock]
-  }
-  category_source {
     source: "lib/thread/src/Extension_ProcessThread.cpp"
     categories: [ProcessThread]
   }
@@ -21,17 +16,12 @@
     categories: [Realtime]
   }
   category_source {
-    source: "lib/thread/src/Extension_SimpleMutex.cpp"
-    categories: [SimpleMutex]
-  }
-  category_source {
     source: "lib/thread/src/Extension_ThreadCondition.cpp"
     categories: [ThreadCondition]
   }
   category_source {
     source: "lib/thread/src/Extension_Enumerated.cpp"
     categories: [EnumeratedBarrier EnumeratedWait]
-    requires: [Stack Vector]
   }
 ]
 mode: incremental {
diff --git a/lib/thread/barrier.0rp b/lib/thread/barrier.0rp
--- a/lib/thread/barrier.0rp
+++ b/lib/thread/barrier.0rp
@@ -24,6 +24,8 @@
 
 // A thread barrier validated using thread enumeration.
 concrete EnumeratedBarrier {
+  refines ReadAt<BarrierWait>
+
   // Create a new barrier for a fixed number of threads.
   //
   // Args:
diff --git a/lib/thread/mutex.0rp b/lib/thread/mutex.0rp
deleted file mode 100644
--- a/lib/thread/mutex.0rp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -----------------------------------------------------------------------------
-Copyright 2021 Kevin P. Barry
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
------------------------------------------------------------------------------ */
-
-// Author: Kevin P. Barry [ta0kira@gmail.com]
-
-// A blocking mutex.
-//
-// Notes:
-// - Most use-cases should use MutexLock instead of explicit calls to lock() and
-//   unlock(), to mitigate the risk of deadlocks.
-@value interface Mutex {
-  // Lock the mutex.
-  lock () -> (#self)
-
-  // Unlock the mutex.
-  unlock () -> (#self)
-}
-
-// A simple mutex with no deadlock prevention.
-concrete SimpleMutex {
-  refines Mutex
-
-  // Create a new mutex.
-  @type new () -> (Mutex)
-}
-
-// An automatic mutex lock.
-//
-// Notes:
-// - freeResource() must be called; otherwise, there will be a crash. This is to
-//   catch code that could cause a deadlock.
-// - freeResource() must only be called once per MutexLock.
-//
-// Example:
-//
-//   scoped {
-//     MutexLock lock <- MutexLock.lock(myMutex)
-//     $Hidden[myMutex]$  // Hide the mutex to prevent further locking attempts.
-//   } cleanup {
-//     \ lock.freeResource()
-//   } in {
-//     $Hidden[lock]$  // Nothing else needs to see the lock.
-//     // your code
-//   }
-concrete MutexLock {
-  refines PersistentResource
-
-  // Create a new lock and lock the Mutex.
-  @type lock (Mutex) -> (MutexLock)
-}
diff --git a/lib/thread/mutex.0rt b/lib/thread/mutex.0rt
deleted file mode 100644
--- a/lib/thread/mutex.0rt
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -----------------------------------------------------------------------------
-Copyright 2021 Kevin P. Barry
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
------------------------------------------------------------------------------ */
-
-// Author: Kevin P. Barry [ta0kira@gmail.com]
-
-testcase "MutexLock crashes if not freed" {
-  crash
-  require "not freed"
-}
-
-unittest test {
-  Mutex mutex <- SimpleMutex.new()
-  \ MutexLock.lock(mutex)
-}
-
-
-testcase "MutexLock crashes if freed twice" {
-  crash
-  require "freed multiple times"
-}
-
-unittest test {
-  Mutex mutex <- SimpleMutex.new()
-  MutexLock lock <- MutexLock.lock(mutex)
-  \ lock.freeResource()
-  \ lock.freeResource()
-}
-
-
-testcase "mutex integration test" {
-  success
-}
-
-unittest test {
-  Mutex mutex <- SimpleMutex.new()
-  Value value <- Value.create()
-  Thread evenThread <- ProcessThread.from(EvenOrOdd.create(mutex,true, 10,value)).start()
-  Thread oddThread  <- ProcessThread.from(EvenOrOdd.create(mutex,false,10,value)).start()
-  \ evenThread.join()
-  \ oddThread.join()
-  \ Testing.checkEquals<?>(value.get(),20)
-}
-
-concrete EvenOrOdd {
-  refines Routine
-
-  // Args:
-  // - Mutex: Locks the Value.
-  // - Bool:  Increment only on even if true, or on odd if false.
-  // - Int:   Number of increment operations.
-  // - Value: Value to increment.
-  @type create (Mutex,Bool,Int,Value) -> (Routine)
-}
-
-define EvenOrOdd {
-  @value Mutex mutex
-  @value Bool even
-  @value Int count
-  @value Value value
-
-  create (m,e,c,v) {
-    return EvenOrOdd{ m, e, c, v }
-  }
-
-  run () {
-    scoped {
-      Int i <- 0
-    } in while (i < count) {
-      $Hidden[count]$
-      scoped {
-        MutexLock lock <- MutexLock.lock(mutex)
-        $Hidden[mutex]$
-        if (value.getInUse()) {
-          fail("value in use")
-        } else {
-          \ value.setInUse(true)
-        }
-      } cleanup {
-        \ value.setInUse(false)
-        \ lock.freeResource()
-      } in {
-        $Hidden[lock]$
-        if ((value.get()%2 == 0) ^ !even) {
-          i <- i+1
-          \ value.increment()
-        }
-      }
-    }
-  }
-}
diff --git a/lib/thread/src/Extension_Enumerated.cpp b/lib/thread/src/Extension_Enumerated.cpp
--- a/lib/thread/src/Extension_Enumerated.cpp
+++ b/lib/thread/src/Extension_Enumerated.cpp
@@ -17,6 +17,7 @@
 // Author: Kevin P. Barry [ta0kira@gmail.com]
 
 #include <atomic>
+#include <vector>
 
 #include <pthread.h>
 #include <string.h>
@@ -27,8 +28,6 @@
 #include "Category_BarrierWait.hpp"
 #include "Category_EnumeratedBarrier.hpp"
 #include "Category_Int.hpp"
-#include "Category_Stack.hpp"
-#include "Category_Vector.hpp"
 
 namespace {
 
@@ -153,6 +152,9 @@
 namespace ZEOLITE_PUBLIC_NAMESPACE {
 #endif  // ZEOLITE_PUBLIC_NAMESPACE
 
+S<TypeValue> CreateValue_EnumeratedBarrier(
+  S<Type_EnumeratedBarrier> parent, std::vector<S<TypeValue>> w);
+
 struct ExtCategory_EnumeratedBarrier : public Category_EnumeratedBarrier {
 };
 
@@ -165,20 +167,38 @@
     if (Var_arg1 < 0) {
       FAIL() << "Invalid barrier thread count " << Var_arg1;
     }
-    S<TypeValue> vector = GetCategory_Vector().Call(
-      Function_Vector_create,
-      ParamTuple(GetType_EnumeratedWait(Params<0>::Type())),
-      ArgTuple()).Only();
+    std::vector<S<TypeValue>> waits;
     S<Barrier> barrier(Var_arg1? new Barrier(Var_arg1) : nullptr);
     for (int i = 0; i < Var_arg1; ++i) {
       S<TypeValue> wait = CreateValue_EnumeratedWait(
         CreateType_EnumeratedWait(Params<0>::Type()), barrier, i);
-      TypeValue::Call(vector, Function_Stack_push, ParamTuple(), ArgTuple(wait));
+      waits.push_back(wait);
     }
-    return ReturnTuple(vector);
+    return ReturnTuple(CreateValue_EnumeratedBarrier(shared_from_this(), std::move(waits)));
   }
 };
 
+struct ExtValue_EnumeratedBarrier : public Value_EnumeratedBarrier {
+  inline ExtValue_EnumeratedBarrier(S<Type_EnumeratedBarrier> p, std::vector<S<TypeValue>> w)
+    : Value_EnumeratedBarrier(p), waits(std::move(w)) {}
+
+  ReturnTuple Call_readAt(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) final {
+    TRACE_FUNCTION("EnumeratedBarrier.readAt")
+    const PrimInt Var_arg1 = (args.At(0))->AsInt();
+    if (Var_arg1 < 0 || Var_arg1 >= waits.size()) {
+      FAIL() << "index " << Var_arg1 << " is out of bounds";
+    }
+    return ReturnTuple(waits[Var_arg1]);
+  }
+
+  ReturnTuple Call_size(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) final {
+    TRACE_FUNCTION("EnumeratedBarrier.size")
+    return ReturnTuple(Box_Int(waits.size()));
+  }
+
+  const std::vector<S<TypeValue>> waits;
+};
+
 Category_EnumeratedBarrier& CreateCategory_EnumeratedBarrier() {
   static auto& category = *new ExtCategory_EnumeratedBarrier();
   return category;
@@ -186,6 +206,10 @@
 S<Type_EnumeratedBarrier> CreateType_EnumeratedBarrier(Params<0>::Type params) {
   static const auto cached = S_get(new ExtType_EnumeratedBarrier(CreateCategory_EnumeratedBarrier(), Params<0>::Type()));
   return cached;
+}
+S<TypeValue> CreateValue_EnumeratedBarrier(
+  S<Type_EnumeratedBarrier> parent, std::vector<S<TypeValue>> w) {
+  return S_get(new ExtValue_EnumeratedBarrier(parent, std::move(w)));
 }
 
 #ifdef ZEOLITE_PUBLIC_NAMESPACE
diff --git a/lib/thread/src/Extension_MutexLock.cpp b/lib/thread/src/Extension_MutexLock.cpp
deleted file mode 100644
--- a/lib/thread/src/Extension_MutexLock.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -----------------------------------------------------------------------------
-Copyright 2021 Kevin P. Barry
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
------------------------------------------------------------------------------ */
-
-// Author: Kevin P. Barry [ta0kira@gmail.com]
-
-#include <mutex>
-
-#include "category-source.hpp"
-#include "Streamlined_MutexLock.hpp"
-#include "Category_Mutex.hpp"
-#include "Category_MutexLock.hpp"
-#include "Category_PersistentResource.hpp"
-
-#ifdef ZEOLITE_PUBLIC_NAMESPACE
-namespace ZEOLITE_PUBLIC_NAMESPACE {
-#endif  // ZEOLITE_PUBLIC_NAMESPACE
-
-S<TypeValue> CreateValue_MutexLock(S<Type_MutexLock> parent, const ValueTuple& args);
-
-struct ExtCategory_MutexLock : public Category_MutexLock {
-};
-
-struct ExtType_MutexLock : public Type_MutexLock {
-  inline ExtType_MutexLock(Category_MutexLock& p, Params<0>::Type params) : Type_MutexLock(p, params) {}
-
-  ReturnTuple Call_lock(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {
-    TRACE_FUNCTION("MutexLock.lock")
-    return ReturnTuple(CreateValue_MutexLock(CreateType_MutexLock(Params<0>::Type()), args));
-  }
-};
-
-struct ExtValue_MutexLock : public Value_MutexLock {
-  inline ExtValue_MutexLock(S<Type_MutexLock> p, const ValueTuple& args)
-    : Value_MutexLock(p), mutex(args.Only()) {
-    TypeValue::Call(mutex, Function_Mutex_lock, ParamTuple(), ArgTuple());
-  }
-
-  ReturnTuple Call_freeResource(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) final {
-    TRACE_FUNCTION("MutexLock.freeResource")
-    TRACE_CREATION
-    if (!mutex) {
-      FAIL() << "MutexLock freed multiple times";
-    } else {
-      TypeValue::Call(mutex, Function_Mutex_unlock, ParamTuple(), ArgTuple());
-      mutex = nullptr;
-    }
-    return ReturnTuple();
-  }
-
-  ~ExtValue_MutexLock() {
-    if (mutex) {
-      TRACE_CREATION
-      TypeValue::Call(mutex, Function_Mutex_unlock, ParamTuple(), ArgTuple());
-      mutex = nullptr;
-      FAIL() << "MutexLock not freed with freeResource()";
-    }
-  }
-
-  S<TypeValue> mutex;
-  CAPTURE_CREATION("MutexLock")
-};
-
-Category_MutexLock& CreateCategory_MutexLock() {
-  static auto& category = *new ExtCategory_MutexLock();
-  return category;
-}
-S<Type_MutexLock> CreateType_MutexLock(Params<0>::Type params) {
-  static const auto cached = S_get(new ExtType_MutexLock(CreateCategory_MutexLock(), Params<0>::Type()));
-  return cached;
-}
-S<TypeValue> CreateValue_MutexLock(S<Type_MutexLock> parent, const ValueTuple& args) {
-  return S_get(new ExtValue_MutexLock(parent, args));
-}
-
-#ifdef ZEOLITE_PUBLIC_NAMESPACE
-}  // namespace ZEOLITE_PUBLIC_NAMESPACE
-using namespace ZEOLITE_PUBLIC_NAMESPACE;
-#endif  // ZEOLITE_PUBLIC_NAMESPACE
diff --git a/lib/thread/src/Extension_ProcessThread.cpp b/lib/thread/src/Extension_ProcessThread.cpp
--- a/lib/thread/src/Extension_ProcessThread.cpp
+++ b/lib/thread/src/Extension_ProcessThread.cpp
@@ -41,7 +41,7 @@
 
   ReturnTuple Call_from(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {
     TRACE_FUNCTION("ProcessThread.from")
-    return ReturnTuple(CreateValue_ProcessThread(CreateType_ProcessThread(Params<0>::Type()), args));
+    return ReturnTuple(CreateValue_ProcessThread(shared_from_this(), args));
   }
 };
 
diff --git a/lib/thread/src/Extension_SimpleMutex.cpp b/lib/thread/src/Extension_SimpleMutex.cpp
deleted file mode 100644
--- a/lib/thread/src/Extension_SimpleMutex.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -----------------------------------------------------------------------------
-Copyright 2021 Kevin P. Barry
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
------------------------------------------------------------------------------ */
-
-// Author: Kevin P. Barry [ta0kira@gmail.com]
-
-#include <mutex>
-
-#include "category-source.hpp"
-#include "Streamlined_SimpleMutex.hpp"
-#include "Category_Mutex.hpp"
-#include "Category_SimpleMutex.hpp"
-
-#ifdef ZEOLITE_PUBLIC_NAMESPACE
-namespace ZEOLITE_PUBLIC_NAMESPACE {
-#endif  // ZEOLITE_PUBLIC_NAMESPACE
-
-S<TypeValue> CreateValue_SimpleMutex(S<Type_SimpleMutex> parent);
-
-struct ExtCategory_SimpleMutex : public Category_SimpleMutex {
-};
-
-struct ExtType_SimpleMutex : public Type_SimpleMutex {
-  inline ExtType_SimpleMutex(Category_SimpleMutex& p, Params<0>::Type params) : Type_SimpleMutex(p, params) {}
-
-  ReturnTuple Call_new(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {
-    TRACE_FUNCTION("SimpleMutex.new")
-    return ReturnTuple(CreateValue_SimpleMutex(CreateType_SimpleMutex(Params<0>::Type())));
-  }
-};
-
-struct ExtValue_SimpleMutex : public Value_SimpleMutex {
-  inline ExtValue_SimpleMutex(S<Type_SimpleMutex> p) : Value_SimpleMutex(p) {}
-
-  ReturnTuple Call_lock(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) final {
-    TRACE_FUNCTION("SimpleMutex.lock")
-    mutex.lock();
-    return ReturnTuple(Var_self);
-  }
-
-  ReturnTuple Call_unlock(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) final {
-    TRACE_FUNCTION("SimpleMutex.unlock")
-    mutex.unlock();
-    return ReturnTuple(Var_self);
-  }
-
-  std::mutex mutex;
-};
-
-Category_SimpleMutex& CreateCategory_SimpleMutex() {
-  static auto& category = *new ExtCategory_SimpleMutex();
-  return category;
-}
-S<Type_SimpleMutex> CreateType_SimpleMutex(Params<0>::Type params) {
-  static const auto cached = S_get(new ExtType_SimpleMutex(CreateCategory_SimpleMutex(), Params<0>::Type()));
-  return cached;
-}
-S<TypeValue> CreateValue_SimpleMutex(S<Type_SimpleMutex> parent) {
-  return S_get(new ExtValue_SimpleMutex(parent));
-}
-
-#ifdef ZEOLITE_PUBLIC_NAMESPACE
-}  // namespace ZEOLITE_PUBLIC_NAMESPACE
-using namespace ZEOLITE_PUBLIC_NAMESPACE;
-#endif  // ZEOLITE_PUBLIC_NAMESPACE
diff --git a/lib/thread/src/Extension_ThreadCondition.cpp b/lib/thread/src/Extension_ThreadCondition.cpp
--- a/lib/thread/src/Extension_ThreadCondition.cpp
+++ b/lib/thread/src/Extension_ThreadCondition.cpp
@@ -42,7 +42,7 @@
 
   ReturnTuple Call_new(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {
     TRACE_FUNCTION("ThreadCondition.new")
-    return ReturnTuple(CreateValue_ThreadCondition(CreateType_ThreadCondition(Params<0>::Type())));
+    return ReturnTuple(CreateValue_ThreadCondition(shared_from_this()));
   }
 };
 
diff --git a/lib/thread/thread.0rt b/lib/thread/thread.0rt
--- a/lib/thread/thread.0rt
+++ b/lib/thread/thread.0rt
@@ -78,6 +78,70 @@
 }
 
 
+testcase "ProcessThread mutex integration test" {
+  success
+}
+
+unittest test {
+  Mutex mutex <- SimpleMutex.new()
+  Value value <- Value.create()
+  Thread evenThread <- ProcessThread.from(EvenOrOdd.create(mutex,true, 10,value)).start()
+  Thread oddThread  <- ProcessThread.from(EvenOrOdd.create(mutex,false,10,value)).start()
+  \ evenThread.join()
+  \ oddThread.join()
+  \ Testing.checkEquals<?>(value.get(),20)
+}
+
+concrete EvenOrOdd {
+  refines Routine
+
+  // Args:
+  // - Mutex: Locks the Value.
+  // - Bool:  Increment only on even if true, or on odd if false.
+  // - Int:   Number of increment operations.
+  // - Value: Value to increment.
+  @type create (Mutex,Bool,Int,Value) -> (Routine)
+}
+
+define EvenOrOdd {
+  @value Mutex mutex
+  @value Bool even
+  @value Int count
+  @value Value value
+
+  create (m,e,c,v) {
+    return EvenOrOdd{ m, e, c, v }
+  }
+
+  run () {
+    scoped {
+      Int i <- 0
+    } in while (i < count) {
+      $Hidden[count]$
+      scoped {
+        MutexLock lock <- MutexLock.lock(mutex)
+        $Hidden[mutex]$
+        if (value.getInUse()) {
+          fail("value in use")
+        } else {
+          \ value.setInUse(true)
+        }
+      } cleanup {
+        \ value.setInUse(false)
+        \ lock.freeResource()
+      } in {
+        $Hidden[lock]$
+        if ((value.get()%2 == 0) ^ !even) {
+          i <- i+1
+          \ value.increment()
+        }
+      }
+    }
+  }
+}
+
+
+
 testcase "Argv available in Thread" {
   success
   args "arg1"
diff --git a/lib/util/.zeolite-module b/lib/util/.zeolite-module
--- a/lib/util/.zeolite-module
+++ b/lib/util/.zeolite-module
@@ -15,8 +15,16 @@
     categories: [Argv]
   }
   category_source {
+    source: "lib/util/src/Extension_MutexLock.cpp"
+    categories: [MutexLock]
+  }
+  category_source {
     source: "lib/util/src/Extension_SimpleInput.cpp"
     categories: [SimpleInput]
+  }
+  category_source {
+    source: "lib/util/src/Extension_SimpleMutex.cpp"
+    categories: [SimpleMutex]
   }
   category_source {
     source: "lib/util/src/Extension_SimpleOutput.cpp"
diff --git a/lib/util/extra.0rt b/lib/util/extra.0rt
--- a/lib/util/extra.0rt
+++ b/lib/util/extra.0rt
@@ -23,9 +23,7 @@
 
 unittest global {
   Int count <- Argv.global().size()
-  if (count != 5) {
-    fail(count)
-  }
+  \ Testing.checkEquals<?>(count,5)
   \ Testing.checkEquals<?>(Argv.global().readAt(0),"testcase")
   \ Testing.checkEquals<?>(Argv.global().readAt(1),"arg1")
   \ Testing.checkEquals<?>(Argv.global().readAt(2),"arg2")
@@ -36,9 +34,7 @@
 unittest subSequence {
   ReadAt<String> argv <- Argv.global().subSequence(2,2)
   Int count <- argv.size()
-  if (count != 2) {
-    fail(count)
-  }
+  \ Testing.checkEquals<?>(count,2)
   \ Testing.checkEquals<?>(argv.readAt(0),"arg2")
   \ Testing.checkEquals<?>(argv.readAt(1),"arg3")
 }
@@ -70,17 +66,13 @@
 
 unittest withValue {
   ErrorOr<Int> value <- ErrorOr:value<Int>(10)
-  if (value.isError()) {
-    fail("Failed")
-  }
+  \ Testing.checkEquals<?>(value.isError(),false)
   \ Testing.checkEquals<?>(value.getValue(),10)
 }
 
 unittest withError {
   ErrorOr<String> value <- ErrorOr:error("error message")
-  if (!value.isError()) {
-    fail("Failed")
-  }
+  \ Testing.checkEquals<?>(value.isError(),true)
   \ Testing.checkEquals<?>(value.getError().formatted(),"error message")
 }
 
diff --git a/lib/util/input.0rt b/lib/util/input.0rt
--- a/lib/util/input.0rt
+++ b/lib/util/input.0rt
@@ -30,9 +30,7 @@
       fail("past end")
     }
     String value <- reader.readNextLine()
-    if (value != line) {
-      fail(value)
-    }
+    \ Testing.checkEquals<?>(value,line)
   }
 }
 
diff --git a/lib/util/input.0rx b/lib/util/input.0rx
--- a/lib/util/input.0rx
+++ b/lib/util/input.0rx
@@ -56,16 +56,13 @@
 
   @value findNewline () -> (Int)
   findNewline () {
-    scoped {
-      Int position <- 0
-    } in while (position < buffer.size()) {
+    traverse (Counter.zeroIndexed(buffer.size()) -> Int position) {
+      $ReadOnly[position]$
       Char c <- buffer.readAt(position)
       // TODO: Maybe the line separator should be a factory argument.
       if (c == '\n' || c == '\r') {
         return position
       }
-    } update {
-      position <- position+1
     }
     return -1
   }
diff --git a/lib/util/iterator.0rt b/lib/util/iterator.0rt
--- a/lib/util/iterator.0rt
+++ b/lib/util/iterator.0rt
@@ -27,16 +27,12 @@
     ReadIterator<Char> iter <- AutoReadIterator:from<?>(s)
   } in while (!iter.pastForwardEnd()) {
     $ReadOnly[count,iter]$
-    if (iter.readCurrent() != s.readAt(count)) {
-      fail(iter.readCurrent())
-    }
+    \ Testing.checkEquals<?>(iter.readCurrent(),s.readAt(count))
   } update {
     count <- count+1
     iter <- iter.forward()
   }
-  if (count != s.size()) {
-    fail(count)
-  }
+  \ Testing.checkEquals<?>(count,s.size())
 }
 
 unittest reverseRead {
@@ -51,9 +47,7 @@
     count <- count-1
     iter <- iter.reverse()
   }
-  if (count != -1) {
-    fail(count)
-  }
+  \ Testing.checkEquals<?>(count,-1)
 }
 
 
@@ -74,9 +68,7 @@
     count <- count+1
     iter <- iter.forward()
   }
-  if (count != s.size()) {
-    fail(count)
-  }
+  \ Testing.checkEquals<?>(count,s.size())
 }
 
 unittest reverseWrite {
@@ -92,9 +84,7 @@
     count <- count-1
     iter <- iter.reverse()
   }
-  if (count != -1) {
-    fail(count)
-  }
+  \ Testing.checkEquals<?>(count,-1)
 }
 
 concrete WriteChecker {
@@ -139,9 +129,7 @@
     count <- count+1
     iter <- iter.forward()
   }
-  if (count != s.size()) {
-    fail(count)
-  }
+  \ Testing.checkEquals<?>(count,s.size())
 }
 
 unittest reverseReadWrite {
@@ -158,9 +146,7 @@
     count <- count-1
     iter <- iter.reverse()
   }
-  if (count != -1) {
-    fail(count)
-  }
+  \ Testing.checkEquals<?>(count,-1)
 }
 
 concrete ReadWriteChecker {
diff --git a/lib/util/mutex.0rp b/lib/util/mutex.0rp
new file mode 100644
--- /dev/null
+++ b/lib/util/mutex.0rp
@@ -0,0 +1,63 @@
+/* -----------------------------------------------------------------------------
+Copyright 2021 Kevin P. Barry
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+----------------------------------------------------------------------------- */
+
+// Author: Kevin P. Barry [ta0kira@gmail.com]
+
+// A blocking mutex.
+//
+// Notes:
+// - Most use-cases should use MutexLock instead of explicit calls to lock() and
+//   unlock(), to mitigate the risk of deadlocks.
+@value interface Mutex {
+  // Lock the mutex.
+  lock () -> (#self)
+
+  // Unlock the mutex.
+  unlock () -> (#self)
+}
+
+// A simple mutex with no deadlock prevention.
+concrete SimpleMutex {
+  refines Mutex
+
+  // Create a new mutex.
+  @type new () -> (Mutex)
+}
+
+// An automatic mutex lock.
+//
+// Notes:
+// - freeResource() must be called; otherwise, there will be a crash. This is to
+//   catch code that could cause a deadlock.
+// - freeResource() must only be called once per MutexLock.
+//
+// Example:
+//
+//   scoped {
+//     MutexLock lock <- MutexLock.lock(myMutex)
+//     $Hidden[myMutex]$  // Hide the mutex to prevent further locking attempts.
+//   } cleanup {
+//     \ lock.freeResource()
+//   } in {
+//     $Hidden[lock]$  // Nothing else needs to see the lock.
+//     // your code
+//   }
+concrete MutexLock {
+  refines PersistentResource
+
+  // Create a new lock and lock the Mutex.
+  @type lock (Mutex) -> (MutexLock)
+}
diff --git a/lib/util/mutex.0rt b/lib/util/mutex.0rt
new file mode 100644
--- /dev/null
+++ b/lib/util/mutex.0rt
@@ -0,0 +1,50 @@
+/* -----------------------------------------------------------------------------
+Copyright 2021 Kevin P. Barry
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+----------------------------------------------------------------------------- */
+
+// Author: Kevin P. Barry [ta0kira@gmail.com]
+
+testcase "SimpleMutex tests" {
+  success
+}
+
+unittest lockUnlock {
+  Mutex mutex <- SimpleMutex.new()
+  \ mutex.lock().unlock().lock().unlock()
+}
+
+
+testcase "MutexLock crashes if not freed" {
+  crash
+  require "not freed"
+}
+
+unittest test {
+  Mutex mutex <- SimpleMutex.new()
+  \ MutexLock.lock(mutex)
+}
+
+
+testcase "MutexLock crashes if freed twice" {
+  crash
+  require "freed multiple times"
+}
+
+unittest test {
+  Mutex mutex <- SimpleMutex.new()
+  MutexLock lock <- MutexLock.lock(mutex)
+  \ lock.freeResource()
+  \ lock.freeResource()
+}
diff --git a/lib/util/src/Extension_MutexLock.cpp b/lib/util/src/Extension_MutexLock.cpp
new file mode 100644
--- /dev/null
+++ b/lib/util/src/Extension_MutexLock.cpp
@@ -0,0 +1,91 @@
+/* -----------------------------------------------------------------------------
+Copyright 2021 Kevin P. Barry
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+----------------------------------------------------------------------------- */
+
+// Author: Kevin P. Barry [ta0kira@gmail.com]
+
+#include <mutex>
+
+#include "category-source.hpp"
+#include "Streamlined_MutexLock.hpp"
+#include "Category_Mutex.hpp"
+#include "Category_MutexLock.hpp"
+#include "Category_PersistentResource.hpp"
+
+#ifdef ZEOLITE_PUBLIC_NAMESPACE
+namespace ZEOLITE_PUBLIC_NAMESPACE {
+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+
+S<TypeValue> CreateValue_MutexLock(S<Type_MutexLock> parent, const ValueTuple& args);
+
+struct ExtCategory_MutexLock : public Category_MutexLock {
+};
+
+struct ExtType_MutexLock : public Type_MutexLock {
+  inline ExtType_MutexLock(Category_MutexLock& p, Params<0>::Type params) : Type_MutexLock(p, params) {}
+
+  ReturnTuple Call_lock(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {
+    TRACE_FUNCTION("MutexLock.lock")
+    return ReturnTuple(CreateValue_MutexLock(CreateType_MutexLock(Params<0>::Type()), args));
+  }
+};
+
+struct ExtValue_MutexLock : public Value_MutexLock {
+  inline ExtValue_MutexLock(S<Type_MutexLock> p, const ValueTuple& args)
+    : Value_MutexLock(p), mutex(args.Only()) {
+    TypeValue::Call(mutex, Function_Mutex_lock, ParamTuple(), ArgTuple());
+  }
+
+  ReturnTuple Call_freeResource(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) final {
+    TRACE_FUNCTION("MutexLock.freeResource")
+    TRACE_CREATION
+    if (!mutex) {
+      FAIL() << "MutexLock freed multiple times";
+    } else {
+      TypeValue::Call(mutex, Function_Mutex_unlock, ParamTuple(), ArgTuple());
+      mutex = nullptr;
+    }
+    return ReturnTuple();
+  }
+
+  ~ExtValue_MutexLock() {
+    if (mutex) {
+      TRACE_CREATION
+      TypeValue::Call(mutex, Function_Mutex_unlock, ParamTuple(), ArgTuple());
+      mutex = nullptr;
+      FAIL() << "MutexLock not freed with freeResource()";
+    }
+  }
+
+  S<TypeValue> mutex;
+  CAPTURE_CREATION("MutexLock")
+};
+
+Category_MutexLock& CreateCategory_MutexLock() {
+  static auto& category = *new ExtCategory_MutexLock();
+  return category;
+}
+S<Type_MutexLock> CreateType_MutexLock(Params<0>::Type params) {
+  static const auto cached = S_get(new ExtType_MutexLock(CreateCategory_MutexLock(), Params<0>::Type()));
+  return cached;
+}
+S<TypeValue> CreateValue_MutexLock(S<Type_MutexLock> parent, const ValueTuple& args) {
+  return S_get(new ExtValue_MutexLock(parent, args));
+}
+
+#ifdef ZEOLITE_PUBLIC_NAMESPACE
+}  // namespace ZEOLITE_PUBLIC_NAMESPACE
+using namespace ZEOLITE_PUBLIC_NAMESPACE;
+#endif  // ZEOLITE_PUBLIC_NAMESPACE
diff --git a/lib/util/src/Extension_SimpleMutex.cpp b/lib/util/src/Extension_SimpleMutex.cpp
new file mode 100644
--- /dev/null
+++ b/lib/util/src/Extension_SimpleMutex.cpp
@@ -0,0 +1,77 @@
+/* -----------------------------------------------------------------------------
+Copyright 2021 Kevin P. Barry
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+----------------------------------------------------------------------------- */
+
+// Author: Kevin P. Barry [ta0kira@gmail.com]
+
+#include <mutex>
+
+#include "category-source.hpp"
+#include "Streamlined_SimpleMutex.hpp"
+#include "Category_Mutex.hpp"
+#include "Category_SimpleMutex.hpp"
+
+#ifdef ZEOLITE_PUBLIC_NAMESPACE
+namespace ZEOLITE_PUBLIC_NAMESPACE {
+#endif  // ZEOLITE_PUBLIC_NAMESPACE
+
+S<TypeValue> CreateValue_SimpleMutex(S<Type_SimpleMutex> parent);
+
+struct ExtCategory_SimpleMutex : public Category_SimpleMutex {
+};
+
+struct ExtType_SimpleMutex : public Type_SimpleMutex {
+  inline ExtType_SimpleMutex(Category_SimpleMutex& p, Params<0>::Type params) : Type_SimpleMutex(p, params) {}
+
+  ReturnTuple Call_new(const S<TypeInstance>& Param_self, const ParamTuple& params, const ValueTuple& args) final {
+    TRACE_FUNCTION("SimpleMutex.new")
+    return ReturnTuple(CreateValue_SimpleMutex(CreateType_SimpleMutex(Params<0>::Type())));
+  }
+};
+
+struct ExtValue_SimpleMutex : public Value_SimpleMutex {
+  inline ExtValue_SimpleMutex(S<Type_SimpleMutex> p) : Value_SimpleMutex(p) {}
+
+  ReturnTuple Call_lock(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) final {
+    TRACE_FUNCTION("SimpleMutex.lock")
+    mutex.lock();
+    return ReturnTuple(Var_self);
+  }
+
+  ReturnTuple Call_unlock(const S<TypeValue>& Var_self, const ParamTuple& params, const ValueTuple& args) final {
+    TRACE_FUNCTION("SimpleMutex.unlock")
+    mutex.unlock();
+    return ReturnTuple(Var_self);
+  }
+
+  std::mutex mutex;
+};
+
+Category_SimpleMutex& CreateCategory_SimpleMutex() {
+  static auto& category = *new ExtCategory_SimpleMutex();
+  return category;
+}
+S<Type_SimpleMutex> CreateType_SimpleMutex(Params<0>::Type params) {
+  static const auto cached = S_get(new ExtType_SimpleMutex(CreateCategory_SimpleMutex(), Params<0>::Type()));
+  return cached;
+}
+S<TypeValue> CreateValue_SimpleMutex(S<Type_SimpleMutex> parent) {
+  return S_get(new ExtValue_SimpleMutex(parent));
+}
+
+#ifdef ZEOLITE_PUBLIC_NAMESPACE
+}  // namespace ZEOLITE_PUBLIC_NAMESPACE
+using namespace ZEOLITE_PUBLIC_NAMESPACE;
+#endif  // ZEOLITE_PUBLIC_NAMESPACE
diff --git a/src/CompilerCxx/CxxFiles.hs b/src/CompilerCxx/CxxFiles.hs
--- a/src/CompilerCxx/CxxFiles.hs
+++ b/src/CompilerCxx/CxxFiles.hs
@@ -388,7 +388,7 @@
     ] where
       members = filter ((== CategoryScope). dmScope) $ dcMembers d
   defineConcreteType fs t = concatM [
-      return $ onlyCode $ "struct " ++ typeName (getCategoryName t) ++ " : public " ++ typeBase ++ " {",
+      return $ onlyCode $ "struct " ++ className ++ " : public " ++ typeBase ++ ", std::enable_shared_from_this<" ++ className ++ "> {",
       fmap indentCompiled $ inlineTypeConstructor t,
       return declareTypeOverrides,
       return $ declareTypeArgGetters t,
@@ -396,7 +396,9 @@
       return $ indentCompiled $ createParams $ getCategoryParams t,
       return $ onlyCode $ "  " ++ categoryName (getCategoryName t) ++ "& parent;",
       return $ onlyCode "};"
-    ]
+    ] where
+      className = typeName (getCategoryName t)
+
   defineConcreteValue r params fs t d = concatM [
       return $ onlyCode $ "struct " ++ valueName (getCategoryName t) ++ " : public " ++ valueBase ++ " {",
       fmap indentCompiled $ inlineValueConstructor t d,
@@ -421,7 +423,7 @@
       return $ onlyCode "};"
     ]
   defineAbstractType t = concatM [
-      return $ onlyCode $ "struct " ++ typeName (getCategoryName t) ++ " : public " ++ typeBase ++ " {",
+      return $ onlyCode $ "struct " ++ className ++ " : public " ++ typeBase ++ ", std::enable_shared_from_this<" ++ className ++ "> {",
       fmap indentCompiled $ inlineTypeConstructor t,
       return declareTypeOverrides,
       return $ declareTypeArgGetters t,
@@ -430,7 +432,8 @@
       return $ indentCompiled $ createParams $ getCategoryParams t,
       return $ onlyCode $ "  " ++ categoryName (getCategoryName t) ++ "& parent;",
       return $ onlyCode "};"
-    ]
+    ] where
+      className = typeName (getCategoryName t)
   defineAbstractValue t = concatM [
       return $ onlyCode $ "struct " ++ valueName (getCategoryName t) ++ " : public " ++ valueBase ++ " {",
       fmap indentCompiled $ abstractValueConstructor t,
@@ -722,7 +725,8 @@
               ["    DispatchTable<CallType>(),","  };"]
   dispatchKeyValue (n2,_) = "    DispatchTable<CallType>(" ++ collectionName n2 ++ ", " ++ tableName n2 ++ "),"
   select = [
-      "  const DispatchTable<CallType>* const table = DispatchSelect(label.collection, all_tables);",
+      "  std::atomic_bool table_lock{0};",
+      "  const DispatchTable<CallType>* const table = DispatchSelect(table_lock, label.collection, all_tables);",
       "  if (table) {",
       "    if (label.function_num < 0 || label.function_num >= table->size) {",
       "      FAIL() << \"Bad function call \" << label;",
@@ -786,7 +790,8 @@
     ] ++ map dispatchKeyValue ((getCategoryName t):refines) ++ [
       "    DispatchSingle<CallType>(),",
       "  };",
-      "  const DispatchSingle<CallType>* const call = DispatchSelect(&category, all_calls);",
+      "  std::atomic_bool table_lock{0};",
+      "  const DispatchSingle<CallType>* const call = DispatchSelect(table_lock, &category, all_calls);",
       "  if (call) {",
       "    (this->*call->value)(args);",
       "    return true;",
diff --git a/src/CompilerCxx/Procedure.hs b/src/CompilerCxx/Procedure.hs
--- a/src/CompilerCxx/Procedure.hs
+++ b/src/CompilerCxx/Procedure.hs
@@ -631,6 +631,7 @@
             UnwrappedSingle $ valueCreator (tiName t') ++ "(" ++ typeInstance ++ ", " ++ es'' ++ ")")
     where
       getType _  True ValueScope _      = "parent"
+      getType _  True TypeScope  _      = "shared_from_this()"
       getType t2 _    _          params = typeCreator (tiName t2) ++ "(" ++ params ++ ")"
       -- Single expression, but possibly multi-return.
       getValues [(Positional ts,e)] = return (ts,useAsArgs e)
@@ -940,8 +941,8 @@
       return $ callName (sfName f) ++ "(Var_self, " ++ ps2 ++ ", " ++ es2 ++ ")"
     assemble Nothing _ TypeScope TypeScope ps2 es2 =
       return $ callName (sfName f) ++ "(Param_self, " ++ ps2 ++ ", " ++ es2 ++ ")"
-    assemble Nothing _ ValueScope TypeScope ps2 es2 =
-      return $ typeBase ++ "::Call(parent, " ++ functionName f ++ ", " ++ ps2 ++ ", " ++ es2 ++ ")"
+    assemble Nothing scoped ValueScope TypeScope ps2 es2 =
+      return $ scoped ++ callName (sfName f) ++ "(parent, "++ ps2 ++ ", " ++ es2 ++ ")"
     assemble Nothing scoped _ _ ps2 es2 =
       return $ scoped ++ callName (sfName f) ++ "(" ++ ps2 ++ ", " ++ es2 ++ ")"
     assemble (Just e2) _ _ ValueScope ps2 es2 =
diff --git a/src/Module/ProcessMetadata.hs b/src/Module/ProcessMetadata.hs
--- a/src/Module/ProcessMetadata.hs
+++ b/src/Module/ProcessMetadata.hs
@@ -232,7 +232,7 @@
           case p `Map.lookup` ca of
                Just m2 -> continue m2 []
                Nothing -> do
-                 errorFromIO $ hPutStrLn stderr $ "Loading metadata for dependency \"" ++ p ++ "\"."
+                 errorFromIO $ hPutStrLn stderr $ "Loading metadata for module \"" ++ p ++ "\"."
                  m2 <- loadMetadata ca p
                  let ds = getDeps m2
                  continue m2 ds
diff --git a/zeolite-lang.cabal b/zeolite-lang.cabal
--- a/zeolite-lang.cabal
+++ b/zeolite-lang.cabal
@@ -1,7 +1,7 @@
 cabal-version:       2.2
 
 name:                zeolite-lang
-version:             0.16.0.0
+version:             0.16.1.0
 synopsis:            Zeolite is a statically-typed, general-purpose programming language.
 
 description:
