<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1204062503604371867</id><updated>2012-02-16T06:34:00.822Z</updated><category term='c++'/><category term='bind'/><category term='asio'/><category term='coding'/><title type='text'>Mostly Coding</title><subtitle type='html'>Stuff about coding and algorithms</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mostlycoding.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1204062503604371867/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mostlycoding.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>nova77</name><uri>http://www.blogger.com/profile/03650683544176779128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_okhl2EZcJDs/Shxm3Nh28QI/AAAAAAAAAAM/3Tqbyy_ruY4/S220/avatar_nova2_160.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>1</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1204062503604371867.post-496126335377974775</id><published>2009-05-27T22:21:00.011+01:00</published><updated>2009-05-28T00:08:38.699+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='bind'/><category scheme='http://www.blogger.com/atom/ns#' term='asio'/><category scheme='http://www.blogger.com/atom/ns#' term='coding'/><title type='text'>Useful ASIO patterns</title><content type='html'>Or maybe I should title this "On how I found a use for boost::protect".&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://tenermerx.com/Asio"&gt;asio&lt;/a&gt; library has been immensely helpful in promoting a series of patterns previously rarely seen in the lands of C++ (i.e the &lt;a href="http://think-async.com/Asio/boost_asio_1_3_1/doc/html/boost_asio/overview/core/async.html"&gt;proactor pattern&lt;/a&gt;). It is therefore not surprising that people are starting to use it beyond the scope of networking.&lt;br /&gt;&lt;br /&gt;Take for instance this &lt;a href="http://think-async.com/Asio/Recipes"&gt;recipe&lt;/a&gt; you can find on the official (non-boost) website:&lt;br /&gt;&lt;pre class="brush: cpp"&gt;asio::io_service io_service;&lt;br /&gt;asio::io_service::work work(io_service);&lt;br /&gt;boost::thread_group threads;&lt;br /&gt;&lt;br /&gt;for (std::size_t i = 0; i &amp;lt; my_thread_count; ++i)&lt;br /&gt;   threads.create_thread(boost::bind(&amp;amp;asio::io_service::run, &amp;amp;io_service));&lt;br /&gt;&lt;br /&gt;io_service.post(boost::bind(an_expensive_calculation, 42));&lt;br /&gt;io_service.post(boost::bind(a_long_running_task, 123));&lt;br /&gt;&lt;br /&gt;io_service.stop();&lt;br /&gt;threads.join_all();&lt;br /&gt;&lt;/pre&gt;In just a bunch of lines of code we have a thread pool executing any arbitrary task whenever one thread is available. No need to address the usual multi-threading issues with concurrent jobs sharing few resources: just post what you need and let &lt;span style="font-style: italic;"&gt;io_service&lt;/span&gt; take care of it!&lt;br /&gt;&lt;br /&gt;I used this approach recently when I needed to implement a way to asynchronously update a backup server with incoming operations.&lt;br /&gt;First a bit of background: at &lt;a href="http://www.last.fm/"&gt;last.fm&lt;/a&gt; we often use &lt;a href="http://incubator.apache.org/thrift/"&gt;thrift&lt;/a&gt; to power our services. Thrift is a powerful RPC framework that works across multiple languages. When you specify the methods the server is going to answer, thrift generates both the code for your server and the client in whatever language you want. For instance this definition&lt;br /&gt;&lt;pre class="brush: plain"&gt;void ping()&lt;br /&gt;void foo(1: i32 value)&lt;br /&gt;&lt;/pre&gt;will create the client class that can be used (this is simplified) this way:&lt;br /&gt;&lt;pre class="brush: cpp"&gt;apache::MyClient client;&lt;br /&gt;// connection stuff&lt;br /&gt;client.ping();&lt;br /&gt;client.foo(10);&lt;br /&gt;&lt;/pre&gt;What I wanted to do is to be able to queue and execute an arbitrary number of &lt;span style="font-style: italic;"&gt;ping&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;foo&lt;/span&gt; on a pool of MyClient objects and on a set of &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; threads running them.&lt;br /&gt;&lt;br /&gt;The pool of objects can be handled by a simple stack that implements the &lt;a href="http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization"&gt;RAII&lt;/a&gt; pattern to safely pull objects when needed and push them back in when their job is done. I might write something about it in the future, but for the sake of simplicity I will skip that in my example. What's mostly interesting is the boost+asio part!&lt;br /&gt;&lt;br /&gt;So here's how. First I define my BackupHandler class:&lt;br /&gt;&lt;pre class="brush: cpp"&gt;&lt;br /&gt;class BackupHandler&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;&lt;br /&gt;   BackupHandler(int poolSize = 4)&lt;br /&gt;   {&lt;br /&gt;      m_pWork.reset( new boost::asio::io_service::work(m_io_service) );&lt;br /&gt;&lt;br /&gt;      for ( int i = 0; i &amp;lt; poolSize; ++i)&lt;br /&gt;         m_threadGroup.create_thread( boost::bind(&amp;amp;boost::asio::io_service::run, &amp;amp;m_io_service) );&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   ~BackupHandler()&lt;br /&gt;   {&lt;br /&gt;      m_pWork.reset(); // stop all!&lt;br /&gt;      m_threadGroup.join_all(); // wait for all completition&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // this will leave immediately&lt;br /&gt;   template &amp;lt;typename TFunc&amp;gt;&lt;br /&gt;   void enqueue(TFunc fun)&lt;br /&gt;   {&lt;br /&gt;      m_io_service.post(&lt;br /&gt;          boost::bind( &amp;amp;BackupHandler::execute&amp;lt;TFunc&amp;gt;, this, fun )&lt;br /&gt;       );&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;&lt;br /&gt;   // this will be executed when one of the threads is available&lt;br /&gt;   template &amp;lt;typename TFunc&amp;gt;&lt;br /&gt;   void execute(TFunc fun)&lt;br /&gt;   {&lt;br /&gt;      MyClient client; // here I should use RAII to get the client resource&lt;br /&gt;      fun(client);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;&lt;br /&gt;   io_service m_io_service;&lt;br /&gt;   shared_ptr&amp;lt;io_service::work&amp;gt; m_pWork;&lt;br /&gt;&lt;br /&gt;   thread_group m_threadGroup;&lt;br /&gt;};&lt;/pre&gt;&lt;br /&gt;Note how client becomes the argument instead of the caller. This is possible because with &lt;a href="http://www.boost.org/doc/libs/1_39_0/libs/bind/bind.html#with_member_pointers"&gt;boost::bind&lt;/a&gt; you can put a placeholder (_1) even on the caller when used on pointer to member functions.&lt;br /&gt;&lt;br /&gt;I can now enqueue the functions whenever I need, thus purely asynchronously, with bind:&lt;br /&gt;&lt;pre class="brush: cpp"&gt;&lt;br /&gt;BackupHandler bkp(10);&lt;br /&gt;//.. code&lt;br /&gt;bkp.enqueue(&lt;br /&gt;  boost::protect(&lt;br /&gt;    boost::bind(&amp;amp;apache::MyClient::ping, _1) // who's gonna call that? _1!&lt;br /&gt;  );&lt;br /&gt;//.. other code&lt;br /&gt;bkp.enqueue(&lt;br /&gt;  boost::protect(&lt;br /&gt;    boost::bind(&amp;amp;apache::MyClient::foo, _1, 42)&lt;br /&gt;  );&lt;br /&gt;// ..more stuff enqueued later..&lt;/pre&gt;Make sure you use &lt;a href="http://www.boost.org/doc/libs/1_39_0/libs/bind/bind.html#nested_binds"&gt;boost::protect&lt;/a&gt; otherwise bind will try and evaluate the placeholder before its time is due and the compiler will cry (or crash).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1204062503604371867-496126335377974775?l=mostlycoding.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mostlycoding.blogspot.com/feeds/496126335377974775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mostlycoding.blogspot.com/2009/05/asio-library-has-been-immensely-helpful.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1204062503604371867/posts/default/496126335377974775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1204062503604371867/posts/default/496126335377974775'/><link rel='alternate' type='text/html' href='http://mostlycoding.blogspot.com/2009/05/asio-library-has-been-immensely-helpful.html' title='Useful ASIO patterns'/><author><name>nova77</name><uri>http://www.blogger.com/profile/03650683544176779128</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_okhl2EZcJDs/Shxm3Nh28QI/AAAAAAAAAAM/3Tqbyy_ruY4/S220/avatar_nova2_160.png'/></author><thr:total>0</thr:total></entry></feed>
