1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2006-2011 Mikkel Schubert ( xaignar@amule.org / http://www.amule.org )
5 // Copyright (c) 2006-2011 aMule Team ( admin@amule.org / http://www.amule.org )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
10 //
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
24 //
25 
26 
27 #ifndef THREADSCHEDULER_H
28 #define THREADSCHEDULER_H
29 
30 #include <deque>
31 #include <map>
32 
33 #include "Types.h"
34 #include "MuleThread.h"
35 
36 
37 class CThreadTask;
38 
39 
40 //! The priority values of tasks.
41 enum ETaskPriority
42 {
43 	ETP_Low = 0,
44 	ETP_Normal,
45 	ETP_High,
46 	//! For tasks such as finding shared files and ipfilter.dat loading only.
47 	ETP_Critical
48 };
49 
50 
51 /**
52  * This class mananges scheduling of background tasks.
53  *
54  * Currently it is assumed that all tasks are IO intensive,
55  * so that only a single task is allowed to proceed at any
56  * one time. All threads are run in lowest priority mode.
57  *
58  * Tasks are sorted by priority (see ETaskPriority) and age.
59  *
60  * Note that the scheduler starts in suspended mode, in
61  * which tasks are queued but not executed. Call Start()
62  * to begin execution of the tasks.
63  */
64 class CThreadScheduler
65 {
66 public:
67 	/** Starts execution of queued tasks. */
68 	static void Start();
69 
70 	/**
71 	 * Terminates task execution and frees the scheduler object.
72 	 *
73 	 * Tasks added after this are discarded.
74 	 */
75 	static void Terminate();
76 
77 
78 	/**
79 	 * Adds a new task to the queue, returning true if the task was queued.
80 	 *
81 	 * Before the task is queued, it is checked against the
82 	 * existing tasks based on type and description. If an
83 	 * matching task already exists, this task-object is
84 	 * discarded. The task is also discarded if the scheduler
85 	 * has been terminated. If 'overwrite' is true, any
86 	 * existing duplicate task is dropped, and if already
87 	 * running, terminated.
88 	 *
89 	 * Note: This function takes ownership of the task.
90 	 *
91 	 * @see Start
92 	 * @see Terminate
93 	 */
94 	static bool AddTask(CThreadTask* task, bool overwrite = false);
95 
96 private:
97 	CThreadScheduler();
98 	~CThreadScheduler();
99 
100 	/** Returns the number of tasks on the queue. */
101 	size_t GetTaskCount() const;
102 
103 	/** Tries to add the given task to the queue, returning true on success. */
104 	bool DoAddTask(CThreadTask* task, bool overwrite);
105 
106 	/** Creates the actual scheduler thread if none exist. */
107 	void CreateSchedulerThread();
108 
109 	/** Entry function called via internal thread-object. */
110 	void* Entry();
111 
112 	//! Contains a task and its age.
113 	typedef std::pair<CThreadTask*, uint32> CEntryPair;
114 
115 	//! List of currently scheduled tasks.
116 	std::deque<CEntryPair> m_tasks;
117 
118 	//! Specifies if tasks should be resorted by priority.
119 	bool	m_tasksDirty;
120 
121 	typedef std::map<wxString, CThreadTask*> CDescMap;
122 	typedef std::map<wxString, CDescMap> CTypeMap;
123 	//! Map of current task by type -> desc. Used to avoid duplicate tasks.
124 	CTypeMap m_taskDescs;
125 
126 	//! The actual worker thread.
127 	CMuleThread* m_thread;
128 	//! The currently running task, if any.
129 	CThreadTask* m_currentTask;
130 
131 	friend class CTaskThread;
132 	friend struct CTaskSorter;
133 };
134 
135 
136 /**
137  * Base-class of all threaded tasks.
138  *
139  * This class acts as a pseudo-thread, and is transparently
140  * executed on a worker thread by the CThreadScheduler
141  * class.
142  *
143  * Note that the task type should be an unique description
144  * of the task type, as it is used to detect completion of
145  * all tasks of a given type and in duplicate detection
146  * with the description. The description should be unique
147  * for the given task, such that duplicates can be discovered.
148  */
149 class CThreadTask
150 {
151 public:
152 	/**
153 	 * @param type Should be a name constant among tasks of the type (hashing, completion, etc).
154 	 * @param desc Should be an unique description for this task, for detecting duplicates.
155 	 * @param priority Decides how soon the task will be carried out.
156 	 */
157 	CThreadTask(const wxString& type, const wxString& desc, ETaskPriority priority = ETP_Normal);
158 
159 	/** Needed since CThreadScheduler only works with CThreadTask pointers. */
160 	virtual ~CThreadTask();
161 
162 	/** Returns the task type, used for debugging and duplicate detection. */
163 	const wxString& GetType() const;
164 
165 	/** Returns the task description, used for debugging and duplicate detection. */
166 	const wxString& GetDesc() const;
167 
168 	/** Returns the priority of the task. Used when selecting the next task. */
169 	ETaskPriority GetPriority() const;
170 
171 protected:
172 	//! @see wxThread::Entry
173 	virtual void Entry() = 0;
174 
175 	/** Called when the last task of a specific type has been completed. */
176 	virtual void OnLastTask();
177 
178 	/** @see wxThread::OnExit */
179 	virtual void OnExit();
180 
181 	/** @see wxThread::TestDestroy */
182 	bool TestDestroy() const;
183 
184 private:
185 	wxString m_type;
186 	wxString m_desc;
187 	ETaskPriority m_priority;
188 
189 	//! The owner (scheduler), used when calling TestDestroy.
190 	CMuleThread* m_owner;
191 	//! Specifies if the specifc task should be aborted.
192 	bool m_abort;
193 
194 	friend class CThreadScheduler;
195 };
196 
197 #endif
198 // File_checked_for_headers
199