From 1298bcd1e421ccfefafa78c6d33760818902f399 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 4 Jul 2013 19:46:58 -0700 Subject: gras: function registry is more flexible --- include/gras/block.hpp | 13 +++++++ include/gras/detail/block.hpp | 87 +++++++++++++++++++++++++++++++++++++++++++ lib/block_props.cpp | 15 ++++++++ lib/gras_impl/block_data.hpp | 2 + tests/block_props_test.cpp | 50 +++++++++++++++++++++++++ 5 files changed, 167 insertions(+) diff --git a/include/gras/block.hpp b/include/gras/block.hpp index f2f1b2b..ba9a64a 100644 --- a/include/gras/block.hpp +++ b/include/gras/block.hpp @@ -166,6 +166,14 @@ struct GRAS_API Block : Element * Provides polymorphic, thread-safe access to block properties. ******************************************************************/ + template void register_call(const std::string &key, ReturnType(ClassType::*fcn)(void)); + template void register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &)); + template void register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &)); + + template ReturnType call(const std::string &key); + template ReturnType call(const std::string &key, const Arg0 &); + template ReturnType call(const std::string &key, const Arg0 &, const Arg1 &); + /*! * Register property getter method into the property interface. * Call register_getter() from the contructor of the block. @@ -430,6 +438,11 @@ struct GRAS_API Block : Element /******************************************************************* * private implementation guts for overloads and template support ******************************************************************/ + + void _register_function(const std::string &, void *); + virtual PMCC _handle_function_access(const std::string &, const std::vector &); + + virtual PMCC _handle_prop_access(const std::string &, const PMCC &, const bool); void _register_getter(const std::string &, void *); void _register_setter(const std::string &, void *); diff --git a/include/gras/detail/block.hpp b/include/gras/detail/block.hpp index 9dccb22..fcd52e1 100644 --- a/include/gras/detail/block.hpp +++ b/include/gras/detail/block.hpp @@ -8,6 +8,93 @@ namespace gras { +struct GRAS_API FunctionRegistry +{ + FunctionRegistry(void); + virtual ~FunctionRegistry(void); + virtual PMCC call(const std::vector &args) = 0; +}; + +template +class FunctionRegistryImpl : public FunctionRegistry +{ +public: + FunctionRegistryImpl( + ClassType *obj, + ReturnType(ClassType::*fcn0)(void), + ReturnType(ClassType::*fcn1)(const Arg0 &) = NULL, + ReturnType(ClassType::*fcn2)(const Arg0 &, const Arg1 &) = NULL + ): + _obj(obj), + _fcn0(fcn0), + _fcn1(fcn1), + _fcn2(fcn2) + {} + virtual ~FunctionRegistryImpl(void){} + + PMCC call(const std::vector &args) + { + if (_fcn0) return PMC_M((_obj->*_fcn0)()); + if (_fcn1) return PMC_M((_obj->*_fcn1)(args[0].safe_as())); + if (_fcn2) return PMC_M((_obj->*_fcn2)(args[0].safe_as(), args[1].safe_as())); + return PMCC();//should not get here + } + +private: + ClassType *_obj; + ReturnType(ClassType::*_fcn0)(void); + ReturnType(ClassType::*_fcn1)(const Arg0 &); + ReturnType(ClassType::*_fcn2)(const Arg0 &, const Arg1 &); +}; + +template void Block::register_call(const std::string &key, ReturnType(ClassType::*fcn)(void)) +{ + ClassType *obj = dynamic_cast(this); + void *fr = new FunctionRegistryImpl(obj, fcn); + _register_function(key, fr); +} + +template void Block::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &)) +{ + ClassType *obj = dynamic_cast(this); + void *fr = new FunctionRegistryImpl(obj, NULL, fcn); + _register_function(key, fr); +} + +template void Block::register_call(const std::string &key, ReturnType(ClassType::*fcn)(const Arg0 &, const Arg1 &)) +{ + ClassType *obj = dynamic_cast(this); + void *fr = new FunctionRegistryImpl(obj, NULL, NULL, fcn); + _register_function(key, fr); +} + +template ReturnType Block::call(const std::string &key) +{ + std::vector args; + PMCC r = _handle_function_access(key, args); + return r.safe_as(); +} + +template ReturnType Block::call(const std::string &key, const Arg0 &a0) +{ + std::vector args; + args.push_back(PMC_M(a0)); + PMCC r = _handle_function_access(key, args); + return r.safe_as(); +} + +template ReturnType Block::call(const std::string &key, const Arg0 &a0, const Arg1 &a1) +{ + std::vector args; + args.push_back(PMC_M(a0)); + args.push_back(PMC_M(a1)); + PMCC r = _handle_function_access(key, args); + return r.safe_as(); +} + + + + struct GRAS_API PropertyRegistry { PropertyRegistry(void); diff --git a/lib/block_props.cpp b/lib/block_props.cpp index ae687be..fc4c755 100644 --- a/lib/block_props.cpp +++ b/lib/block_props.cpp @@ -5,6 +5,9 @@ using namespace gras; +FunctionRegistry::FunctionRegistry(void){} +FunctionRegistry::~FunctionRegistry(void){} + PropertyRegistry::PropertyRegistry(void){} PropertyRegistry::~PropertyRegistry(void){} @@ -113,3 +116,15 @@ PMCC Block::_get_property(const std::string &key) { return prop_access_dispatcher((*this)->block_actor, key, PMCC(), false); } + + +void Block::_register_function(const std::string &key, void *fr) +{ + (*this)->block_data->function_registry[key].reset(reinterpret_cast(fr)); +} + +PMCC Block::_handle_function_access(const std::string &key, const std::vector &args) +{ + //TODO this is testing -- needs to call actor instead + return (*this)->block_data->function_registry[key]->call(args); +} diff --git a/lib/gras_impl/block_data.hpp b/lib/gras_impl/block_data.hpp index cbc657e..664ee5a 100644 --- a/lib/gras_impl/block_data.hpp +++ b/lib/gras_impl/block_data.hpp @@ -18,6 +18,7 @@ namespace gras { +typedef boost::shared_ptr FunctionRegistrySptr; typedef boost::shared_ptr PropertyRegistrySptr; struct PropertyRegistryPair { @@ -82,6 +83,7 @@ struct BlockData //property stuff std::map property_registry; + std::map function_registry; BlockStats stats; }; diff --git a/tests/block_props_test.cpp b/tests/block_props_test.cpp index f53a1c3..ad1c5e2 100644 --- a/tests/block_props_test.cpp +++ b/tests/block_props_test.cpp @@ -68,3 +68,53 @@ BOOST_AUTO_TEST_CASE(test_property_errors) //wrong type for property BOOST_CHECK_THROW(my_block.set("foo", "a string"), std::exception); } + +struct MyBlockNewShit : gras::Block +{ + MyBlockNewShit(void): + gras::Block("MyBlockNewShit") + { + this->register_call("foo", &MyBlockNewShit::foo); + this->register_call("bar", &MyBlockNewShit::bar); + this->register_call("baz", &MyBlockNewShit::baz); + //this->register_call("example_setter", &MyBlockNewShit::example_setter); + } + + //dummy work + void work(const InputItems &, const OutputItems &){} + + int foo(void) + { + return 42; + } + + int bar(const std::string &a0) + { + return a0.size(); + } + + int baz(const std::string &a0, const bool &a1) + { + return a1?a0.size():-1; + } + + void example_setter(const long &) + { + + } +}; + +BOOST_AUTO_TEST_CASE(test_property_newshit) +{ + MyBlockNewShit my_block; + size_t my_foo = my_block.call("foo"); + BOOST_CHECK_EQUAL(my_foo, size_t(42)); + + size_t my_bar = my_block.call("bar", "hello"); + BOOST_CHECK_EQUAL(my_bar, size_t(5)); + + signed my_baz = my_block.call("baz", "hello", false); + BOOST_CHECK_EQUAL(my_baz, signed(-1)); + + //my_block.call("example_setter", 123); +} -- cgit