Replace CCriticalSection + CWinThread + Win32 events — std::mutex/thread or Boost
Classification¶
Abandoned by operator decision on 2026-05-21. This historical record preserves the old Boost/POCO analysis only as provenance; do not promote it without a new active item.
Summary¶
15+ files use Win32-specific threading primitives directly (CCriticalSection,
CWinThread, raw HANDLE events). None of the lock/unlock pairs are
exception-safe — an exception between Lock() and Unlock() causes a permanent
deadlock. Two equivalent replacement paths are documented: one using C++17
standard library, one using Boost.Thread.
Current Pain Points¶
| File | Current usage |
|---|---|
srchybrid/EMSocket.h:134 |
CCriticalSection sendLocker; — manual Lock/Unlock |
srchybrid/UDPSocket.h:80 |
CCriticalSection sendLocker; |
srchybrid/UploadBandwidthThrottler.h:68-69 |
Two CCriticalSection members |
srchybrid/UploadQueue.h:37 |
CCriticalSection |
srchybrid/GDIThread.h:23-24 |
HANDLE m_hEventKill; HANDLE m_hEventDead; |
srchybrid/GDIThread.cpp:45-57 |
CreateEvent, WaitForSingleObject, SetEvent, CloseHandle |
srchybrid/PartFileWriteThread.h:64-65 |
CEvent m_eventThreadEnded; CEvent m_eventPaused; |
srchybrid/TLSthreading.cpp:13-44 |
Manual InitializeCriticalSection wrappers |
Current (exception-unsafe) pattern¶
void SetConState(uint8 val) {
sendLocker.Lock(); // if exception thrown below → permanent deadlock
byConnected = val;
sendLocker.Unlock();
}
Option A — C++17 Standard Library (no Boost dependency)¶
Header-only; no new dependencies. Preferred if Boost is not adopted.
#include <mutex>
#include <thread>
#include <condition_variable>
// Replace CCriticalSection
std::mutex sendLocker;
// Replace Lock/Unlock — exception-safe RAII
void SetConState(uint8_t val) {
std::lock_guard<std::mutex> guard(sendLocker);
byConnected = val;
} // unlocks automatically on any exit, including exceptions
// Replace HANDLE events + WaitForSingleObject/SetEvent
std::condition_variable cv;
std::mutex cv_mutex;
bool killFlag = false;
// Waiting thread:
std::unique_lock<std::mutex> lk(cv_mutex);
cv.wait(lk, [] { return killFlag; });
// Signaling thread:
{ std::lock_guard<std::mutex> lk(cv_mutex); killFlag = true; }
cv.notify_one();
// Replace CWinThread
std::thread workerThread([] { /* thread body */ });
workerThread.join();
TLSthreading.cpp replacement:
The 40-line InitializeCriticalSection/EnterCriticalSection/LeaveCriticalSection
wrappers become a single std::mutex member — the entire file can be deleted.
Pros: Zero new dependencies; part of the C++17 standard the project already
uses; same semantics as Boost.Thread.
Cons: std::thread on Windows does not support priority setting or stack
size without platform extensions — if those are needed, keep CWinThread for
those specific threads and replace the rest.
Option B — Boost.Thread¶
Requires Boost dependency (see REF-008).
#include <boost/thread/mutex.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/thread.hpp>
// Replace CCriticalSection
boost::mutex sendLocker;
// Replace Lock/Unlock
void SetConState(uint8_t val) {
boost::lock_guard<boost::mutex> guard(sendLocker);
byConnected = val;
}
// Replace HANDLE events
boost::condition_variable cv;
boost::mutex cv_mutex;
bool killFlag = false;
boost::unique_lock<boost::mutex> lk(cv_mutex);
cv.wait(lk, [] { return killFlag; });
// Replace CWinThread
boost::thread workerThread([] { /* thread body */ });
workerThread.join();
Pros: Additional features (boost::shared_mutex, boost::upgrade_lock,
interruptible threads, thread groups); consistent with Boost.Asio if REF-008
uses Option A.
Cons: Requires Boost; largely redundant with C++17 std for this use case.
Recommendation¶
Use Option A (std::mutex / std::thread) regardless of the Boost decision.
The C++17 standard library provides everything needed here. Reserve CWinThread
only for threads that require platform-specific priority or stack-size control.
Files¶
srchybrid/EMSocket.h/.cppsrchybrid/UDPSocket.h/.cppsrchybrid/UploadBandwidthThrottler.h/.cppsrchybrid/UploadQueue.h/.cppsrchybrid/GDIThread.h/.cppsrchybrid/PartFileWriteThread.h/.cppsrchybrid/TLSthreading.cpp— candidate for deletion
Acceptance Criteria¶
- [ ] No bare
Lock()/Unlock()pairs onCCriticalSectionin the migrated files - [ ] All locks use RAII (
std::lock_guardorstd::unique_lock) - [ ] No raw
HANDLEevent objects replaced bystd::condition_variable - [ ]
TLSthreading.cppeither deleted or reduced to a singlestd::mutex - [ ] Exception thrown inside a critical section no longer causes deadlock
- [ ] Thread join/detach lifecycle explicitly managed