Files
triangles_v5/src/notificationqueue.h
T
sami7777 2ba0ecf428 Cleanup: drop boost::filesystem/thread/chrono, retire dead code
Migration from boost to std-library equivalents and removal of unreachable
code paths. Touches infrastructure only — no consensus rule or wallet
serialization changes.

Dead code removed:
- IRC bootstrap (irc.cpp/h, 417 lines): orphan from pre-Tor era, no callers.
- Alert system (alert.cpp/h + sendalert RPC + Qt UI signal, ~500 lines):
  retired post-V5 fork; old peers' alert messages now hit the unknown-cmd
  default branch, logged + ignored.
- Legacy P2P handlers in main.cpp: "checkpoint" (already a no-op stub since
  V5 fork master-key removal), "checkorder"/"reply" (2010-era Receive-by-IP
  feature), plus their unused supporting structures (CRequestTracker,
  PushRequest overloads, mapRequests/cs_mapRequests, mapReuseKey).
- Unreachable RPCs clearwallettransactions and scanforalltxns (~175 lines):
  defined in rpcwallet.cpp but never registered in the dispatch table.
- Stale -alertnotify CLI help text (option was advertised but never wired).

boost::filesystem -> std::filesystem (C++17):
- 30 source files, 5 headers. namespace fs = boost::filesystem swapped to
  namespace fs = std::filesystem; boost::filesystem::ifstream/ofstream
  replaced with std::ifstream/ofstream (path-aware in C++17);
  fs::system_complete -> fs::absolute; boost::filesystem::filesystem_error
  -> std::filesystem::filesystem_error.
- Build system: dropped Boost::filesystem from link libs and Boost
  components; PCH includes updated.
- Added explicit <filesystem> includes where types were previously
  available only transitively (db.h, rpcblockchain.cpp).

boost::thread -> std::thread (12 files):
- sync.h CCriticalSection/CWaitableCriticalSection now alias
  std::recursive_mutex/std::mutex. boost::unique_lock and
  boost::condition_variable / boost::mutex::scoped_lock swapped to std
  equivalents; sync.cpp boost::thread_specific_ptr -> thread_local
  std::unique_ptr.
- init.cpp boost::thread_group rewritten as std::vector<std::thread> with
  manual join loop. boost::thread::hardware_concurrency ->
  std::thread::hardware_concurrency.
- main.cpp/wallet.cpp -blocknotify/-walletnotify shell-out threads now use
  std::thread(...).detach() — fixes a latent bug where modern boost::thread
  destructor would call std::terminate on the joinable thread.
- util.cpp NewThread now catches std::system_error.
- No interruption_point/interrupt usage anywhere — pure mechanical swap.

boost::chrono / boost::posix_time -> std::chrono (3 of 5 files):
- util.h: MilliSleep, GetTimeMillis, GetTimeMicros rewritten on std::chrono
  (system_clock for epoch math, sleep_for for delays).
- snapshotnet.cpp: sleep_for swapped.
- DoS_tests.cpp: timing harness uses steady_clock.
- Skipped: rpcdump.cpp (boost::posix_time::time_input_facet has no clean
  std::get_time equivalent) and qt/qtipcserver.cpp (locked to
  boost::posix_time by boost::interprocess::message_queue::timed_receive).

Other housekeeping:
- Dropped unnecessary "using namespace boost;" from txdb-leveldb.cpp,
  txdb-rocksdb.cpp, walletdb.cpp, db.cpp (verified no unqualified boost
  names in those TUs).
- Removed unused extern declaration for clearwallettransactions.

Build fixes for non-unity builds on MinGW64/GCC 15:
- net.cpp: dropped stale #include "irc.h".
- addrman.cpp + main.cpp: explicit <cmath> include for sqrt/pow (was
  arriving transitively via boost headers).
- rpcblockchain.cpp + init.cpp: defensive #undef STRICT/ADVISORY/PERMISSIVE
  since windows.h macros collide with the Checkpoints:: enum values when
  std headers reorder include flow.
- tor_embed_hooks.cpp: triangles_tor_check_interrupted now polls fShutdown
  instead of boost::this_thread::interruption_requested (we never used
  boost interruption — the hook was always effectively a no-op).
- snapshotnet.cpp: fs::remove error handle uses std::error_code.
- serialize.h: added <ios> for std::ios::badbit/failbit (was relying on
  transitive include via boost).

Note: unity builds currently fail on this branch due to std::byte (C++17)
colliding with COM 'byte' typedef from shlobj.h when 'using namespace std;'
from earlier files in the unity slice leaks into util.cpp's parse of
shlobj.h. Build with -DENABLE_UNITY_BUILD=OFF (the default).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 15:27:14 -07:00

110 lines
3.1 KiB
C++

// Copyright (c) 2026 The Triangles developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef TRIANGLES_NOTIFICATIONQUEUE_H
#define TRIANGLES_NOTIFICATIONQUEUE_H
#include <string>
#include <deque>
#include <vector>
#include <chrono>
#include <condition_variable>
#include <mutex>
/**
* Thread-safe notification queue for SSE (Server-Sent Events) clients.
*
* Producers (block acceptance, mempool acceptance) push JSON event strings.
* Consumer threads (SSE HTTP handlers) wait on the condition variable and
* drain events as they arrive.
*
* The queue keeps the last MAX_QUEUED_EVENTS events so late-joining clients
* can get a small backlog. Each SSE client tracks its own read position.
*/
class CNotificationQueue
{
private:
mutable std::mutex cs;
std::condition_variable cond;
struct Event {
uint64_t id;
std::string data; // JSON payload
};
std::deque<Event> events;
uint64_t nNextId;
static const size_t MAX_QUEUED_EVENTS = 256;
public:
CNotificationQueue() : nNextId(1) {}
/** Push a new event. Wakes all waiting SSE clients. */
void Push(const std::string& strData)
{
std::unique_lock<std::mutex> lock(cs);
events.push_back(Event{nNextId++, strData});
while (events.size() > MAX_QUEUED_EVENTS)
events.pop_front();
cond.notify_all();
}
/**
* Wait for events newer than nLastId.
* Returns new events and updates nLastId to the newest seen.
* Returns false if timed out with no new events, true if events were returned.
* Also returns false if fShutdown becomes true.
*/
bool WaitForEvents(uint64_t& nLastId, std::vector<std::string>& vEvents, int nTimeoutMs, const volatile bool& fShutdown)
{
vEvents.clear();
std::unique_lock<std::mutex> lock(cs);
// Check for events already in the queue past our read position
bool fHasNew = false;
for (std::deque<Event>::const_iterator it = events.begin(); it != events.end(); ++it)
{
if (it->id > nLastId)
{
fHasNew = true;
break;
}
}
if (!fHasNew)
{
// Wait for new events or timeout
cond.wait_for(lock, std::chrono::milliseconds(nTimeoutMs));
}
// Drain all events newer than nLastId
for (std::deque<Event>::const_iterator it = events.begin(); it != events.end(); ++it)
{
if (it->id > nLastId)
{
vEvents.push_back(it->data);
nLastId = it->id;
}
}
if (fShutdown)
return false;
return !vEvents.empty();
}
/** Get the current latest event ID (for clients that want to skip history). */
uint64_t GetLatestId() const
{
std::unique_lock<std::mutex> lock(cs);
return nNextId - 1;
}
};
/** Global notification queue instance */
extern CNotificationQueue* pNotificationQueue;
#endif // TRIANGLES_NOTIFICATIONQUEUE_H