workthread.h

Go to the documentation of this file.
00001 /**
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /** @file workthread.h Interface for WorkThread API */
00020 
00021 #ifndef __WORKTHREAD_H__
00022 #define __WORKTHREAD_H__
00023 
00024 #include <hn/osdep.h>
00025 #include <hn/hnfwd.h>
00026 #include <hn/event.h>
00027 
00028 /**
00029  * ThreadWork class indicates a job to be processed in separate thread. Derived
00030  * classes shall override pure virtual process() member function to perform
00031  * their work. Notice that process() method is called from secondary thread,
00032  * so everything done in that method must be multi-thread safe.
00033  *
00034  * After constructing ThreadWork object on free store, wrapped in shared_ptr,
00035  * submit the work to WorkThread class for processing. Only one work is being
00036  * processed at any time, altough this may be changed/increased in later
00037  * revisions to make better use of multi-processor systems.
00038  */
00039 class ThreadWork {
00040 public:
00041         ThreadWork();
00042         virtual ~ThreadWork();
00043 
00044         /**
00045          * Override this pure virtual method to perform your work. It is highly
00046          * recommended to perform your work incrementally, returning false here
00047          * after each pass, and true once all the work has been processed. There
00048          * is no performance penalty for doing so, and it allows us to later add
00049          * support for work_progress concept.
00050          *
00051          * @return true if all work has been done, false otherwise.
00052          *
00053          * \todo Return value is currently ignored by implementation; use
00054          *       setComplete() to indicate the job is complete to WorkThread.
00055          */
00056         virtual bool process() = 0;
00057 
00058         //! Cancels a pending job
00059         void cancel();
00060         //! Check whether this job is still valid for processing
00061         bool isValid();
00062         //! Check whether this job is complete
00063         bool isComplete();
00064 protected:
00065         //! Set the state of the job to /completed/
00066         void setComplete();
00067 private:
00068         bool m_valid;                  //!< If true, the job is still valid
00069         boost::mutex m_validLock;      //!< Protects m_valid member
00070         bool m_complete;               //!< If true, the job is complete
00071         boost::mutex m_completeLock;   //!< Protects m_complete member
00072 };
00073 
00074 /**
00075  * WorkThread class provides an interface for submitting jobs to secondary
00076  * thread for processing, and takes care of job queue handling. This class
00077  * is a Singleton, with the only instance accessible via instance() member
00078  * function. To post jobs for processing, pass them to postWork() function.
00079  */
00080 class WorkThread {
00081 public:
00082         static WorkThread& instance();
00083 
00084         /**
00085          * Post a work for processing.
00086          *
00087          * @param work      Pointer to ThreadWork object to be processed
00088          */
00089         void postWork(ThreadWorkPtr work);
00090 private:
00091         /**
00092          * @name Singleton Pattern requirements
00093          */
00094         //@{
00095         WorkThread();
00096         WorkThread(const WorkThread&);
00097         WorkThread& operator=(const WorkThread&);
00098         ~WorkThread();
00099         //@}
00100 
00101         //! Main work thread loop function
00102         void threadLoop();
00103         //! Used by secondary thread, this is used to check whether the thread
00104         //! should exit
00105         bool checkExit();
00106         //! Used by main thread, this signals work thread to exit ASAP
00107         void exit();
00108 
00109         //! Pending jobs queue, filled by postWork() and processed by
00110         //! secondary thread.
00111         std::deque<ThreadWorkPtr> m_queue;
00112         //! Protects m_queue member
00113         boost::mutex m_queueLock;
00114         //! Used to signal events to secondary thread
00115         boost::condition m_notify;
00116         //! Protects m_notify member
00117         boost::mutex m_notifyLock;
00118         //! If true, work thread should exit as soon as possible
00119         bool m_exiting;
00120         //! Protects m_exiting member
00121         boost::mutex m_exitLock;
00122         //! Worker thread object
00123         boost::thread m_worker;
00124 };
00125 
00126 #endif