Mercurial > hg > orthanc-stone
diff UnitTestsSources/TestMessageBroker2.cpp @ 300:b4abaeb783b1 am-callable-and-promise
messaging refactoring almost complete: works fine in native
author | am@osimis.io |
---|---|
date | Tue, 18 Sep 2018 15:23:21 +0200 |
parents | 3897f9f28cfa |
children | 4a79193ffb58 |
line wrap: on
line diff
--- a/UnitTestsSources/TestMessageBroker2.cpp Fri Sep 14 16:44:01 2018 +0200 +++ b/UnitTestsSources/TestMessageBroker2.cpp Tue Sep 18 15:23:21 2018 +0200 @@ -22,296 +22,291 @@ #include "gtest/gtest.h" #include "Framework/Messages/MessageBroker.h" +#include "Framework/Messages/Promise.h" +#include "Framework/Messages/IObservable.h" +#include "Framework/Messages/IObserver.h" +#include "Framework/Messages/MessageForwarder.h" -#include <boost/noncopyable.hpp> -#include <boost/function.hpp> -#include <boost/bind.hpp> - -#include <string> -#include <map> -#include <set> int testCounter = 0; namespace { - class IObserver; - class IObservable; - class Promise; +// class IObserver; +// class IObservable; +// class Promise; - enum MessageType - { - MessageType_Test1, - MessageType_Test2, +// enum MessageType +// { +// MessageType_Test1, +// MessageType_Test2, - MessageType_CustomMessage, - MessageType_LastGenericStoneMessage - }; +// MessageType_CustomMessage, +// MessageType_LastGenericStoneMessage +// }; - struct IMessage : public boost::noncopyable - { - MessageType messageType_; - public: - IMessage(const MessageType& messageType) - : messageType_(messageType) - {} - virtual ~IMessage() {} +// struct IMessage : public boost::noncopyable +// { +// MessageType messageType_; +// public: +// IMessage(const MessageType& messageType) +// : messageType_(messageType) +// {} +// virtual ~IMessage() {} - virtual int GetType() const {return messageType_;} - }; +// virtual int GetType() const {return messageType_;} +// }; - struct ICustomMessage : public IMessage - { - int customMessageType_; - public: - ICustomMessage(int customMessageType) - : IMessage(MessageType_CustomMessage), - customMessageType_(customMessageType) - {} - virtual ~ICustomMessage() {} +// struct ICustomMessage : public IMessage +// { +// int customMessageType_; +// public: +// ICustomMessage(int customMessageType) +// : IMessage(MessageType_CustomMessage), +// customMessageType_(customMessageType) +// {} +// virtual ~ICustomMessage() {} - virtual int GetType() const {return customMessageType_;} - }; +// virtual int GetType() const {return customMessageType_;} +// }; - // This is referencing an object and member function that can be notified - // by an IObservable. The object must derive from IO - // The member functions must be of type "void Function(const IMessage& message)" or reference a derived class of IMessage - class ICallable : public boost::noncopyable - { - public: - virtual ~ICallable() - { - } +// // This is referencing an object and member function that can be notified +// // by an IObservable. The object must derive from IO +// // The member functions must be of type "void Function(const IMessage& message)" or reference a derived class of IMessage +// class ICallable : public boost::noncopyable +// { +// public: +// virtual ~ICallable() +// { +// } - virtual void Apply(const IMessage& message) = 0; +// virtual void Apply(const IMessage& message) = 0; - virtual MessageType GetMessageType() const = 0; - virtual IObserver* GetObserver() const = 0; - }; +// virtual MessageType GetMessageType() const = 0; +// virtual IObserver* GetObserver() const = 0; +// }; - template <typename TObserver, - typename TMessage> - class Callable : public ICallable - { - private: - typedef void (TObserver::* MemberFunction) (const TMessage&); +// template <typename TObserver, +// typename TMessage> +// class Callable : public ICallable +// { +// private: +// typedef void (TObserver::* MemberFunction) (const TMessage&); - TObserver& observer_; - MemberFunction function_; +// TObserver& observer_; +// MemberFunction function_; - public: - Callable(TObserver& observer, - MemberFunction function) : - observer_(observer), - function_(function) - { - } +// public: +// Callable(TObserver& observer, +// MemberFunction function) : +// observer_(observer), +// function_(function) +// { +// } - void ApplyInternal(const TMessage& message) - { - (observer_.*function_) (message); - } +// void ApplyInternal(const TMessage& message) +// { +// (observer_.*function_) (message); +// } - virtual void Apply(const IMessage& message) - { - ApplyInternal(dynamic_cast<const TMessage&>(message)); - } +// virtual void Apply(const IMessage& message) +// { +// ApplyInternal(dynamic_cast<const TMessage&>(message)); +// } - virtual MessageType GetMessageType() const - { - return static_cast<MessageType>(TMessage::Type); - } +// virtual MessageType GetMessageType() const +// { +// return static_cast<MessageType>(TMessage::Type); +// } - virtual IObserver* GetObserver() const - { - return &observer_; - } - }; +// virtual IObserver* GetObserver() const +// { +// return &observer_; +// } +// }; - /* - * This is a central message broker. It keeps track of all observers and knows - * when an observer is deleted. - * This way, it can prevent an observable to send a message to a delete observer. - */ - class MessageBroker : public boost::noncopyable - { +// /* +// * This is a central message broker. It keeps track of all observers and knows +// * when an observer is deleted. +// * This way, it can prevent an observable to send a message to a delete observer. +// */ +// class MessageBroker : public boost::noncopyable +// { - std::set<IObserver*> activeObservers_; // the list of observers that are currently alive (that have not been deleted) +// std::set<IObserver*> activeObservers_; // the list of observers that are currently alive (that have not been deleted) - public: +// public: - void Register(IObserver& observer) - { - activeObservers_.insert(&observer); - } +// void Register(IObserver& observer) +// { +// activeObservers_.insert(&observer); +// } - void Unregister(IObserver& observer) - { - activeObservers_.erase(&observer); - } +// void Unregister(IObserver& observer) +// { +// activeObservers_.erase(&observer); +// } - bool IsActive(IObserver* observer) - { - return activeObservers_.find(observer) != activeObservers_.end(); - } - }; +// bool IsActive(IObserver* observer) +// { +// return activeObservers_.find(observer) != activeObservers_.end(); +// } +// }; - class Promise : public boost::noncopyable - { - protected: - MessageBroker& broker_; +// class Promise : public boost::noncopyable +// { +// protected: +// MessageBroker& broker_; - ICallable* successCallable_; - ICallable* failureCallable_; +// ICallable* successCallable_; +// ICallable* failureCallable_; - public: - Promise(MessageBroker& broker) - : broker_(broker), - successCallable_(NULL), - failureCallable_(NULL) - { - } +// public: +// Promise(MessageBroker& broker) +// : broker_(broker), +// successCallable_(NULL), +// failureCallable_(NULL) +// { +// } - void Success(const IMessage& message) - { - // check the target is still alive in the broker - if (broker_.IsActive(successCallable_->GetObserver())) - { - successCallable_->Apply(message); - } - } +// void Success(const IMessage& message) +// { +// // check the target is still alive in the broker +// if (broker_.IsActive(successCallable_->GetObserver())) +// { +// successCallable_->Apply(message); +// } +// } - void Failure(const IMessage& message) - { - // check the target is still alive in the broker - if (broker_.IsActive(failureCallable_->GetObserver())) - { - failureCallable_->Apply(message); - } - } +// void Failure(const IMessage& message) +// { +// // check the target is still alive in the broker +// if (broker_.IsActive(failureCallable_->GetObserver())) +// { +// failureCallable_->Apply(message); +// } +// } - Promise& Then(ICallable* successCallable) - { - if (successCallable_ != NULL) - { - // TODO: throw throw new "Promise may only have a single success target" - } - successCallable_ = successCallable; - return *this; - } +// Promise& Then(ICallable* successCallable) +// { +// if (successCallable_ != NULL) +// { +// // TODO: throw throw new "Promise may only have a single success target" +// } +// successCallable_ = successCallable; +// return *this; +// } - Promise& Else(ICallable* failureCallable) - { - if (failureCallable_ != NULL) - { - // TODO: throw throw new "Promise may only have a single failure target" - } - failureCallable_ = failureCallable; - return *this; - } +// Promise& Else(ICallable* failureCallable) +// { +// if (failureCallable_ != NULL) +// { +// // TODO: throw throw new "Promise may only have a single failure target" +// } +// failureCallable_ = failureCallable; +// return *this; +// } - }; +// }; - class IObserver : public boost::noncopyable - { - protected: - MessageBroker& broker_; +// class IObserver : public boost::noncopyable +// { +// protected: +// MessageBroker& broker_; - public: - IObserver(MessageBroker& broker) - : broker_(broker) - { - broker_.Register(*this); - } +// public: +// IObserver(MessageBroker& broker) +// : broker_(broker) +// { +// broker_.Register(*this); +// } - virtual ~IObserver() - { - broker_.Unregister(*this); - } +// virtual ~IObserver() +// { +// broker_.Unregister(*this); +// } - }; +// }; - class IObservable : public boost::noncopyable - { - protected: - MessageBroker& broker_; +// class IObservable : public boost::noncopyable +// { +// protected: +// MessageBroker& broker_; - typedef std::map<int, std::set<ICallable*> > Callables; - Callables callables_; - public: +// typedef std::map<int, std::set<ICallable*> > Callables; +// Callables callables_; +// public: - IObservable(MessageBroker& broker) - : broker_(broker) - { - } +// IObservable(MessageBroker& broker) +// : broker_(broker) +// { +// } - virtual ~IObservable() - { - for (Callables::const_iterator it = callables_.begin(); - it != callables_.end(); ++it) - { - for (std::set<ICallable*>::const_iterator - it2 = it->second.begin(); it2 != it->second.end(); ++it2) - { - delete *it2; - } - } - } +// virtual ~IObservable() +// { +// for (Callables::const_iterator it = callables_.begin(); +// it != callables_.end(); ++it) +// { +// for (std::set<ICallable*>::const_iterator +// it2 = it->second.begin(); it2 != it->second.end(); ++it2) +// { +// delete *it2; +// } +// } +// } - void Register(ICallable* callable) - { - MessageType messageType = callable->GetMessageType(); +// void Register(ICallable* callable) +// { +// MessageType messageType = callable->GetMessageType(); - callables_[messageType].insert(callable); - } +// callables_[messageType].insert(callable); +// } - void EmitMessage(const IMessage& message) - { - Callables::const_iterator found = callables_.find(message.GetType()); +// void EmitMessage(const IMessage& message) +// { +// Callables::const_iterator found = callables_.find(message.GetType()); - if (found != callables_.end()) - { - for (std::set<ICallable*>::const_iterator - it = found->second.begin(); it != found->second.end(); ++it) - { - if (broker_.IsActive((*it)->GetObserver())) - { - (*it)->Apply(message); - } - } - } - } +// if (found != callables_.end()) +// { +// for (std::set<ICallable*>::const_iterator +// it = found->second.begin(); it != found->second.end(); ++it) +// { +// if (broker_.IsActive((*it)->GetObserver())) +// { +// (*it)->Apply(message); +// } +// } +// } +// } - }; +// }; - enum CustomMessageType - { - CustomMessageType_First = MessageType_LastGenericStoneMessage + 1, +// enum CustomMessageType +// { +// CustomMessageType_First = MessageType_LastGenericStoneMessage + 1, - CustomMessageType_Completed, - CustomMessageType_Increment - }; +// CustomMessageType_Completed, +// CustomMessageType_Increment +// }; + + using namespace OrthancStone; class MyObservable : public IObservable { public: - struct MyCustomMessage: public ICustomMessage + struct MyCustomMessage: public BaseMessage<MessageType_Test1> { int payload_; - enum - { - Type = CustomMessageType_Completed - }; MyCustomMessage(int payload) - : ICustomMessage(Type), + : BaseMessage(), payload_(payload) {} }; @@ -337,20 +332,30 @@ }; + class MyIntermediate : public IObserver, public IObservable + { + IObservable& observedObject_; + public: + MyIntermediate(MessageBroker& broker, IObservable& observedObject) + : IObserver(broker), + IObservable(broker), + observedObject_(observedObject) + { + observedObject_.RegisterObserverCallback(new MessageForwarder<MyObservable::MyCustomMessage>(broker, *this)); + } + }; + + class MyPromiseSource : public IObservable { Promise* currentPromise_; public: - struct MyPromiseMessage: public ICustomMessage + struct MyPromiseMessage: public BaseMessage<MessageType_Test1> { int increment; - enum - { - Type = CustomMessageType_Increment - }; MyPromiseMessage(int increment) - : ICustomMessage(Type), + : BaseMessage(), increment(increment) {} }; @@ -407,7 +412,7 @@ MyObserver observer(broker); // create a permanent connection between an observable and an observer - observable.Register(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage)); + observable.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage)); testCounter = 0; observable.EmitMessage(MyObservable::MyCustomMessage(12)); @@ -426,7 +431,7 @@ MyObserver* observer = new MyObserver(broker); // create a permanent connection between an observable and an observer - observable.Register(new Callable<MyObserver, MyObservable::MyCustomMessage>(*observer, &MyObserver::HandleCompletedMessage)); + observable.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(*observer, &MyObserver::HandleCompletedMessage)); testCounter = 0; observable.EmitMessage(MyObservable::MyCustomMessage(12)); @@ -441,6 +446,27 @@ ASSERT_EQ(0, testCounter); } +TEST(MessageBroker2, TestMessageForwarderSimpleUseCase) +{ + MessageBroker broker; + MyObservable observable(broker); + MyIntermediate intermediate(broker, observable); + MyObserver observer(broker); + + // let the observer observers the intermediate that is actually forwarding the messages from the observable + intermediate.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage)); + + testCounter = 0; + observable.EmitMessage(MyObservable::MyCustomMessage(12)); + ASSERT_EQ(12, testCounter); + + // the connection is permanent; if we emit the same message again, the observer will be notified again + testCounter = 0; + observable.EmitMessage(MyObservable::MyCustomMessage(20)); + ASSERT_EQ(20, testCounter); +} + + TEST(MessageBroker2, TestPromiseSuccessFailure) { @@ -496,196 +522,3 @@ ASSERT_EQ(0, testCounter); } - - -//#include <stdio.h> -//#include <boost/noncopyable.hpp> - -//#include <string> -//#include <memory> -//#include <map> -//#include <set> - -//enum MessageType -//{ -// MessageType_SeriesDownloaded = 1 -//}; - - -//class IMessage : public boost::noncopyable -//{ -//private: -// MessageType type_; - -//public: -// IMessage(MessageType type) : -// type_(type) -// { -// } - -// virtual ~IMessage() -// { -// } - -// MessageType GetMessageType() const -// { -// return type_; -// } -//}; - - -//class IObserver : public boost::noncopyable -//{ -//public: -// virtual ~IObserver() -// { -// } -//}; - - -//class SeriesDownloadedMessage : public IMessage -//{ -//private: -// std::string value_; - -//public: -// enum -// { -// Type = MessageType_SeriesDownloaded -// }; - -// SeriesDownloadedMessage(const std::string& value) : -// IMessage(static_cast<MessageType>(Type)), -// value_(value) -// { -// } - -// const std::string& GetValue() const -// { -// return value_; -// } -//}; - - -//class MyObserver : public IObserver -//{ -//public: -// void OnSeriesDownloaded(const SeriesDownloadedMessage& message) -// { -// printf("received: [%s]\n", message.GetValue().c_str()); -// } -//}; - - - -//class ICallable : public boost::noncopyable // ne peut referencer que les classes de base -//{ -//public: -// virtual ~ICallable() -// { -// } - -// virtual void Apply(const IMessage& message) = 0; - -// virtual MessageType GetMessageType() const = 0; -//}; - - - -//template <typename Observer, -// typename Message> -//class Callable : public ICallable -//{ -//private: -// typedef void (Observer::* MemberFunction) (const Message&); - -// Observer& observer_; -// MemberFunction function_; - -//public: -// Callable(Observer& observer, -// MemberFunction function) : -// observer_(observer), -// function_(function) -// { -// } - -// void ApplyInternal(const Message& message) -// { -// (observer_.*function_) (message); -// } - -// virtual void Apply(const IMessage& message) -// { -// ApplyInternal(dynamic_cast<const Message&>(message)); -// } - -// virtual MessageType GetMessageType() const -// { -// return static_cast<MessageType>(Message::Type); -// } -//}; - - - -//class IObservable : public boost::noncopyable -//{ -//private: -// typedef std::map<MessageType, std::set<ICallable*> > Callables; - -// Callables callables_; - -//public: -// virtual ~IObservable() -// { -// for (Callables::const_iterator it = callables_.begin(); -// it != callables_.end(); ++it) -// { -// for (std::set<ICallable*>::const_iterator -// it2 = it->second.begin(); it2 != it->second.end(); ++it2) -// { -// delete *it2; -// } -// } -// } - -// void Register(ICallable* callable) -// { -// MessageType type = callable->GetMessageType(); - -// callables_[type].insert(callable); -// } - -// void Emit(const IMessage& message) const -// { -// Callables::const_iterator found = callables_.find(message.GetMessageType()); - -// if (found != callables_.end()) -// { -// for (std::set<ICallable*>::const_iterator -// it = found->second.begin(); it != found->second.end(); ++it) -// { -// (*it)->Apply(message); -// } -// } -// } -//}; - - - - -//int main() -//{ -// MyObserver observer; - -// SeriesDownloadedMessage message("coucou"); - -// IObservable observable; -// observable.Register(new Callable<MyObserver, SeriesDownloadedMessage>(observer, &MyObserver::OnSeriesDownloaded)); -// observable.Register(new Callable<MyObserver, SeriesDownloadedMessage>(observer, &MyObserver::OnSeriesDownloaded)); - -// SeriesDownloadedMessage message2("hello"); -// observable.Emit(message2); - -// printf("%d\n", SeriesDownloadedMessage::Type); -//}