diff --git a/lib/modules/Thread.pmod b/lib/modules/Thread.pmod
index 68d228f67772ebfb952a94b25b4eacb22a28e5ba..2d4992ebecc206a810b3e975d74f6124b3f9f5b9 100644
--- a/lib/modules/Thread.pmod
+++ b/lib/modules/Thread.pmod
@@ -804,6 +804,79 @@ optional class Farm
   }
 }
 
+//! When this key is destroyed, the corresponding resource counter
+//! will be decremented.
+//!
+//! @seealso
+//!   @[ResourceCount], @[MutexKey]
+//!
+optional class ResourceCountKey {
+  /*semi*/private ResourceCount parent;
+
+  /*semi*/private void create(ResourceCount _parent) {
+    parent = _parent;
+  }
+
+  /*semi*/private void destroy() {
+    --parent->_count;
+    parent->_cond->signal();
+  }
+}
+
+//! Implements an inverted-semaphore-like resource
+//! counter.  A thread can poll or perform a blocking wait for the
+//! resource-count to drop below a certain @ref{level@}.
+//!
+//! @seealso
+//!   @[ResourceCountKey], @[Condition], @[Mutex]
+optional class ResourceCount {
+  /*semi*/final int _count;
+  /*semi*/final Condition _cond = Condition();
+
+  //! @param level
+  //!   The maximum level that is considered drained.
+  //!
+  //! @returns
+  //!   True if the resource counter drops to equal or below @ref{level@}.
+  /*semi*/final int(0..1) drained(void|int level) {
+    return level >= _count;
+  }
+
+  //! Blocks until the resource-counter dips to max @ref{level@}.
+  //!
+  //! @param lock
+  //!   A previously acquired @[MutexKey].
+  //!
+  //! @param level
+  //!   The maximum level that is considered drained.
+  /*semi*/final void wait_till_drained(MutexKey lock, void|int level) {
+    while (_count > level)		// Recheck before allowing further
+      _cond->wait(lock);
+    lock = 0;				// Eliminate references
+  }
+
+  //! Increments the resource-counter.
+  //! @returns
+  //!   A @[ResourceCountKey] to decrement the resource-counter again.
+  /*semi*/final ResourceCountKey acquire() {
+    _count++;
+    return ResourceCountKey(this);
+  }
+
+  /*semi*/private string _sprintf(int type) {
+    string res = UNDEFINED;
+    switch(type) {
+      case 'O':
+        res = sprintf("Count: %d", _count);
+        break;
+      case 'd':
+        res = sprintf("%d", _count);
+        break;
+    }
+    return res;
+  }
+}
+
 #else /* !constant(thread_create) */
 
 // Simulations of some of the classes for nonthreaded use.
diff --git a/lib/modules/testsuite.in b/lib/modules/testsuite.in
index f174965c3e03303dae08b16f052c5d125898ddd3..2bf693f8c498c43130c5b6605134aead54fbf4b5 100644
--- a/lib/modules/testsuite.in
+++ b/lib/modules/testsuite.in
@@ -1743,6 +1743,22 @@ test_false([[ TestQueue->size() ]])
 test_true([[ zero_type(TestQueue->try_read()) ]])
 test_do([[ add_constant("TestQueue"); ]])
 
+// Thread.ResourceCount
+test_do([[ add_constant("TestResourceCount", Thread.ResourceCount()); ]])
+test_any_equal([[
+  int i;
+  array a = allocate(10);
+  for(i = 0; i < 10; i++) {
+    a[i] = TestResourceCount->acquire();
+  }
+  for(i = 0; i < 10; i++) {
+    a[i] = 0;
+    a[i] = TestResourceCount->drained();
+  }
+  return a;
+]], ({ 0,0,0,0,0,0,0,0,0,1 }))
+test_do([[ add_constant("TestResourceCount"); ]])
+
 test_false(!Val.true)
 test_true(!Val.false)
 test_eq((int) Val.true, 1)