[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Re: Request For Comments: KThread
From:       Don Sanders <dsanders () cch ! com ! au>
Date:       1999-10-01 1:27:27
[Download RAW message or body]

Would it be a good idea for a threading api to faciliate thread synchronization
by providing easy to use Critical Sections/Semaphores? I think thread
synchronization is the trickiest part of multi-threaded programming.

What would happen if I have some data structure that I want to update without
blocking the UI? Typically only one thread could update the data structure at a
time, so I would use a semaphore/critical section to lock the data structure,
maybe pushing commands to be performed on to a stack (the stack would also
require a critical section for thread synchronization). In this way I could
serialize updates to the data structure without blocking the man UI thread for
any noticeable amount of time.

This is a pretty common scenario isn't it? Does the proposed API make this easy
to do? How about other common tasks?

As far as I am aware in *nix one currently uses flock (or binding of a network
socket?) to act as critical sections. To be honest I find these techniques
confusing, there seem to be subtle but critically important details (flock
sometimes fails silently over network drives so files have to created in
/tmp?). It would be nice if this could simplified, or do people like using
flock raw?

There is definitely scope for using threads in KMail (background folder
compaction) but it will be months before I have time to do that.

BFN,
Don.

On Thu, 30 Sep 1999, Waldo Bastian wrote:
> Given the recent discussion about multi-threading the following might
> be of interest:
> 
> Request For Comments: KThread
> 
> Why Threads?
> ============
> 
> Within KDE a level of parallelism is reached using two mechanisms:
> events and sub-processes. Up till now KDE has not made use of threads.
> There are some good reasons for this:
> 1. Threads are complex to use
> 2. Most activities can be handled in parallel using either events or
>   sub-processes.
> 3. Thread implementations were not widely available in a portable
>   fashion.
> 
> The above not withstanding, there is an additional need for a finer
> grained paralellism within KDE which can be achieved with threads:
> * Processing operations which can take an unpredictable and/or
> unbounded amount of time.
> 
> For these operations, events or sub-processes are often not well suited.
> The processing can theoretically be split in small processing-units and
> each processing-unit can be handled during one event. This approach is
> taken in the HTML Widget. It is however, not always possible to split
> a processing task into smaller tasks. In the case of the HTML widget,
> starting and stopping the processing of a chunk of HTML code can actually
> take longer than the processing of the chunk itself. Another example
> could be the loading a of large JPG image. Although technically possible to
> do this in small chunks, the library used for handling JPG does not foresee
> in this.
> 
> The other approach to achieve paralellism is to use sub-processes. The
> best example within KDE for this are our IO-slaves. A seperate process is
> however unsuitable for tasks which require an intimate interaction with 
> data-structures in the parent process, or who produce large quantities 
> of data, e.g. image/multi-media operations.
> 
> I think it's therefor safe to conclude that there is a need for a finer
> grained form of paralellism which can be achieved with threads.
> 
> Goals of KThread
> ================
> 
> I stated three reasons why threads haven't been used widely within KDE.
> I have shown that the second reason, "Most activities can be handled in 
> parallel using either events or sub-processes.", might be valid, but leaves
> a significant group of activities out in the cold. With KThread I want to 
> offer finer grained paralellism which addresses the other two points:
> 
> * KThread should make threading easy.
> * KThread should take care of portability issues.
> 
> 
> Interface of KThread
> ====================
> I would like to make the following proposal for a KThread implementation.
> 
> [An explanation and some examples follow below: NOT YET FINISHED]
> 
> class KThread 
> {
> public:
>   KThread(KThreadWorker *worker);
> 
>   /**
>    * Returns whether the thread is still active
>    */
>   bool isRunning();
> 
>   /**
>    * Terminates thread on the first sequence point.
>    * (Almost the same as "suspend(); kill();")
>    */ 
>   void cancel();
> 
>   /**
>    * Terminates a thread unconditionally.
>    * You better know what you are doing.
>    */
>   void kill();
> 
>   /**
>    * Suspends thread when it reaches the next sequence point.
>    */
>   void suspend();
> 
>   /**
>    * Resumes the thread after it has been suspended.
>    */
>   void resume();
> 
> signals:
>   /**
>    * Signal indicating the "progress scale".
>    */
>   void maxProgress(int _maxProgress);
> 
>   /**
>    * Signal indicating progress
>    */
>   void progress(int _progress);
> 
>   /**
>    * Signal containing some info message
>    */
>   void info(QString infoMsg);
> 
>   /**
>    * Signal indicating the thread has finished. (See also isRunning())
>    */
>   void finished();
> }
> 
> class KThreadWorker
> {
>    /**
>     * Constructor.
>     *
>     * The constructor is called from the main-thread.
>     */
>    KThreadWorker();
> 
>    /**
>     * Destructor.
>     *
>     * The destructor is called from the main-thread.
>     */
>    virtual ~KThreadWorker();
> 
>    /**
>     * Function which does the actual work.
>     * Returning from this function terminates the thread.
>     */
>    virtual void exec() { }; 
> 
>    /**
>     * Function which gets called before a thread is canceled.
>     * This function gets called in the thread itself.
>     *
>     * Either 'finished()' or 'canceled()' is called but
>     * never both of them.
>     */
>    virtual void canceled() { };
> 
>    /**
>     * Function which gets called before a thread ends.
>     * This function gets called in the thread itself.
>     *
>     * Either 'finished()' or 'canceled()' is called but
>     * never both of them.
>     */
>    virtual void finsished() { };
> 
>    /**
>     * Function who indicates a sequence point.
>     * The main-thread can suspend() the thread at this point.
>     * Normally the object should make sure to be in
>     * a defined state when entering this state.
>     *
>     * This function returns very fast when no suspend() is
>     * pending.
>     */
>    void sequencePoint();
> 
>    /**
>     * Sends a maxProgress signal to the main-thread. 
>     * 
>     * The thread gets suspended until the signal has been
>     * handled by the main-thread.
>     *
>     * (Synchronizes with main-thread)
>     **/
>    void maxProgress(int _maxProgress);
> 
>    /**
>     * Sends a progress signal to the main-thread. 
>     * 
>     * The thread gets suspended until the signal has been
>     * handled by the main-thread.
>     *
>     * (Synchronizes with main-thread)
>     **/
>    void progress(int _progress);
> 
>    /**
>     * Sends a info signal to the main-thread. 
>     * 
>     * The thread gets suspended until the signal has been
>     * handled by the main-thread.
>     *
>     * (Synchronizes with main-thread)
>     **/
>    void info(QString infoMsg);
> 
>    /**
>     * Sends an event in the application main-loop. 
>     * 
>     * The thread gets suspended until the event has been
>     * handled by the main-thread.
>     *
>     * (Synchronizes with main-thread)
>     **/
>    void sendEvent(QObject *receiver, QEvent *ev);
> }

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic