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
37class CThreadTask;
38
39
40//! The priority values of tasks.
41enum 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 */
64class CThreadScheduler
65{
66public:
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
96private:
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 */
149class CThreadTask
150{
151public:
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
171protected:
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
184private:
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