summaryrefslogtreecommitdiffstats
path: root/libkdepim/weaver.h
diff options
context:
space:
mode:
Diffstat (limited to 'libkdepim/weaver.h')
-rw-r--r--libkdepim/weaver.h451
1 files changed, 0 insertions, 451 deletions
diff --git a/libkdepim/weaver.h b/libkdepim/weaver.h
deleted file mode 100644
index 8e82b5811..000000000
--- a/libkdepim/weaver.h
+++ /dev/null
@@ -1,451 +0,0 @@
-/* -*- C++ -*-
-
- This file declares the Weaver, Job and Thread classes.
-
- $ Author: Mirko Boehm $
- $ Copyright: (C) 2004, Mirko Boehm $
- $ Contact: mirko@kde.org
- http://www.kde.org
- http://www.hackerbuero.org $
- $ License: LGPL with the following explicit clarification:
- This code may be linked against any version of the TQt toolkit
- from Troll Tech, Norway. $
-
-*/
-
-#ifndef WEAVER_H
-#define WEAVER_H
-
-extern "C"
-{
-#include <stdarg.h>
-#include <unistd.h>
-#include <stdio.h>
-}
-
-#include <tqobject.h>
-#include <tqptrlist.h>
-#include <tqthread.h>
-#include <tqwaitcondition.h>
-#include <tqmutex.h>
-#include <tqevent.h>
-
-#include <tdepimmacros.h>
-
-namespace KPIM {
-namespace ThreadWeaver {
-
- /** This method prints a text message on the screen, if debugging is
- enabled. Otherwise, it does nothing. The message is thread safe,
- therefore providing that the messages appear in the order they where
- issued by the different threads.
- All messages are suppressed when Debug is false. All messages with a
- lower importance (higher number) than DebugLevel will be suppressed,
- too. Debug level 0 messages will always be printed as long as
- Debug is true.
- We use our own debugging method, since debugging threads is a more
- complicated experience than debugging single threaded
- contexts. This might change in future in the way that debug
- prints it's messages to another logging facility provided by
- the platform.
- Use setDebugLevel () to integrate adapt debug () to your platform.
- */
-
- KDE_EXPORT extern bool Debug;
- KDE_EXPORT extern int DebugLevel;
-
- KDE_EXPORT inline void setDebugLevel (bool debug, int level)
- {
- Debug = debug;
- DebugLevel = level;
- }
-
- KDE_EXPORT inline void debug(int severity, const char * cformat, ...)
-#ifdef __GNUC__
- __attribute__ ( (format (printf, 2, 3 ) ) )
-#endif
-;
-
- KDE_EXPORT inline void debug(int severity, const char * cformat, ...)
- {
- if ( Debug == true && ( severity<=DebugLevel || severity == 0) )
- {
- static TQMutex mutex;
- TQString text;
-
- mutex.lock();
- va_list ap;
- va_start( ap, cformat );
- vprintf (cformat, ap);
- va_end (ap);
- mutex.unlock();
- }
- }
-
-
- class Thread;
- class Job;
-
- /** A class to represent the events threads generate and send to the
- Weaver object. Examples include the start or end of the processing of a
- job. Threads create the event objects and discard them after posting
- the event, since the event receiver will assume ownership of the
- event.
- Events are associated to the sending thread and possibly to a
- processed job.
-
- Note: Do not create and use SPR/APR events, use Job::triggerSPR or
- Job::triggerAPR to create the requests. */
-
- class KDE_EXPORT Event : public TQCustomEvent
- {
- public:
- enum Action {
- NoAction = 0,
- Finished, /// All jobs in the queue are done.
- Suspended, /// Thread queueing halted.
- ThreadStarted,
- ThreadExiting,
- ThreadBusy,
- ThreadSuspended,
- JobStarted,
- JobFinished,
- JobSPR, /// Synchronous Process Request
- JobAPR /// Asynchronous Process Request
- };
- Event ( Action = NoAction, Thread * = 0, Job *job = 0);
- /** Return the (custom defined) event type. */
- static int type ();
- /** The ID of the sender thread. */
- Thread* thread () const;
- /** The associated job. */
- Job* job () const;
- /** The action. */
- Action action () const;
- private:
- Action m_action;
- Thread *m_thread;
- Job *m_job;
- static const int Type;
- };
-
- /** A Job is a simple abstraction of an action that is to be
- executed in a thread context.
- It is essential for the ThreadWeaver library that as a kind of
- convention, the different creators of Job objects do not touch the
- protected data members of the Job until somehow notified by the
- Job. See the SPR signal for an example.
-
- Jobs may emit process requests as signals. Consider process requests
- as a kind of synchronized call to the main thread.
- Process Requests are a generic means for Job derivate programmers to have
- the jobs interact with the creators (in the main thread) during
- processing time. To avoid race
- conditions and extensive locking and unlocking, the thread executing the
- job is suspended during the period needed to process the request.
-
- There are two kinds of process requests (we introduce abbreviations,
- also in the signal names and the code,
- only to save typing). Both are emitted by signals in the main thread:
- - Synchronous Process Requests (SPR): Synchronous requests expect that the
- complete request is performed in the slots connected to the signals. For
- example, to update a widget according to the progress of the job, a SPR
- may be used. In such cases, the Job's execution will be resumed
- immediately after the signal has been processed.
- - Asynchronous Process Requests (APR): For APRs, the job emitting the
- signal does not assume anything about the amount of time needed to
- perform the operation. Therefore, the thread is not waked after the
- signal returns. The creator has to wake to thread whenever it is
- ready by calling the wakeAPR method.
-
- Note: When using an APR, you better make sure to receive the signal
- with some object, otherwise the calling thread will block forever!
- */
- class KDE_EXPORT Job : public TQObject
- {
- Q_OBJECT
- TQ_OBJECT
- public:
- /** Construct a Job object. */
- Job(TQObject* parent=0, const char* name=0);
-
- /** Destructor. */
- virtual ~Job();
-
- /** Perform the job. The thread in which this job is executed
- is given as a parameter.
- Do not overload this method to create your own Job
- implementation, overload run(). */
- virtual void execute(Thread*);
-
- /** Returns true if the jobs's execute method finished. */
- virtual bool isFinished() const;
-
- /** Wake the thread after an APR has been processed. */
- void wakeAPR ();
-
- /** Process events related to this job (created by the processing
- thread or the weaver or whoever). */
- virtual void processEvent ( Event* );
-
- signals:
- /** This signal is emitted when a thread starts to process a job. */
- void started ();
- /** This signal is emitted when a job has been finished. */
- void done ();
- /** This signal is emitted when the job needs some operation done by
- the main thread (usually the creator of the job).
- It is important to understand that the emitting thread is
- suspended until the signal returns.
- When
- the operation requested has been performed and this signal is
- finished, the thread is automatically waked.
- What operation needs to be performed has to be negotiated between
- the two objects.
- Note: This signal is an attempt to provide job programmers with a
- generic way to interact while the job is executed. I am interested
- in feedback about it's use. */
- void SPR ();
- /** Perform an Asynchronous Process Request. See SPR and the generic
- Job documentation for a comparison. */
- void APR ();
- protected:
- /** Lock this Job's mutex. */
- void lock();
- /** Unlock this Job's mutex. */
- void unlock();
- /** The method that actually performs the job. It is called from
- execute(). This method is the one to overload it with the
- job's task. */
- virtual void run () = 0;
- /** Return the thread that executes this job.
- Returns zero of the job is not currently executed. */
- Thread *thread();
- /** Call with status = true to mark this job as done. */
- virtual void setFinished(bool status);
- /** Trigger a SPR.
- This emits a signal in the main thread indicating the necessity of
- a synchronized operation. */
- void triggerSPR ();
- /** Trigger an APR.
- This emit a signal in the main thread indicating the necessity of
- an unsynchronized operation.
- The calling thread needs to ensure to wake the thread when the
- operation is done. */
- void triggerAPR ();
-
- bool m_finished;
-
- TQMutex *m_mutex;
-
- Thread * m_thread;
-
- TQWaitCondition *m_wc;
- };
-
- class Weaver;
-
- /** The class Thread is used to represent the worker threads in
- the weaver's inventory. It is not meant to be overloaded. */
- class KDE_EXPORT Thread : public TQThread
- {
- public:
- /** Create a thread.
- These thread objects are only used inside the Weaver parent
- object. */
- Thread(Weaver *parent);
-
- /** The destructor. */
- ~Thread();
-
- /** Overloaded to execute the assigned job.
- This will NOT return until shutdown() is called. The
- thread will try to execute one job after the other, asking
- the Weaver parent for a new job when the assigned one is
- finished.
- If no jobs are available, the thread will suspend.
- After shutdown() is called, the thread will end as soon as
- the currently assigned job is done.
- */
- void run();
-
- /* Provide the msleep() method (protected in TQThread) to be
- available for executed jobs. */
- void msleep(unsigned long msec);
-
- /** Returns the thread id.
- This id marks the respective Thread object, and must
- therefore not be confused with, e.g., the pthread thread
- ID. */
- unsigned int id() const;
-
- /** Post an event, will be received and processed by the Weaver. */
- void post (Event::Action, Job* = 0);
-
- private:
- Weaver *m_parent;
-
- const unsigned int m_id;
-
- static unsigned int sm_Id;
-
- static unsigned int makeId();
- };
-
- /** A weaver is the manager of worker threads (Thread objects) to
- which it assigns jobs from it's queue. */
- class KDE_EXPORT Weaver : public TQObject
- {
- Q_OBJECT
- TQ_OBJECT
- public:
- Weaver (TQObject* parent=0, const char* name=0,
- int inventoryMin = 4, // minimal number of provided threads
- int inventoryMax = 32); // maximum number of provided threads
- virtual ~Weaver ();
- /** Add a job to be executed. */
- virtual void enqueue (Job*);
- /** Enqueue all jobs in the given list.
- This is an atomic operation, no jobs will start
- before all jobs in the list are enqueued.
- If you need a couple of jobs done and want to receive the
- finished () signal afterwards, use this method to queue
- them. Otherwise, when enqueueing your jobs
- individually, there is a chance that you receive more than
- one finished signal. */
- void enqueue (TQPtrList<Job> jobs);
- /** Remove a job from the queue.
- If the job qas queued but not started so far, it is simple
- removed from the queue. For now, it is unsupported to
- dequeue a job once its execution has started.
- For that case, you will have to provide a method to interrupt your
- job's execution (and receive the done signal).
- Returns true if the job has been dequeued, false if the
- job has already been started or is not found in the
- queue. */
- virtual bool dequeue (Job*);
- /** Remove all queued jobs.
- Please note that this will not kill the threads, therefore
- all jobs that are being processed will be continued. */
- virtual void dequeue ();
- /** Get notified when a thread has finished a job.
- This is done automatically. */
- // virtual void jobFinished(Thread *);
- /** Finish all queued operations, then return.
- This method is used in imperative programs that cannot react on
- events to have the controlling (main) thread wait wait for the
- jobs to finish.
- Warning: This will suspend your thread!
- Warning: If your jobs enter for example an infinite loop, this
- will never return! */
- virtual void finish();
- /** Suspend job execution if state = true, otherwise resume
- job execution if it was suspended.
- When suspending, all threads are allowed to finish the
- currently assigned job but will not receive a new
- assignment.
- When all threads are done processing the assigned job, the
- signal suspended will() be emitted.
- If you call suspend (true) and there are no jobs left to
- be done, you will immidiately receive the suspended()
- signal. */
- virtual void suspend (bool state);
- /** Is the queue empty? */
- bool isEmpty () const;
- /** Is the weaver idle?
- The weaver is idle if no jobs are queued and no jobs are processed
- by the threads (m_active is zero). */
- bool isIdle () const;
- /** Returns the number of pending jobs. */
- int queueLength ();
- /** Assign a job to the calling thread.
- This is supposed to be called from the Thread objects in
- the inventory.
- 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);
- /** 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 ();
- /** Post an event that is handled by this object, but in the main
- (GUI) thread. Different threads may use this method to communicate
- with the main thread.
- thread and job mark the objects associated with this event. */
- void post (Event::Action, Thread* = 0, Job* = 0);
- /** Returns the current number of threads in the inventory. */
- int threads () const;
- signals:
- /** This signal is emitted when the Weaver has finished ALL currently
- queued jobs.
- If a number of jobs is enqueued sequentially, this signal might be
- emitted a couple of times (what happens is that all already queued
- jobs have been processed while you still add new ones). This is
- not a bug, but the intended behaviour. */
- void finished ();
- /** Thread queueing has been suspended.
- When suspend is called with state = true, all threads are
- allowed to finish their job. When the last thread
- finished, this signal is emitted. */
- void suspended ();
- /** This signal is emitted when a job is done. It is up to the
- programmer if this signal or the done signal of the job is more
- handy. */
- void jobDone (Job*);
-// The following signals are used mainly for debugging purposes.
- void threadCreated (Thread *);
- void threadDestroyed (Thread *);
- void threadBusy (Thread *);
- void threadSuspended (Thread *);
-
- protected:
- /** 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();
- /** Check incoming events for user defined ones. The threads use user
- defined events to communicate with the Weaver. */
- bool event ( TQEvent* );
- /** The thread inventory. */
- TQPtrList<Thread> m_inventory;
- /** The job queue. */
- TQPtrList<Job> m_assignments;
- /** The number of jobs that are assigned to the worker
- threads, but not finished. */
- int m_active;
- /** Stored setting. */
- int m_inventoryMin;
- /** Stored setting . */
- int m_inventoryMax;
- /** Wait condition all idle or done threads wait for. */
- TQWaitCondition m_jobAvailable;
- /** Wait for a job to finish. */
- TQWaitCondition m_jobFinished;
- /** Indicates if the weaver is shutting down and exiting it's
- threads. */
- bool m_shuttingDown;
- /** m_running is set to true when a job is enqueued and set to false
- when the job finishes that was the last in the queue.
- E.g., this will flip from false to true to false when you
- continuously enqueue one single job. */
- bool m_running;
- /** If m_suspend is true, no new jobs will be assigned to
- threads.
- Jobs may be queued, but will not be processed until suspend
- (false) is called. */
- bool m_suspend;
- private:
- /** Mutex to serialize operations. */
- TQMutex *m_mutex;
- };
-} // namespace ThreadWeaver
-} // namespace KPIM
-
-#endif // defined WEAVER_H