Skip to content

Instantly share code, notes, and snippets.

@mmj-the-fighter
Last active December 26, 2024 14:35
Show Gist options
  • Save mmj-the-fighter/52b1b3ca0a15aee1bf96bcebd37184e3 to your computer and use it in GitHub Desktop.
Save mmj-the-fighter/52b1b3ca0a15aee1bf96bcebd37184e3 to your computer and use it in GitHub Desktop.
#include <string>
#include <map>
#include <functional>
#include <vector>
#include <iostream>
#include <set>
#include <algorithm>
using Message = std::string;
using Topic = std::string;
using Client = std::string;
using Callback = std::function<void(Message&)>;
using ClientCallbackSetMap = std::map<Client, std::vector<Callback>>;
using TopicSubscriberInfoMap = std::map<Topic, ClientCallbackSetMap>;
class MessageDispatcher
{
TopicSubscriberInfoMap topicSubscriberInfoMap;
public:
void Subscribe(Topic topic, Client client, Callback callback) {
topicSubscriberInfoMap[topic][client].push_back(callback);
}
void Unsubscribe(const Topic& topic, const Client& client, const Callback& callback) {
if (topicSubscriberInfoMap.count(topic) && topicSubscriberInfoMap[topic].count(client)) {
auto& clientCallbacks = topicSubscriberInfoMap[topic][client];
auto it = std::find_if(clientCallbacks.begin(), clientCallbacks.end(),
[&callback](const Callback& cb) {
return cb.target<void(Message&)>() == callback.target<void(Message&)>();
}
);
if (it != clientCallbacks.end()) {
clientCallbacks.erase(it);
}
if (topicSubscriberInfoMap[topic][client].empty()) {
topicSubscriberInfoMap[topic].erase(client);
if (topicSubscriberInfoMap[topic].empty()) {
topicSubscriberInfoMap.erase(topic);
}
}
}
}
void BroadCast(const Topic& topic, const Message& message) {
auto it = topicSubscriberInfoMap.find(topic);
if (it != topicSubscriberInfoMap.end()) {
const auto& callbackMap = it->second;
for (const auto& clientCallbackSetPair : callbackMap) {
for (const auto& callback : clientCallbackSetPair.second) {
Message mutableMessage = message;
callback(mutableMessage);
}
}
}
}
void MultiCast(const Topic& topic, const Message& message, const std::set<Client> targetClients) {
auto it = topicSubscriberInfoMap.find(topic);
if (it != topicSubscriberInfoMap.end()) {
const auto& callbackMap = it->second;
for (const auto& clientCallbackSetPair : callbackMap) {
Client client = clientCallbackSetPair.first;
if (targetClients.find(client) == targetClients.end()) {
continue;
}
for (const auto& callback : clientCallbackSetPair.second) {
Message mutableMessage = message;
callback(mutableMessage);
}
}
}
}
void Send(const Topic& topic, const Message& message, const Client& client) {
auto it = topicSubscriberInfoMap.find(topic);
if (it != topicSubscriberInfoMap.end()) {
const auto& callbackMap = it->second;
auto it2 = callbackMap.find(client);
if (it2 != callbackMap.end()) {
for (const auto& callback : it2->second) {
Message mutableMessage = message;
callback(mutableMessage);
}
}
}
}
};
void client1_on_greetings(Message& message) {
std::cout << "@Client1 received:" << message << "\n";
}
void client2_on_greetings(Message& message) {
std::cout << "@Client2 received:" << message << "\n";
}
void client3_on_greetings(Message& message) {
std::cout << "@Client3 received:" << message << "\n";
}
void client4_on_greetings(Message& message) {
std::cout << "@Client4 received:" << message << "\n";
}
void client5_on_greetings(Message& message) {
std::cout << "@Client5 received:" << message << "\n";
}
int main(int argc, char* argv[]) {
MessageDispatcher pmd;
//register as event subscriber
pmd.Subscribe("/greetings", "Client1", client1_on_greetings);
pmd.Subscribe("/greetings", "Client2", client2_on_greetings);
pmd.Subscribe("/greetings", "Client3", client3_on_greetings);
pmd.Subscribe("/greetings", "Client4", client4_on_greetings);
pmd.Subscribe("/greetings", "Client5", client5_on_greetings);
//unregister an event
pmd.Unsubscribe("/greetings", "Client2", client2_on_greetings);
//fire an event
std::cout << "Event Brodcasting" << "\n";
pmd.BroadCast("/greetings", "hi");
std::cout << "\n";
std::cout <<"Sending Event to a particular subscriber" << "\n";
pmd.Send("/greetings", "hola", "Client1");
std::cout << "\n";
std::cout << "Sending Event to a subset of subscribers" << "\n";
pmd.MultiCast("/greetings", "namaste", { "Client3", "Client5"});
std::cout << "\n";
}
/* output:
Event Brodcasting
@Client1 received:hi
@Client3 received:hi
@Client4 received:hi
@Client5 received:hi
Sending Event to a particular subscriber
@Client1 received:hola
Sending Event to a subset of subscribers
@Client3 received:namaste
@Client5 received:namaste
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment