1 // templated callback system 2 // Copyright (C) 2008, 2009 Tim Blechmann 3 // 4 // This program is free software; you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation; either version 2 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; see the file COPYING. If not, write to 16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 // Boston, MA 02111-1307, USA. 18 19 #pragma once 20 21 #include <memory> 22 #include <exception> 23 #include <iostream> 24 25 #include <boost/checked_delete.hpp> 26 27 #include <boost/lockfree/spsc_queue.hpp> 28 #include <boost/lockfree/queue.hpp> 29 30 31 namespace nova { 32 33 /** \brief simple templated callback system, using a lockfree fifo */ 34 template <class callback_type, bool mpmc = true, class callback_deleter = boost::checked_deleter<callback_type>> 35 class callback_system : private callback_deleter { 36 typedef typename boost::mpl::if_c<mpmc, boost::lockfree::queue<callback_type*>, 37 boost::lockfree::spsc_queue<callback_type*>>::type queue_type; 38 39 public: callback_system(size_t element_count=2048)40 callback_system(size_t element_count = 2048): callbacks(element_count) {} 41 42 /** \brief adds a new Callback to the Scheduler, threadsafe */ add_callback(callback_type * cb)43 inline void add_callback(callback_type* cb) { callbacks.push(cb); } 44 45 /** \brief run all callbacks */ run_callbacks(void)46 inline void run_callbacks(void) { 47 callbacks.consume_all([this](callback_type* cb) { run_callback(cb); }); 48 } 49 50 /** \brief run one callback 51 * 52 * assumes, that the queue contains at least one callback 53 * 54 * */ run_callback(void)55 void run_callback(void) { 56 callbacks.consume_one([this](callback_type* cb) { run_callback(cb); }); 57 } 58 59 private: 60 /** run a callback, handle exceptions */ run_callback(callback_type * runme)61 bool run_callback(callback_type* runme) { 62 bool ret; 63 try { 64 runme->run(); 65 ret = true; 66 } catch (std::exception const& e) { 67 std::cout << "unhandled exception while running callback: " << e.what() << std::endl; 68 ret = false; 69 } 70 callback_deleter::operator()(runme); 71 return ret; 72 } 73 74 protected: 75 queue_type callbacks; /**< \brief fifo for callbacks */ 76 }; 77 78 } /* namespace nova */ 79