Skip to content

Instantly share code, notes, and snippets.

@kyle-go
Last active December 14, 2015 01:08
Show Gist options
  • Save kyle-go/5003400 to your computer and use it in GitHub Desktop.
Save kyle-go/5003400 to your computer and use it in GitHub Desktop.
/*!
dispatch message.
copy from https://github.com/chenshuo/recipes/blob/master/protobuf/dispatcher.cc
*/
#include <map>
#include <assert.h>
#include <iostream>
#include <functional>
class Message
{
public:
virtual int GetDescriptor()
{
//0 for default message.
return 0;
}
};
class Callback
{
public:
virtual ~Callback() {}
virtual void onMessage(Message* message) const = 0;
};
template <typename T>
class CallbackT : public Callback
{
public:
typedef std::function<void (T* message)> MessageCallback;
CallbackT(const MessageCallback& callback)
: callback_(callback)
{}
virtual void onMessage(Message* message) const
{
T* t = static_cast<T*>(message);
assert(t);
callback_(t);
}
private:
MessageCallback callback_;
};
void discardMessage(Message* message)
{
std::cout << "Discarding " << message->GetDescriptor() << std::endl;
}
class Dispatcher
{
public:
Dispatcher()
: defaultCallback_(discardMessage)
{}
void onMessage(Message* message) const
{
CallbackMap::const_iterator it = callbacks_.find(message->GetDescriptor());
if (it != callbacks_.end()) {
it->second->onMessage(message);
} else {
defaultCallback_(message);
}
}
template<typename T>
void registerMessageCallback(const typename CallbackT<T>::MessageCallback& callback)
{
typename std::shared_ptr<CallbackT<T>> pd(new CallbackT<T>(callback));
//T must support no param constructor.
callbacks_[T().GetDescriptor()] = pd;
}
typedef std::map<int, std::shared_ptr<Callback>> CallbackMap;
CallbackMap callbacks_;
std::function<void (Message* message)> defaultCallback_;
};
//
// test
//
class Query : public Message
{
public:
virtual int GetDescriptor()
{
//1 for query messager
return 1;
}
//some data
char x_;
};
class Answer : public Message
{
public:
virtual int GetDescriptor()
{
//2 for answer messager
return 2;
}
//some data
char x_;
};
void onQuery(Query* query)
{
std::cout << "onQuery: " << query->GetDescriptor() << std::endl;
}
void onAnswer(Answer* answer)
{
std::cout << "onAnswer: " << answer->GetDescriptor() << std::endl;
}
int main()
{
Dispatcher dispatcher;
dispatcher.registerMessageCallback<Query>(onQuery);
dispatcher.registerMessageCallback<Answer>(onAnswer);
Query q;
Answer a;
Message m;
dispatcher.onMessage(&q);
dispatcher.onMessage(&a);
dispatcher.onMessage(&m);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment