/* -*- C++ -*- This file implements the public interfaces of the WeaverImpl class. $ Author: Mirko Boehm $ $ Copyright: (C) 2005-2013 Mirko Boehm $ $ Contact: mirko@kde.org http://www.kde.org http://creative-destruction.me $ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. $Id: WeaverImpl.h 32 2005-08-17 08:38:01Z mirko $ */ #ifndef WEAVERIMPL_H #define WEAVERIMPL_H #include #include #ifndef THREADWEAVER_PRIVATE_API #define THREADWEAVER_PRIVATE_API #endif #include "State.h" #include "WeaverInterface.h" namespace ThreadWeaver { class Job; class Thread; class WeaverObserver; /** A WeaverImpl is the manager of worker threads (Thread objects) to which it assigns jobs from its queue. It extends the API of WeaverInterface to provide additional methods needed by the Thread objects. */ class WeaverImpl : public WeaverInterface { Q_OBJECT public: /** Construct a WeaverImpl object. */ explicit WeaverImpl (QObject* parent=0 ); /** Destruct a WeaverImpl object. */ virtual ~WeaverImpl (); const State& state() const; void setMaximumNumberOfThreads( int cap ); int maximumNumberOfThreads() const; int currentNumberOfThreads () const; /** Set the object state. */ void setState( StateId ); void registerObserver ( WeaverObserver* ); virtual void enqueue (Job*); virtual bool dequeue (Job*); virtual void dequeue (); virtual void finish(); virtual void suspend( ); virtual void resume(); bool isEmpty () const; bool isIdle () const; int queueLength () const; /** Assign a job to the calling thread. This is supposed to be called from the Thread objects in the inventory. Do not call this method from your code. Returns 0 if the weaver is shutting down, telling the calling thread to finish and exit. If no jobs are available and shut down is not in progress, the calling thread is suspended until either condition is met. In *previous*, threads give the job they have completed. If this is the first job, previous is zero. */ virtual Job* applyForWork (Thread *thread, Job *previous); /** Blocks the calling thread until some actor calls assignJobs. */ void blockThreadUntilJobsAreBeingAssigned(Thread *th); /** Wait for a job to become available. */ void waitForAvailableJob(Thread *th); /** Increment the count of active threads. */ void incActiveThreadCount(); /** Decrement the count of active threads. */ void decActiveThreadCount(); /** Returns the number of active threads. Threads are active if they process a job. */ int activeThreadCount(); /** Take the first available job out of the queue and return it. The job will be removed from the queue (therefore, take). Only jobs that have no unresolved dependencies are considered available. If only jobs that depened on other, unfinished jobs are in the queue, this method returns a nil pointer. */ Job* takeFirstAvailableJob(Job* previous); /** Schedule enqueued jobs to be executed by idle threads. This will try to distribute as many jobs as possible to all idle threads. */ void assignJobs(); void requestAbort(); /** Dump the current jobs to the console. Not part of the API. */ void dumpJobs(); Q_SIGNALS: /** A Thread has been created. */ void threadStarted ( ThreadWeaver::Thread* ); /** A thread has exited. */ void threadExited ( ThreadWeaver::Thread* ); /** A thread has been suspended. */ void threadSuspended ( ThreadWeaver::Thread* ); /** The thread is busy executing job j. */ void threadBusy ( ThreadWeaver::Thread*, ThreadWeaver::Job* j); protected: /** Adjust active thread count. This is a helper function for incActiveThreadCount and decActiveThreadCount. */ void adjustActiveThreadCount ( int diff ); /** Factory method to create the threads. Overload in adapted Weaver implementations. */ virtual Thread* createThread(); /** Adjust the inventory size. This method creates threads on demand. Threads in the inventory are not created upon construction of the WeaverImpl object, but when jobs are queued. This avoids costly delays on the application startup time. Threads are created when the inventory size is under inventoryMin and new jobs are queued. */ // @TODO: add code to raise inventory size over inventoryMin // @TODO: add code to quit unnecessary threads void adjustInventory ( int noOfNewJobs ); /** Lock the mutex for this weaver. The threads in the inventory need to lock the weaver's mutex to synchronize the job management. */ // void lock (); // /** Unlock. See lock(). */ // void unlock (); /** The thread inventory. */ QList m_inventory; /** The job queue. */ QList m_assignments; /** The number of jobs that are assigned to the worker threads, but not finished. */ int m_active; /** Stored setting . */ int m_inventoryMax; /** Wait condition all idle or done threads wait for. */ QWaitCondition m_jobAvailable; /** Wait for a job to finish. */ QWaitCondition m_jobFinished; private: /** Mutex to serialize operations. */ QMutex *m_mutex; /** Non-recursive mutex to serialize calls to finish(). */ QMutex* m_finishMutex; /** Mutex used by m_jobAvailable wait condition. */ QMutex* m_jobAvailableMutex; // @TODO: make state objects static /** The state of the art. * @see StateId */ State* m_state; /** The state objects. */ State *m_states[NoOfStates]; }; } // namespace ThreadWeaver #endif // WEAVERIMPL_H