00001 /* Copyright (C) 2009 Väinö Lappi <djap84@gmail.com> 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00016 00017 */ 00018 00019 /* 00020 * Keeps count on child threads created for playlist to add/remove files. 00021 * Implements API to check if there are still threads running and stopping all threads. 00022 * Takes care of deleting when thread finishes it's task. 00023 * 00024 * Originally planned to use simple system of signals/slots to get the same behaviour 00025 * but there was some problems (upon closing the program 00026 * the signals seemed never reach the destination and the program froze) 00027 * so I had to do this litle more complicated tracker system of Mutexes, destruction queue 00028 * and destructor thread to avoid using signals as much as possible. 00029 */ 00030 00031 #ifndef PLAYLISTCHILDTHREADSTRACKER_H 00032 #define PLAYLISTCHILDTHREADSTRACKER_H 00033 // 00034 #include <QThread> 00035 #include <QMutex> 00036 #include <QWaitCondition> //Used to put thread to sleep for a while when it's not needed 00037 00038 class PlaylistFolderAdder; 00039 class PlaylistEditorDialog; 00040 class PlaylistModifierBase; 00041 00042 /* 00043 * Store child pointers here when they announce their 00044 * attempt to quit. 00045 */ 00046 struct childDestructQueueEntry 00047 { 00048 PlaylistModifierBase* childPtr; 00049 childDestructQueueEntry* next; 00050 }; 00051 // 00052 class PlaylistChildThreadsTracker : public QThread 00053 { 00054 Q_OBJECT 00055 public: 00056 PlaylistChildThreadsTracker(PlaylistEditorDialog* parent); 00057 00058 /* 00059 * Childs can use this announce when they are about to exit, 00060 * When a child calls this, it's pointer will be added to destruction 00061 * queue where it will be picked as soon as all childs before it have 00062 * been deleted. This will be done in tracker threads main event loop 00063 * that will after picking the child from Queue wait the child from exit 00064 * and then delete the child and the Queue entry. 00065 */ 00066 void ChildAboutToExit(PlaylistModifierBase* childPtr); 00067 00068 /* 00069 * Add a new child thread to tracker. 00070 * This will only increase the child counter. The pointers are not stored 00071 * Since each child will send it when about to exit. Termination of child 00072 * is done by emitting terminateThreads(), which is connected to every child upon creation. 00073 */ 00074 void AddChild(); 00075 // Stop all childs 00076 void TerminateAllChilds(); 00077 // Wait untill there's no child threads left 00078 void WaitChildsExit(); 00079 // Stop this thread and wait untill exit 00080 void StopAndWaitExit(); 00081 protected: 00082 //Trackers main event loop 00083 void run(); 00084 private: 00085 PlaylistEditorDialog* iParent; 00086 unsigned iChildThreadCount; 00087 QMutex iChildThreadCounterMux; //UI or some of the threads might collide when increasing/decreasing this counter. 00088 00089 //The que will be modified from more than 2 threads 00090 QMutex iChildDestructQueueMutex; 00091 childDestructQueueEntry* iChildDestructQueueIndex; 00092 //Delay for main event loop of tracker thread when nothing to do 00093 QWaitCondition iTrackerMainLoopDelay; 00094 //locking this will cause the main event loop of tracker to exit 00095 QMutex iEndThread; 00096 QWaitCondition iWaitChildsToExitDelay; 00097 QWaitCondition iWaitSelfToExitDelay; 00098 QMutex iWaitSelfToExitMux; 00099 signals: 00100 void terminateThreads(); //Use this to terminate all child threads 00101 }; 00102 #endif