if( _ready_state == DONE )
cb(this);
else
- _cb_done = cb;
+ _cb_done.push_back(cb);
return this;
}
if( _ready_state == FAILED )
cb(this);
else
- _cb_fail = cb;
+ _cb_fail.push_back(cb);
return this;
}
if( isComplete() )
cb(this);
else
- _cb_always = cb;
+ _cb_always.push_back(cb);
return this;
}
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);
}
//------------------------------------------------------------------------------
#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;
{ 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.
}
/**
- * 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
}
/**
- * 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.
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;
if( _status == Delegate::FAIL_SUCCESS )
cb(this);
else
- _cb_done = cb;
+ _cb_done.push_back(cb);
return this;
}
&& _status != Delegate::FAIL_IN_PROGRESS )
cb(this);
else
- _cb_fail = cb;
+ _cb_fail.push_back(cb);
return this;
}
if( _status != Delegate::FAIL_IN_PROGRESS )
cb(this);
else
- _cb_always = cb;
+ _cb_always.push_back(cb);
return this;
}
//------------------------------------------------------------------------------
Install* Install::progress(const ProgressCallback& cb)
{
- _cb_progress = cb;
+ _cb_progress.push_back(cb);
return this;
}
{
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);
}
#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
{
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;
};
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
)
simgear_component(structure structure "${SOURCES}" "${HEADERS}")
+simgear_component(structure/detail structure/detail "" "${DETAIL_HEADERS}")
if(ENABLE_TESTS)
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}
--- /dev/null
+#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
--- /dev/null
+///@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_ */
--- /dev/null
+#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);
+}