// [License] // The Ariba-Underlay Copyright // // Copyright (c) 2008-2009, Institute of Telematics, Universität Karlsruhe (TH) // // Institute of Telematics // Universität Karlsruhe (TH) // Zirkel 2, 76128 Karlsruhe // Germany // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation // are those of the authors and should not be interpreted as representing // official policies, either expressed or implied, of the Institute of // Telematics. // [License] #ifndef SYSTEMQUEUE_H_ #define SYSTEMQUEUE_H_ #include "SystemEvent.h" #include "SystemEventListener.h" #include "ariba/utility/logging/Logging.h" #include #include #include #include // std::priority_queue #include // std::greater #include #include #include #include #include #include #include #include #include namespace ariba { namespace utility { using std::list; using boost::posix_time::ptime; /** * This class implements a simple system event queue to allow * a simulation of cooperative multitasking. It also allows * events to be scheduled from other tasks. This allows * dispatching asynchronous tasks. * * @author Christoph Mayer, Sebastian Mies */ /** XXX Mario Hock -- reworking the entire module **/ class SystemQueue : private boost::noncopyable { use_logging_h(SystemQueue); friend class EnterMethod; public: /** * Get the SystemQueue singleton instance. */ static SystemQueue& instance(); /** * This methods schedules a given event. * * @param The event to be scheduled * @param The delay in milli-seconds */ void scheduleEvent( const SystemEvent& event, uint32_t delay = 0 ); /** * This method schedules a function call in the SystemQueue. * (Like scheduleEvent, but to be used with boost::bind.) * * @param function: The function to be called [void function()] * @param The delay in milli-seconds */ void scheduleCall( const boost::function0& function, uint32_t delay = 0 ); /** * Starts the processing and waiting for events. * Use cancel() to end system queue processing and * isEmpty() to check wheter the queue is empty. */ void run(); /** * Cancels the system queue and ends the processing after the * currently processed event is processed. * * NOTE: Do not call this function from within a SystemQueue-Event. * Use SystemQueue::leave() instead. * * This method is thread-safe. */ void cancel(); /** * Like SystemQueue::cancel(), but may only be called from within a SystemQueue-Event. * * NOTE: In this case some cleanup can not be made. -- If the SystemQueue is * restarted, SystemQueue::cancel() must be called before SystemQueue::run() * can be called again. */ void leave(); /** * Join the SystemQueue thread -- the current thread is blocked until the * SystemQueue finishes. * * NOTE: Use this only in combination with SystemQueue::leave() * * [ There is a possible race condition with SystemQueue::cancel(), but * SystemQueue::join() should not be used at the same time as * SystemQueue::cancel() anyway. (SystemQueue::leave() is fine, though.) */ void join(); /** * Drop all queued events for that listener */ void dropAll( const SystemEventListener* mlistener); /** * Check wheter this queue has items or not. * * @return True, if this queue is empty. */ bool isEmpty(); /** * Is the system queue already started and running? * * @return TRUE, if the system queue is running. | FALSE otherwise */ bool isRunning(); /** * NOTE: This function is for debugging and asserts only!! * * @return TRUE if called from the SysQ thread (from inside a SystemEvent) * | FALSE if it's called from another thread */ bool am_I_in_the_SysQ_thread(); protected: /** * Aqcuire the mutex */ void enterMethod(); /** * Leave the mutex */ void leaveMethod(); /** * Constructs a system queue. */ SystemQueue(); /** * Destroys the system queue. Beware that all events * are canceled */ ~SystemQueue(); /** * inner class of class SystemQueue: * * QueueThread -- the class the does the actual work */ private: typedef list EventQueue; typedef std::priority_queue, // [ TODO is vector the best underlay? ] std::greater > PriorityEventQueue; //******************************************************** class QueueThread { friend class SystemQueue; public: QueueThread(); virtual ~QueueThread(); /// main loop -- called from boost::thread void operator()(); // void run(); void cancel(); bool isEmpty(); void insert( SystemEvent& event, uint32_t delay ); void enter(); void leave(); void dropAll( const SystemEventListener* mlistener); bool isRunning(); private: /// main loop functions void run_immediate_event(); void check_timed_queue(); void wait_for_next_deadline(); /// makes sure that always the same clock is used ptime get_clock(); private: EventQueue immediateEventsQ; PriorityEventQueue timedEventsQ; boost::condition_variable system_queue_idle; boost::mutex queue_mutex; bool processing_event; volatile bool running; volatile bool aborted; volatile bool unclean; }; // class QueueThread /// inner class of class SystemQueue private: /** * This inner class handles the function-call events. * @see SystemQueue::scheduleCall */ class FunctionCaller : public SystemEventListener { void handleSystemEvent(const SystemEvent& event) { boost::function0* function_ptr = event.getData< boost::function0 >(); (*function_ptr)(); delete function_ptr; } }; FunctionCaller internal_function_caller; /// member variables of class SystemQueue private: boost::scoped_ptr SysQ; boost::scoped_ptr sysq_thread; // volatile bool systemQueueRunning; }; // class SystemQueue }} // spovnet, common #endif /* SYSTEMQUEUE_H_ */