From: Thomas Geymayer Date: Mon, 30 Jun 2014 16:22:24 +0000 (+0200) Subject: HTTPRequest/pkg::Install: do not replace callbacks. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=0b60643053343a8573097287cae89c2e99393105;p=simgear.git HTTPRequest/pkg::Install: do not replace callbacks. Keep a list of callbacks to allow registering multiple callbacks to the same event. This is consistent with eg. jQuery.Deferred and is needed for example to open multiple dialogs showing the progress of installing a package at the same time. --- diff --git a/simgear/io/HTTPRequest.cxx b/simgear/io/HTTPRequest.cxx index 900b7fc2..0809c70a 100644 --- a/simgear/io/HTTPRequest.cxx +++ b/simgear/io/HTTPRequest.cxx @@ -39,7 +39,7 @@ Request* Request::done(const Callback& cb) if( _ready_state == DONE ) cb(this); else - _cb_done = cb; + _cb_done.push_back(cb); return this; } @@ -50,7 +50,7 @@ Request* Request::fail(const Callback& cb) if( _ready_state == FAILED ) cb(this); else - _cb_fail = cb; + _cb_fail.push_back(cb); return this; } @@ -61,7 +61,7 @@ Request* Request::always(const Callback& cb) if( isComplete() ) cb(this); else - _cb_always = cb; + _cb_always.push_back(cb); return this; } @@ -321,22 +321,19 @@ void Request::setReadyState(ReadyState state) onDone(); onAlways(); - if( _cb_done ) - _cb_done(this); + _cb_done(this); } else if( state == FAILED ) { onFail(); onAlways(); - if( _cb_fail ) - _cb_fail(this); + _cb_fail(this); } else return; - if( _cb_always ) - _cb_always(this); + _cb_always(this); } //------------------------------------------------------------------------------ diff --git a/simgear/io/HTTPRequest.hxx b/simgear/io/HTTPRequest.hxx index ef101b3f..f739d2b8 100644 --- a/simgear/io/HTTPRequest.hxx +++ b/simgear/io/HTTPRequest.hxx @@ -3,13 +3,13 @@ #include +#include #include #include #include #include #include -#include class SGPropertyNode; @@ -47,7 +47,7 @@ public: { return _request_headers.get(key); } /** - * Set the handler to be called when the request successfully completes. + * Add a handler to be called when the request successfully completes. * * @note If the request is already complete, the handler is called * immediately. @@ -61,7 +61,7 @@ public: } /** - * Set the handler to be called when the request completes or aborts with an + * Add a handler to be called when the request completes or aborts with an * error. * * @note If the request has already failed, the handler is called @@ -76,8 +76,8 @@ public: } /** - * Set the handler to be called when the request either successfully - * completes or fails. + * Add a handler to be called when the request either successfully completes + * or fails. * * @note If the request is already complete or has already failed, the * handler is called immediately. @@ -224,9 +224,9 @@ private: unsigned int _responseLength; unsigned int _receivedBodyBytes; - Callback _cb_done, - _cb_fail, - _cb_always; + function_list _cb_done, + _cb_fail, + _cb_always; ReadyState _ready_state; bool _willClose; diff --git a/simgear/package/Install.cxx b/simgear/package/Install.cxx index b5c9487d..659511ff 100644 --- a/simgear/package/Install.cxx +++ b/simgear/package/Install.cxx @@ -325,7 +325,7 @@ Install* Install::done(const Callback& cb) if( _status == Delegate::FAIL_SUCCESS ) cb(this); else - _cb_done = cb; + _cb_done.push_back(cb); return this; } @@ -337,7 +337,7 @@ Install* Install::fail(const Callback& cb) && _status != Delegate::FAIL_IN_PROGRESS ) cb(this); else - _cb_fail = cb; + _cb_fail.push_back(cb); return this; } @@ -348,7 +348,7 @@ Install* Install::always(const Callback& cb) if( _status != Delegate::FAIL_IN_PROGRESS ) cb(this); else - _cb_always = cb; + _cb_always.push_back(cb); return this; } @@ -356,7 +356,7 @@ Install* Install::always(const Callback& cb) //------------------------------------------------------------------------------ Install* Install::progress(const ProgressCallback& cb) { - _cb_progress = cb; + _cb_progress.push_back(cb); return this; } @@ -365,24 +365,20 @@ void Install::installResult(Delegate::FailureCode aReason) { if (aReason == Delegate::FAIL_SUCCESS) { m_package->catalog()->root()->finishInstall(this); - if( _cb_done ) - _cb_done(this); + _cb_done(this); } else { m_package->catalog()->root()->failedInstall(this, aReason); - if( _cb_fail ) - _cb_fail(this); + _cb_fail(this); } - if( _cb_always ) - _cb_always(this); + _cb_always(this); } //------------------------------------------------------------------------------ void Install::installProgress(unsigned int aBytes, unsigned int aTotal) { - m_package->catalog()->root()->installProgress(this, aBytes, aTotal); - if( _cb_progress ) - _cb_progress(this, aBytes, aTotal); + m_package->catalog()->root()->installProgress(this, aBytes, aTotal); + _cb_progress(this, aBytes, aTotal); } diff --git a/simgear/package/Install.hxx b/simgear/package/Install.hxx index 81cf580a..e65789c4 100644 --- a/simgear/package/Install.hxx +++ b/simgear/package/Install.hxx @@ -23,11 +23,11 @@ #include #include +#include #include #include #include -#include namespace simgear { @@ -156,11 +156,10 @@ private: Delegate::FailureCode _status; - Callback _cb_done, - _cb_fail, - _cb_always; - ProgressCallback _cb_progress; - + function_list _cb_done, + _cb_fail, + _cb_always; + function_list _cb_progress; }; diff --git a/simgear/structure/CMakeLists.txt b/simgear/structure/CMakeLists.txt index 7679588c..0c41b622 100644 --- a/simgear/structure/CMakeLists.txt +++ b/simgear/structure/CMakeLists.txt @@ -21,12 +21,17 @@ set(HEADERS commands.hxx event_mgr.hxx exception.hxx + function_list.hxx intern.hxx map.hxx subsystem_mgr.hxx StateMachine.hxx ) +set(DETAIL_HEADERS + detail/function_list_template.hxx +) + set(SOURCES SGAtomic.cxx SGBinding.cxx @@ -43,6 +48,7 @@ set(SOURCES ) simgear_component(structure structure "${SOURCES}" "${HEADERS}") +simgear_component(structure/detail structure/detail "" "${DETAIL_HEADERS}") if(ENABLE_TESTS) @@ -56,6 +62,11 @@ add_test(expressions ${EXECUTABLE_OUTPUT_PATH}/test_expressions) endif(ENABLE_TESTS) +add_boost_test(function_list + SOURCES function_list_test.cxx + LIBRARIES ${TEST_LIBS} +) + add_boost_test(shared_ptr SOURCES shared_ptr_test.cpp LIBRARIES ${TEST_LIBS} diff --git a/simgear/structure/detail/function_list_template.hxx b/simgear/structure/detail/function_list_template.hxx new file mode 100644 index 00000000..92a10a27 --- /dev/null +++ b/simgear/structure/detail/function_list_template.hxx @@ -0,0 +1,37 @@ +#ifndef SG_FUNCTION_LIST_HXX_ +# error function_list - do not include this file! +#endif + +#ifndef SG_DONT_DO_ANYTHING +#define n BOOST_PP_ITERATION() +#define SG_FUNC_TYPE boost::function +#define SG_LIST_TYPE std::vector + +template +class function_list: + public SG_LIST_TYPE +{ + public: + typedef SG_FUNC_TYPE function_type; + typedef typename SG_LIST_TYPE::iterator iterator; + typedef typename SG_LIST_TYPE::const_iterator const_iterator; + + Ret operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, A, a)) const + { + if( this->empty() ) + return Ret(); + + const_iterator list_end = --this->end(); + for(const_iterator f = this->begin(); f != list_end; ++f) + if( *f ) + (*f)(BOOST_PP_ENUM_PARAMS(n, a)); + + return (*list_end) ? (*list_end)(BOOST_PP_ENUM_PARAMS(n, a)) : Ret(); + } +}; + +#undef n +#undef SG_FUNC_TYPE +#undef SG_LIST_TYPE + +#endif // SG_DONT_DO_ANYTHING diff --git a/simgear/structure/function_list.hxx b/simgear/structure/function_list.hxx new file mode 100644 index 00000000..28ef08e4 --- /dev/null +++ b/simgear/structure/function_list.hxx @@ -0,0 +1,51 @@ +///@file Handle a list of callbacks like a single boost::function +// +// Copyright (C) 2014 Thomas Geymayer +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +#ifndef SG_FUNCTION_LIST_HXX_ +#define SG_FUNCTION_LIST_HXX_ + +#include +#include +#include +#include +#include +#include + +namespace simgear +{ + template class function_list; + + // Build dependency for CMake, gcc, etc. +# define SG_DONT_DO_ANYTHING +# include +# undef SG_DONT_DO_ANYTHING + +# define BOOST_PP_ITERATION_LIMITS (0, 3) +# define BOOST_PP_FILENAME_1 +# include BOOST_PP_ITERATE() + + template + class function_list >: + public function_list + { + + }; + +} // namespace simgear + +#endif /* SG_FUNCTION_LIST_HXX_ */ diff --git a/simgear/structure/function_list_test.cxx b/simgear/structure/function_list_test.cxx new file mode 100644 index 00000000..58202c9c --- /dev/null +++ b/simgear/structure/function_list_test.cxx @@ -0,0 +1,77 @@ +#define BOOST_TEST_MODULE structurce +#include + +#include "function_list.hxx" + +static int func_called = 0, + func2_called = 0; + +int func(int x) +{ + ++func_called; + return x; +} + +int func2(int x) +{ + ++func2_called; + return 2 * x; +} + +int func_add(int x, int y) +{ + return func(x) + y; +} + +int func2_add(int x, int y) +{ + return func2(x) + y; +} + +static int func_void_called = 0; +void func_void() +{ + ++func_void_called; +} + +BOOST_AUTO_TEST_CASE( create_and_call ) +{ + using namespace simgear; + + function_list func_list; + + BOOST_REQUIRE(func_list.empty()); + + func_list.push_back(&func); + BOOST_REQUIRE_EQUAL(func_list(2), 2); + BOOST_REQUIRE_EQUAL(func_called, 1); + + func_list.push_back(&func2); + BOOST_REQUIRE_EQUAL(func_list(2), 4); + BOOST_REQUIRE_EQUAL(func_called, 2); + BOOST_REQUIRE_EQUAL(func2_called, 1); + + function_list > func_list2; + func_list2.push_back(&func); + func_list2.push_back(&func2); + func_list2.push_back(&func2); + + BOOST_REQUIRE_EQUAL(func_list2(2), 4); + BOOST_REQUIRE_EQUAL(func_called, 3); + BOOST_REQUIRE_EQUAL(func2_called, 3); + + // two parameters + function_list > func_list3; + func_list3.push_back(&func_add); + func_list3.push_back(&func2_add); + + BOOST_REQUIRE_EQUAL(func_list3(2, 3), 7); + BOOST_REQUIRE_EQUAL(func_called, 4); + BOOST_REQUIRE_EQUAL(func2_called, 4); + + // returning void/no params + function_list void_func_list; + void_func_list.push_back(&func_void); + void_func_list(); + BOOST_REQUIRE_EQUAL(func_void_called, 1); +}