Skip to content

Commit 9aaeec3

Browse files
committed
proxy-io.h: Add EventLoopRef RAII class handle addClient/removeClient refcounting
1 parent f58c8d8 commit 9aaeec3

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

include/mp/proxy-io.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ class EventLoop
190190
//! other IPC calls.
191191
void startAsyncThread(std::unique_lock<std::mutex>& lock);
192192

193-
//! Add/remove remote client reference counts.
193+
//! Add/remove remote client reference counts. Can use EventLoopRef
194+
//! below to avoid calling these directly.
194195
void addClient(std::unique_lock<std::mutex>& lock);
195196
bool removeClient(std::unique_lock<std::mutex>& lock);
196197
//! Check if loop should exit.

include/mp/proxy.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <mp/util.h>
99

1010
#include <array>
11+
#include <cassert>
1112
#include <functional>
1213
#include <list>
1314
#include <stddef.h>
@@ -47,6 +48,26 @@ inline void CleanupRun(CleanupList& fns) {
4748
}
4849
}
4950

51+
//! Event loop smart pointer automatically calling addClient and removeClient.
52+
//! If a lock pointer argument is passed, the specified lock will be used,
53+
//! otherwise EventLoop::m_mutex will be locked when needed.
54+
class EventLoopRef
55+
{
56+
public:
57+
explicit EventLoopRef(EventLoop& loop, std::unique_lock<std::mutex>* lock = nullptr);
58+
EventLoopRef(EventLoopRef&& other) noexcept : m_loop(other.m_loop) { other.m_loop = nullptr; }
59+
EventLoopRef(const EventLoopRef&) = delete;
60+
EventLoopRef& operator=(const EventLoopRef&) = delete;
61+
EventLoopRef& operator=(EventLoopRef&&) = delete;
62+
~EventLoopRef() { reset(); }
63+
EventLoop& operator*() const { assert(m_loop); return *m_loop; }
64+
EventLoop* operator->() const { assert(m_loop); return m_loop; }
65+
bool reset();
66+
67+
EventLoop* m_loop{nullptr};
68+
std::unique_lock<std::mutex>* m_lock{nullptr};
69+
};
70+
5071
//! Context data associated with proxy client and server classes.
5172
struct ProxyContext
5273
{

include/mp/util.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <tuple>
1919
#include <type_traits>
2020
#include <utility>
21+
#include <variant>
2122
#include <vector>
2223

2324
namespace mp {
@@ -130,6 +131,20 @@ const char* TypeName()
130131
return short_name ? short_name + 1 : display_name;
131132
}
132133

134+
//! Convenient wrapper around std::variant<T*, T>
135+
template <typename T>
136+
struct PtrOrValue {
137+
std::variant<T*, T> data;
138+
139+
template <typename... Args>
140+
PtrOrValue(T* ptr, Args&&... args) : data(ptr ? ptr : std::variant<T*, T>{std::in_place_type<T>, std::forward<Args>(args)...}) {}
141+
142+
T& operator*() { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }
143+
T* operator->() { return &**this; }
144+
T& operator*() const { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }
145+
T* operator->() const { return &**this; }
146+
};
147+
133148
//! Analog to std::lock_guard that unlocks instead of locks.
134149
template <typename Lock>
135150
struct UnlockGuard

src/mp/proxy.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,23 @@ void LoggingErrorHandler::taskFailed(kj::Exception&& exception)
4848
m_loop.log() << "Uncaught exception in daemonized task.";
4949
}
5050

51+
EventLoopRef::EventLoopRef(EventLoop& loop, std::unique_lock<std::mutex>* lock) : m_loop(&loop), m_lock(lock)
52+
{
53+
auto loop_lock{PtrOrValue{m_lock, m_loop->m_mutex}};
54+
m_loop->addClient(*loop_lock);
55+
}
56+
57+
bool EventLoopRef::reset()
58+
{
59+
bool done = false;
60+
if (auto* loop{m_loop}) {
61+
m_loop = nullptr;
62+
auto loop_lock{PtrOrValue{m_lock, loop->m_mutex}};
63+
done = loop->removeClient(*loop_lock);
64+
}
65+
return done;
66+
}
67+
5168
Connection::~Connection()
5269
{
5370
// Shut down RPC system first, since this will garbage collect Server

0 commit comments

Comments
 (0)