
Hello boost, Traditionally, I think of services as having a thread pool or manually managed threads to handle requests and produce responses. I have been looking at boost::asio and tbb as an alternative to this in order to take advantage of multiple cores. Also, I think that implementing an event handler with asio or tbb should provide better performance over a threadpool. Do you have any suggestions? So far, I have implemented an example using tbb::task_group and spawned tasks. This yielded full CPU utilization, but since these are very short lived tasks, the task creation overhead took over. Using io_service, it seems to be as easy as posting to the service, and running it among different threads. Would this be the correct approach for my case? Can somebody share their experiences on libraries or patterns used to implement an event handling mechanism? Thanks, Alessandro

On Fri, Jan 22, 2010 at 09:00:42PM -0600, Alessandro Bellina wrote:
Can somebody share their experiences on libraries or patterns used to implement an event handling mechanism?
Below is code for an experimental scheduler that I am currently writing,
based on boost::asio::io_service object with a bunch of threads. I am
also using the new boost::packaged_task and boost::shared_future classes
that arrived with 1.41. There are a few
issues, though:
1) I don't know why the mutex in the handler (func) does not work.
2) No structure (e.g., tree-like) on the tasks as in TBB, no priorities.
#include <memory>
#include <iostream>
#include

1) I don't know why the mutex in the handler (func) does not work.
Inside the func(), the mutex should be locked as: boost::mutex::scoped_lock lk(mtx); rather than (in your code): boost::mutex::scoped_lock(mtx); Cheers, Robert On Mon, Jan 25, 2010 at 3:06 AM, Matthias Vallentin < vallentin@icsi.berkeley.edu> wrote:
On Fri, Jan 22, 2010 at 09:00:42PM -0600, Alessandro Bellina wrote:
Can somebody share their experiences on libraries or patterns used to implement an event handling mechanism?
Below is code for an experimental scheduler that I am currently writing, based on boost::asio::io_service object with a bunch of threads. I am also using the new boost::packaged_task and boost::shared_future classes that arrived with 1.41. There are a few issues, though:
1) I don't know why the mutex in the handler (func) does not work. 2) No structure (e.g., tree-like) on the tasks as in TBB, no priorities.
#include <memory> #include <iostream> #include
#include #include "boost/utility/result_of.hpp" namespace core {
template <typename R> class task { public: typedef typename boost::unique_future<R> unique_future;
private: typedef boost::packaged_task<R> task_type;
public: template <typename F> explicit task(const F& f) : pt_(new task_type(f)) { }
void operator()() { (*pt_)(); }
unique_future future() { return pt_->get_future(); }
private: boost::shared_ptr
pt_; }; class scheduler { public: template <typename T> typename T::unique_future put(T& t) { io_service_.post(boost::bind(&T::operator(), t));
return t.future(); }
template <typename F> typename task
::type>::unique_future schedule(const F& f) { task ::type> t(f); return put(t); }
void run(unsigned n = boost::thread::hardware_concurrency()) { sentinel_.reset(new boost::asio::io_service::work(io_service_));
for (unsigned i = 0; i < n; ++i) threads_.add_thread(new boost::thread( boost::bind(&boost::asio::io_service::run, &io_service_))); }
void finish() { sentinel_.reset(); }
void interrupt() { io_service_.stop(); }
private: boost::thread_group threads_; boost::asio::io_service io_service_; std::auto_ptrboost::asio::io_service::work sentinel_; };
} // namespace core
static boost::mutex mtx;
void func(int i) { boost::mutex::scoped_lock(mtx); std::cout << "i = " << i << std::endl; }
int main() { core::scheduler s; s.run();
core::task<void> task(boost::bind(&func, 42)); core::task<void>::unique_future f = s.put(task); core::task<void>::unique_future g = s.schedule(boost::bind(&func, 43)); core::task<void>::unique_future h = s.schedule(boost::bind(&func, 44));
h.wait(); g.wait(); f.wait();
return 0; }
Matthias -- Matthias Vallentin vallentin@icsi.berkeley.edu http://www.icir.org/matthias _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Matthias Vallentin wrote:
On Fri, Jan 22, 2010 at 09:00:42PM -0600, Alessandro Bellina wrote:
Can somebody share their experiences on libraries or patterns used to implement an event handling mechanism?
Below is code for an experimental scheduler that I am currently writing, based on boost::asio::io_service object with a bunch of threads. I am also using the new boost::packaged_task and boost::shared_future classes that arrived with 1.41. There are a few issues, though:
1) I don't know why the mutex in the handler (func) does not work. 2) No structure (e.g., tree-like) on the tasks as in TBB, no priorities.
I've written something quite simple that is also able to do 2), semantics are Asio-like, reference_counter m_counter; ios.post( m_counter.wrap( task1 ) ); ios.post( m_counter.wrap( task2 ) ); ios.post( m_counter.wrap( task3 ) ); m_counter.async_wait( all_complete_handler ); the reasons for me to use this are that it doesn't require additional locking (it's using an atomic counter), and that it fits the asynchronous model well. If there's enough interest, I can post the implementation. Cheers, Rutger

On Sat, Mar 20, 2010 at 08:57:35AM +0100, Rutger ter Borg wrote:
Matthias Vallentin wrote:
2) No structure (e.g., tree-like) on the tasks as in TBB, no priorities.
I've written something quite simple that is also able to do 2), semantics are Asio-like,
reference_counter m_counter; ios.post( m_counter.wrap( task1 ) ); ios.post( m_counter.wrap( task2 ) ); ios.post( m_counter.wrap( task3 ) ); m_counter.async_wait( all_complete_handler );
How does the task structure look like here? It looks like the tasks execute concurrently and increment a counter on start/finish - atomically, as you say. What I mean with structure are for example hierarchical (e.g., tree-like) groupings of tasks. I haven't looked at it in detail, but Oliver Kowalke's task and fiber implementation in the Boost vault look like a good starting point. From the documentation, it seems there is some support for structuring tasks via sub-tasks. The libraries support atomic operations via Boost.Atomic. Matthias -- Matthias Vallentin vallentin@icsi.berkeley.edu http://www.icir.org/matthias

Matthias Vallentin wrote:
I've written something quite simple that is also able to do 2), semantics are Asio-like,
reference_counter m_counter; ios.post( m_counter.wrap( task1 ) ); ios.post( m_counter.wrap( task2 ) ); ios.post( m_counter.wrap( task3 ) ); m_counter.async_wait( all_complete_handler );
How does the task structure look like here? It looks like the tasks execute concurrently and increment a counter on start/finish - atomically, as you say. What I mean with structure are for example hierarchical (e.g., tree-like) groupings of tasks.
Right. Tasks are wrapped/bound handlers (like in Asio). Hierarchical stuff would look like reference_counter m_counter_1; reference_counter m_counter_2; ios.post( m_counter_1.wrap( task1 ) ); ios.post( m_counter_1.wrap( task2 ) ); ios.post( m_counter_2.wrap( task3 ) ); m_counter_1.async_wait( m_counter_2.wrap( task4 ) ); m_counter_2.async_wait( task5 ); Execution dependencies and order will be 1) task1, task2, task3 2) task4 3) task5
I haven't looked at it in detail, but Oliver Kowalke's task and fiber implementation in the Boost vault look like a good starting point. From the documentation, it seems there is some support for structuring tasks via sub-tasks. The libraries support atomic operations via Boost.Atomic.
I haven't look at those in detail, yet. For atomic stuff, I just borrowed the atomic counter from boost/detail. Cheers, Rutger
participants (4)
-
Alessandro Bellina
-
Boost lzw
-
Matthias Vallentin
-
Rutger ter Borg