diff --git a/emper/Blockable.hpp b/emper/Blockable.hpp
index 43aaa13d30a1eac82279f0756189b7b2000f48e3..2e9c6350fc6b104b2ff4030cd34d52d902f19c3f 100644
--- a/emper/Blockable.hpp
+++ b/emper/Blockable.hpp
@@ -6,7 +6,10 @@
 #include "ContextManager.hpp"
 #include "Context.hpp"
 
-class Blockable {
+template<LogSubsystem logSubsystem>
+class Blockable :
+	public Logger<logSubsystem> {
+
 protected:
 
 	Runtime& runtime;
@@ -31,5 +34,4 @@ protected:
 		runtime.schedule(*unblockFiber);
 	}
 
-	virtual void logD(const std::string& string) const = 0;
 };
diff --git a/emper/Debug.hpp b/emper/Debug.hpp
index dca6fe1c946d2dbb33ad5c24e84ec42fe9d81752..1ed5fd468d11ed7d35308cc25155f50b9f63fbd9 100644
--- a/emper/Debug.hpp
+++ b/emper/Debug.hpp
@@ -18,8 +18,11 @@
 
 #define DBG(x) do { std::cerr << x << std::endl; } while (false)
 #define WDBG(x) do { std::stringstream sst; sst << x; worker_log("", sst.str()); } while (false)
-#define LOGD(x) do { std::stringstream sst; sst << x; logD(sst.str()); } while (false)
-#define LOGDD(x) do { std::stringstream sst; sst << x; logDD(sst.str()); } while (false)
+// To avoid "error: there are no arguments to ‘logD’ that depend on a
+// template parameter, so a declaration of ‘logD’ must be available"
+// we use "this->logD()" instead of simply "logD()" below.
+#define LOGD(x) do { std::stringstream sst; sst << x; this->logD(sst.str()); } while (false)
+#define LOGDD(x) do { std::stringstream sst; sst << x; this->logDD(sst.str()); } while (false)
 
 #endif
 
diff --git a/emper/PrivateSemaphore.hpp b/emper/PrivateSemaphore.hpp
index 6d9bcefe22c080b65393d9795fa13aff272a407e..e31175005f82fc95c56c0b9d79ad78a01bf35ede 100644
--- a/emper/PrivateSemaphore.hpp
+++ b/emper/PrivateSemaphore.hpp
@@ -1,43 +1,33 @@
 #pragma once
 
+#include "Blockable.hpp"
 #include "Context.hpp"
 #include "ContextManager.hpp"
 #include "Debug.hpp"
 #include "Runtime.hpp"
 #include "Fiber.hpp"
 
-class PrivateSemaphore : protected Logger<LogSubsystem::PS> {
+class PrivateSemaphore :
+	protected Blockable<LogSubsystem::PS> {
+
 protected:
-	Runtime& runtime;
-	ContextManager& contextManager;
 
 	// cppcheck-suppress uninitMemberVar
-	PrivateSemaphore() : runtime(*Runtime::getRuntime())
-					   , contextManager(runtime.getContextManager())
+	PrivateSemaphore() : Blockable(*Runtime::getRuntime())
 	{
 		LOGD("constructed by fiber " << Dispatcher::getCurrentFiber());
 	}
 
-	void block(func_t freshContextHook) {
-		LOGD("block() blockedContext is " << Context::getCurrentContext());
-		contextManager.saveAndStartNew(freshContextHook);
-	}
-
-	void unblock(Context* context) {
-		assert(context != nullptr);
-		// cppcheck-suppress unsafeClassCanLeak
-		Fiber* unblockFiber = Fiber::from([this, context] {
-				contextManager.discardAndResume(context);
-			});
-		runtime.schedule(*unblockFiber);
-	}
-
 	[[noreturn]] void unblockAndExit(Context* context) {
 		contextManager.discardAndResume(context);
 	}
 
 	virtual Context* signalInternal() = 0;
 
+	virtual void debugLog(const std::string& string) const {
+		Logger::logD(string);
+	}
+
 public:
 
 	virtual void wait() = 0;
diff --git a/emper/UnboundedBlockingMpscQueue.hpp b/emper/UnboundedBlockingMpscQueue.hpp
index 47dd19f6abea0b5c67e1d641cebac7da12d3f963..51e3501ab250bf8e1ab370ec26616e4e08c62c90 100644
--- a/emper/UnboundedBlockingMpscQueue.hpp
+++ b/emper/UnboundedBlockingMpscQueue.hpp
@@ -7,8 +7,8 @@
 #include <mutex>
 
 template<typename T>
-class UnboundedBlockingMpscQueue : protected Logger<LogSubsystem::U_B_MPSC_Q>
-								 , protected Blockable {
+class UnboundedBlockingMpscQueue :
+	public Blockable<LogSubsystem::U_B_MPSC_Q> {
 
 private:
 	std::atomic<Context*> blockedContext = nullptr;
@@ -40,10 +40,6 @@ private:
 		}
 	}
 
-	virtual void logD(const std::string& string) const {
-		Logger::logD(string);
-	}
-
 public:
 
 	UnboundedBlockingMpscQueue(Runtime& runtime) : Blockable(runtime) {