Skip to content

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 / .cpp
  • srchybrid/UDPSocket.h / .cpp
  • srchybrid/UploadBandwidthThrottler.h / .cpp
  • srchybrid/UploadQueue.h / .cpp
  • srchybrid/GDIThread.h / .cpp
  • srchybrid/PartFileWriteThread.h / .cpp
  • srchybrid/TLSthreading.cpp — candidate for deletion

Acceptance Criteria

  • [ ] No bare Lock()/Unlock() pairs on CCriticalSection in the migrated files
  • [ ] All locks use RAII (std::lock_guard or std::unique_lock)
  • [ ] No raw HANDLE event objects replaced by std::condition_variable
  • [ ] TLSthreading.cpp either deleted or reduced to a single std::mutex
  • [ ] Exception thrown inside a critical section no longer causes deadlock
  • [ ] Thread join/detach lifecycle explicitly managed