Permalink
Browse files

* Signals are now regular attributes.

* Serialization of signal/slot connections.
  • Loading branch information...
1 parent d175277 commit 71591c9ad3ad6f58e3bf174d79c68c68d0ea7a03 @simonask committed May 11, 2012
Showing with 131 additions and 45 deletions.
  1. +2 −3 reflect.hpp
  2. +16 −0 signal.cpp
  3. +80 −42 signal.hpp
  4. +33 −0 struct_type.hpp
View
@@ -33,8 +33,7 @@ struct StructTypeBuilder {
template <typename... Args>
Self& signal(Signal<Args...> T::* member, std::string name, std::string description) {
- signals_.push_back(new SignalAttribute<T, Args...>(std::move(name), std::move(description), member));
- return *this;
+ return property(member, name, description);
}
template <typename R, typename... Args>
@@ -50,6 +49,7 @@ struct StructTypeBuilder {
StructType<T> type(super_, std::move(name_), std::move(description_));
type.set_abstract(is_abstract_);
type.set_properties(std::move(attributes_));
+ type.set_slots(std::move(slots_));
return type;
}
@@ -58,7 +58,6 @@ struct StructTypeBuilder {
std::string name_;
std::string description_;
std::vector<AttributeForObject<T>*> attributes_;
- std::vector<SignalForObject<T>*> signals_;
std::vector<SlotForObject<T>*> slots_;
};
View
@@ -0,0 +1,16 @@
+#include "signal.hpp"
+#include "struct_type.hpp"
+#include <sstream>
+
+std::string SignalTypeBase::build_signal_name(const std::vector<const Type*>& signature) {
+ std::stringstream ss;
+ ss << "Signal<";
+ for (size_t i = 0; i < signature.size(); ++i) {
+ ss << signature[i]->name();
+ if (i+1 != signature.size()) {
+ ss << ", ";
+ }
+ }
+ ss << ">";
+ return ss.str();
+}
View
@@ -3,12 +3,26 @@
#define SIGNAL_HPP_IVWSWZJM
#include "basic.hpp"
+#include "type.hpp"
+#include "objectptr.hpp"
#include <vector>
#include <functional>
#include <sstream>
+struct SlotAttributeBase;
+struct Object;
+struct StructTypeBase;
+
+struct SignalTypeBase;
+template <typename... Args> struct SignalType;
+
+struct SlotInvokerBase {
+ virtual Object* receiver() const = 0;
+ virtual const SlotAttributeBase* slot() const = 0;
+};
+
template <typename... Args>
-struct SlotInvoker {
+struct SlotInvoker : SlotInvokerBase {
virtual void invoke(Args...) const = 0;
};
@@ -22,10 +36,47 @@ class Signal {
void invoke(Args...) const;
void operator()(Args... args) const { invoke(std::forward<Args>(args)...); }
+
+ size_t num_connections() const { return invokers_.size(); }
+ const SlotInvoker<Args...>* connection_at(size_t idx) const { return invokers_[idx]; }
private:
std::vector<SlotInvoker<Args...>*> invokers_;
};
+struct SignalTypeBase : Type {
+public:
+ virtual const std::vector<const Type*>& signature() const = 0;
+protected:
+ static std::string build_signal_name(const std::vector<const Type*>& signature);
+};
+
+template <typename... Args>
+struct SignalType : SignalTypeBase {
+ void construct(byte* place, IUniverse&) const { new(place) Signal<Args...>; }
+ void destruct(byte* place, IUniverse&) const { ::destruct(reinterpret_cast<Signal<Args...>*>(place)); }
+ void deserialize(byte* place, const ArchiveNode&) const;
+ void serialize(const byte* place, ArchiveNode&) const;
+ const std::string& name() const { return name_; }
+ size_t size() const { return sizeof(Signal<Args...>); }
+ const std::vector<const Type*>& signature() const { return signature_; }
+
+ SignalType() {
+ build_signature<Args...>(signature_);
+ name_ = build_signal_name(signature_);
+ }
+private:
+ std::string name_;
+ std::vector<const Type*> signature_;
+};
+
+template <typename... Args>
+struct BuildTypeInfo<Signal<Args...>> {
+ static const SignalType<Args...>* build() {
+ static const SignalType<Args...> type;
+ return &type;
+ }
+};
+
template <typename T, typename R, typename... Args>
struct MemberSlotInvoker : SlotInvoker<Args...> {
typedef R(T::*FunctionType)(Args...);
@@ -36,6 +87,10 @@ struct MemberSlotInvoker : SlotInvoker<Args...> {
(object_->*member_)(std::forward<Args>(args)...);
}
+ Object* receiver() const { return object_; }
+
+ const SlotAttributeBase* slot() const;
+
MemberSlotInvoker(T* object, FunctionType member) : object_(object), member_(member) {}
};
@@ -69,47 +124,6 @@ void Signal<Args...>::connect(std::function<R(Args...)> function) {
invokers_.push_back(new FunctionInvoker<R, Args...>(function));
}
-struct SignalAttributeBase {
- SignalAttributeBase(std::string name, std::string description) : name_(std::move(name)), description_(std::move(description)) {}
- virtual ~SignalAttributeBase() {}
- const std::string& name() const { return name_; }
- const std::string& description() const { return description_; }
- virtual std::string signature_description() const = 0;
- const std::vector<const Type*>& signature() const { return signature_; }
-private:
- std::string name_;
- std::string description_;
-protected:
- std::vector<const Type*> signature_;
-};
-
-template <typename T>
-struct SignalForObject {
- virtual ~SignalForObject() {}
-};
-
-template <typename... Args>
-struct SignalWithSignature : SignalAttributeBase {
- SignalWithSignature(std::string name, std::string description) : SignalAttributeBase(name, description) {
- signature_.reserve(sizeof...(Args));
- build_signature<Args...>(signature_);
- }
- virtual ~SignalWithSignature() {}
-
- std::string signature_description() const override {
- return get_signature_description<Args...>();
- }
-};
-
-template <typename T, typename... Args>
-struct SignalAttribute : SignalForObject<T>, SignalWithSignature<Args...> {
- typedef Signal<Args...> T::* MemberType;
-
- SignalAttribute(std::string name, std::string description, MemberType member) : SignalWithSignature<Args...>(name, description), member_(member) {}
-
- MemberType member_;
-};
-
struct SlotAttributeBase {
SlotAttributeBase(std::string name, std::string description) : name_(name), description_(description) {}
virtual ~SlotAttributeBase() {}
@@ -149,6 +163,30 @@ struct SlotAttribute : SlotForObject<T>, SlotWithSignature<Args...> {
SlotAttribute(std::string name, std::string description, FunctionType function) : SlotWithSignature<Args...>(name, description), function_(function) {}
FunctionType function_;
+
+ FunctionType method() const { return function_; }
};
+template <typename... Args>
+void SignalType<Args...>::deserialize(byte* place, const ArchiveNode& node) const {
+ // XXX TODO!
+ assert(false);
+}
+
+template <typename... Args>
+void SignalType<Args...>::serialize(const byte* place, ArchiveNode& node) const {
+ const Signal<Args...>* signal = reinterpret_cast<const Signal<Args...>*>(place);
+ for (size_t i = 0; i < signal->num_connections(); ++i) {
+ const SlotInvoker<Args...>* invoker = signal->connection_at(i);
+ ObjectPtr<Object> receiver = invoker->receiver();
+ const SlotAttributeBase* slot = invoker->slot();
+ if (receiver != nullptr && slot != nullptr) {
+ ArchiveNode& signal_connection = node.array_push();
+ ArchiveNode& receiver_node = signal_connection["receiver"];
+ get_type<ObjectPtr<Object>>()->serialize(reinterpret_cast<const byte*>(&receiver), receiver_node); // TODO! Prettier API…!
+ signal_connection["slot"] = slot->name();
+ }
+ }
+}
+
#endif /* end of include guard: SIGNAL_HPP_IVWSWZJM */
View
@@ -7,13 +7,34 @@
#include <vector>
#include <new>
#include "attribute.hpp"
+#include "signal.hpp"
+
+struct SlotAttributeBase;
+template <typename T> struct SlotForObject;
struct StructTypeBase : DerivedType {
const std::string& name() const override { return name_; }
const std::string& description() const { return description_; }
Object* cast(const DerivedType* to, Object* o) const override;
const StructTypeBase* super() const;
virtual std::vector<const AttributeBase*> attributes() const = 0;
+ virtual size_t num_slots() const = 0;
+ virtual const SlotAttributeBase* slot_at(size_t idx) const = 0;
+
+ template <typename T, typename R, typename... Args>
+ const SlotAttributeBase* find_slot_for_method(R(T::*method)(Args...)) const {
+ size_t n = num_slots();
+ for (size_t i = 0; i < n; ++i) {
+ const SlotAttributeBase* s = slot_at(i);
+ const SlotAttribute<T, R, Args...>* slot = dynamic_cast<const SlotAttribute<T,R,Args...>*>(s);
+ if (slot != nullptr) {
+ if (slot->method() == method) {
+ return slot;
+ }
+ }
+ }
+ return nullptr;
+ }
protected:
StructTypeBase(const StructTypeBase* super, std::string name, std::string description) : super_(super), name_(std::move(name)), description_(std::move(description)) {}
@@ -37,6 +58,9 @@ struct StructType : StructTypeBase {
void set_properties(std::vector<AttributeForObject<T>*> properties) {
properties_ = std::move(properties);
}
+ void set_slots(std::vector<SlotForObject<T>*> slots) {
+ slots_ = std::move(slots);
+ }
std::vector<const AttributeBase*> attributes() const override {
std::vector<const AttributeBase*> result;
@@ -46,6 +70,8 @@ struct StructType : StructTypeBase {
}
return result;
}
+ size_t num_slots() const { return slots_.size(); }
+ const SlotAttributeBase* slot_at(size_t idx) const { return dynamic_cast<const SlotAttributeBase*>(slots_[idx]); }
size_t num_elements() const override { return properties_.size(); }
const Type* type_of_element(size_t idx) const override { return properties_[idx]->attribute_type(); }
@@ -58,6 +84,7 @@ struct StructType : StructTypeBase {
bool is_abstract() const override { return is_abstract_; }
protected:
std::vector<AttributeForObject<T>*> properties_;
+ std::vector<SlotForObject<T>*> slots_;
bool is_abstract_;
};
@@ -85,4 +112,10 @@ void StructType<T>::serialize(const byte* object, ArchiveNode& node) const {
node["class"] = name();
}
+template <typename T, typename R, typename... Args>
+const SlotAttributeBase* MemberSlotInvoker<T,R,Args...>::slot() const {
+ const StructTypeBase* type = get_type<T>();
+ return type->find_slot_for_method(member_);
+}
+
#endif /* end of include guard: STRUCT_TYPE_HPP_PTB31EJN */

0 comments on commit 71591c9

Please sign in to comment.