Add simple message buffer and dispatcher

This commit is contained in:
WarmUpTill 2024-01-30 21:20:50 +01:00 committed by WarmUpTill
parent 06fef08f56
commit 394e2500e8
3 changed files with 94 additions and 0 deletions

View File

@ -166,6 +166,8 @@ target_sources(
lib/utils/log-helper.hpp
lib/utils/math-helpers.cpp
lib/utils/math-helpers.hpp
lib/utils/message-buffer.hpp
lib/utils/message-dispatcher.hpp
lib/utils/mouse-wheel-guard.cpp
lib/utils/mouse-wheel-guard.hpp
lib/utils/name-dialog.cpp

View File

@ -0,0 +1,42 @@
#pragma once
#include <deque>
#include <mutex>
#include <optional>
namespace advss {
template<class T> class MessageBuffer {
public:
bool Empty();
void AppendMessage(const T &);
std::optional<T> ConsumeMessage();
private:
std::deque<T> _buffer;
std::mutex _mutex;
};
template<class T> inline bool MessageBuffer<T>::Empty()
{
std::lock_guard<std::mutex> lock(_mutex);
return _buffer.empty();
}
template<class T> inline void MessageBuffer<T>::AppendMessage(const T &message)
{
std::lock_guard<std::mutex> lock(_mutex);
_buffer.emplace_back(message);
}
template<class T> inline std::optional<T> MessageBuffer<T>::ConsumeMessage()
{
std::lock_guard<std::mutex> lock(_mutex);
if (_buffer.empty()) {
return {};
}
T message = _buffer.at(0);
_buffer.pop_front();
return message;
}
} // namespace advss

View File

@ -0,0 +1,50 @@
#pragma once
#include "message-buffer.hpp"
#include <algorithm>
#include <memory>
#include <vector>
namespace advss {
template<class T> class MessageDispatcher {
public:
[[nodiscard]] std::shared_ptr<MessageBuffer<T>> RegisterClient();
void DispatchMessage(const T &message);
private:
std::vector<std::weak_ptr<MessageBuffer<T>>> _clients;
std::mutex _mutex;
};
template<class T>
inline std::shared_ptr<MessageBuffer<T>> MessageDispatcher<T>::RegisterClient()
{
std::lock_guard<std::mutex> lock(_mutex);
// Clear expired client buffers
auto isExpired = [](const std::weak_ptr<MessageBuffer<T>> &ptr) {
return ptr.expired();
};
_clients.erase(std::remove_if(_clients.begin(), _clients.end(),
isExpired),
_clients.end());
// Prepare new buffer for client
auto buffer = std::make_shared<MessageBuffer<T>>();
_clients.emplace_back(buffer);
return buffer;
}
template<class T>
inline void MessageDispatcher<T>::DispatchMessage(const T &message)
{
std::lock_guard<std::mutex> lock(_mutex);
for (auto &client_ : _clients) {
auto client = client_.lock();
if (!client) {
continue;
}
client->AppendMessage(message);
}
}
} // namespace advss