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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <simgear/structure/function_list.hxx>
|
||||
#include <simgear/structure/map.hxx>
|
||||
#include <simgear/structure/SGReferenced.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
#include <simgear/math/sg_types.hxx>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
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<Callback> _cb_done,
|
||||
_cb_fail,
|
||||
_cb_always;
|
||||
|
||||
ReadyState _ready_state;
|
||||
bool _willClose;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/package/Delegate.hxx>
|
||||
|
||||
#include <simgear/structure/function_list.hxx>
|
||||
#include <simgear/structure/SGReferenced.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
@@ -156,11 +156,10 @@ private:
|
||||
|
||||
Delegate::FailureCode _status;
|
||||
|
||||
Callback _cb_done,
|
||||
_cb_fail,
|
||||
_cb_always;
|
||||
ProgressCallback _cb_progress;
|
||||
|
||||
function_list<Callback> _cb_done,
|
||||
_cb_fail,
|
||||
_cb_always;
|
||||
function_list<ProgressCallback> _cb_progress;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
37
simgear/structure/detail/function_list_template.hxx
Normal file
37
simgear/structure/detail/function_list_template.hxx
Normal file
@@ -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<Ret (BOOST_PP_ENUM_PARAMS(n, A))>
|
||||
#define SG_LIST_TYPE std::vector<SG_FUNC_TYPE >
|
||||
|
||||
template<class Ret BOOST_PP_ENUM_TRAILING_PARAMS(n, class A)>
|
||||
class function_list<Ret (BOOST_PP_ENUM_PARAMS(n, A))>:
|
||||
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
|
||||
51
simgear/structure/function_list.hxx
Normal file
51
simgear/structure/function_list.hxx
Normal file
@@ -0,0 +1,51 @@
|
||||
///@file Handle a list of callbacks like a single boost::function
|
||||
//
|
||||
// Copyright (C) 2014 Thomas Geymayer <tomgey@gmail.com>
|
||||
//
|
||||
// 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 <boost/function.hpp>
|
||||
#include <boost/preprocessor/iteration/iterate.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
template<typename Sig> class function_list;
|
||||
|
||||
// Build dependency for CMake, gcc, etc.
|
||||
# define SG_DONT_DO_ANYTHING
|
||||
# include <simgear/structure/detail/function_list_template.hxx>
|
||||
# undef SG_DONT_DO_ANYTHING
|
||||
|
||||
# define BOOST_PP_ITERATION_LIMITS (0, 3)
|
||||
# define BOOST_PP_FILENAME_1 <simgear/structure/detail/function_list_template.hxx>
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
template<typename Sig>
|
||||
class function_list<boost::function<Sig> >:
|
||||
public function_list<Sig>
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
} // namespace simgear
|
||||
|
||||
#endif /* SG_FUNCTION_LIST_HXX_ */
|
||||
77
simgear/structure/function_list_test.cxx
Normal file
77
simgear/structure/function_list_test.cxx
Normal file
@@ -0,0 +1,77 @@
|
||||
#define BOOST_TEST_MODULE structurce
|
||||
#include <BoostTestTargetConfig.h>
|
||||
|
||||
#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<int (int)> 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<boost::function<int (int)> > 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<boost::function<int (int, int)> > 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()> void_func_list;
|
||||
void_func_list.push_back(&func_void);
|
||||
void_func_list();
|
||||
BOOST_REQUIRE_EQUAL(func_void_called, 1);
|
||||
}
|
||||
Reference in New Issue
Block a user