1495676caSIngo Weinhold/*
27483c98dSIngo Weinhold * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
34605febaSRene Gollent * Copyright 2014, Rene Gollent, rene@gollent.com.
4495676caSIngo Weinhold * Distributed under the terms of the MIT License.
5495676caSIngo Weinhold */
6495676caSIngo Weinhold#ifndef WORKER_H
7495676caSIngo Weinhold#define WORKER_H
8495676caSIngo Weinhold
9495676caSIngo Weinhold#include <Locker.h>
10495676caSIngo Weinhold
11495676caSIngo Weinhold#include <ObjectList.h>
12da4d62dbSIngo Weinhold#include <Referenceable.h>
139d9c74ecSRene Gollent#include <String.h>
14495676caSIngo Weinhold#include <util/DoublyLinkedList.h>
15495676caSIngo Weinhold#include <util/OpenHashTable.h>
16495676caSIngo Weinhold
17495676caSIngo Weinhold
18495676caSIngo Weinholdclass Job;
19495676caSIngo Weinholdclass Worker;
20495676caSIngo Weinhold
21495676caSIngo Weinhold
22495676caSIngo Weinholdenum job_state {
23495676caSIngo Weinhold	JOB_STATE_UNSCHEDULED,
24495676caSIngo Weinhold	JOB_STATE_WAITING,
25495676caSIngo Weinhold	JOB_STATE_ACTIVE,
26495676caSIngo Weinhold	JOB_STATE_ABORTED,
27495676caSIngo Weinhold	JOB_STATE_FAILED,
28495676caSIngo Weinhold	JOB_STATE_SUCCEEDED
29495676caSIngo Weinhold};
30495676caSIngo Weinhold
31495676caSIngo Weinholdenum job_wait_status {
32495676caSIngo Weinhold	JOB_DEPENDENCY_NOT_FOUND,
33495676caSIngo Weinhold	JOB_DEPENDENCY_SUCCEEDED,
34495676caSIngo Weinhold	JOB_DEPENDENCY_FAILED,
35495676caSIngo Weinhold	JOB_DEPENDENCY_ABORTED,
364605febaSRene Gollent	JOB_DEPENDENCY_ACTIVE,
374605febaSRene Gollent
384605febaSRene Gollent	JOB_USER_INPUT_WAITING
39495676caSIngo Weinhold		// internal only
40495676caSIngo Weinhold};
41495676caSIngo Weinhold
42495676caSIngo Weinhold
43da4d62dbSIngo Weinholdclass JobKey {
44da4d62dbSIngo Weinholdpublic:
45da4d62dbSIngo Weinhold	virtual						~JobKey();
46da4d62dbSIngo Weinhold
477483c98dSIngo Weinhold	virtual	size_t				HashValue() const = 0;
48da4d62dbSIngo Weinhold
49da4d62dbSIngo Weinhold	virtual	bool				operator==(const JobKey& other) const = 0;
50da4d62dbSIngo Weinhold};
51da4d62dbSIngo Weinhold
52da4d62dbSIngo Weinhold
53da4d62dbSIngo Weinholdstruct SimpleJobKey : public JobKey {
543fab5ae4SRene Gollent			const void*			object;
55da4d62dbSIngo Weinhold			uint32				type;
56da4d62dbSIngo Weinhold
57da4d62dbSIngo Weinholdpublic:
583fab5ae4SRene Gollent								SimpleJobKey(const void* object, uint32 type);
59da4d62dbSIngo Weinhold								SimpleJobKey(const SimpleJobKey& other);
60da4d62dbSIngo Weinhold
617483c98dSIngo Weinhold	virtual	size_t				HashValue() const;
62da4d62dbSIngo Weinhold
63da4d62dbSIngo Weinhold	virtual	bool				operator==(const JobKey& other) const;
64da4d62dbSIngo Weinhold
65da4d62dbSIngo Weinhold			SimpleJobKey&		operator=(const SimpleJobKey& other);
66495676caSIngo Weinhold};
67495676caSIngo Weinhold
68495676caSIngo Weinhold
69495676caSIngo Weinholdclass JobListener {
70495676caSIngo Weinholdpublic:
71495676caSIngo Weinhold	virtual						~JobListener();
72495676caSIngo Weinhold
739d9c74ecSRene Gollent	virtual	void				JobStarted(Job* job);
74495676caSIngo Weinhold	virtual	void				JobDone(Job* job);
759d9c74ecSRene Gollent	virtual	void				JobWaitingForInput(Job* job);
76495676caSIngo Weinhold	virtual	void				JobFailed(Job* job);
77495676caSIngo Weinhold	virtual	void				JobAborted(Job* job);
78495676caSIngo Weinhold};
79495676caSIngo Weinhold
80495676caSIngo Weinhold
81495676caSIngo Weinholdtypedef DoublyLinkedList<Job> JobList;
82495676caSIngo Weinhold
83495676caSIngo Weinhold
84c3e066cfSIngo Weinholdclass Job : public BReferenceable, public DoublyLinkedListLinkImpl<Job> {
85495676caSIngo Weinholdpublic:
86495676caSIngo Weinhold								Job();
87495676caSIngo Weinhold	virtual						~Job();
88495676caSIngo Weinhold
89da4d62dbSIngo Weinhold	virtual	const JobKey&		Key() const = 0;
90495676caSIngo Weinhold	virtual	status_t			Do() = 0;
91495676caSIngo Weinhold
92495676caSIngo Weinhold			Worker*				GetWorker() const	{ return fWorker; }
93495676caSIngo Weinhold			job_state			State() const		{ return fState; }
94495676caSIngo Weinhold
959d9c74ecSRene Gollent			const BString&		GetDescription() const
969d9c74ecSRene Gollent									{ return fDescription; }
979d9c74ecSRene Gollent
98495676caSIngo Weinholdprotected:
99495676caSIngo Weinhold			job_wait_status		WaitFor(const JobKey& key);
1004605febaSRene Gollent			status_t			WaitForUserInput();
1019d9c74ecSRene Gollent			void				SetDescription(const char* format, ...);
102495676caSIngo Weinhold
103495676caSIngo Weinholdprivate:
104495676caSIngo Weinhold			friend class Worker;
105495676caSIngo Weinhold
106495676caSIngo Weinholdprivate:
107495676caSIngo Weinhold			void				SetWorker(Worker* worker);
108495676caSIngo Weinhold			void				SetState(job_state state);
109495676caSIngo Weinhold
110495676caSIngo Weinhold			Job*				Dependency() const	{ return fDependency; }
111495676caSIngo Weinhold			void				SetDependency(Job* job);
112495676caSIngo Weinhold
113495676caSIngo Weinhold			JobList&			DependentJobs()		{ return fDependentJobs; }
114495676caSIngo Weinhold
115495676caSIngo Weinhold			job_wait_status		WaitStatus() const	{ return fWaitStatus; }
116495676caSIngo Weinhold			void				SetWaitStatus(job_wait_status status);
117495676caSIngo Weinhold
118495676caSIngo Weinhold			status_t			AddListener(JobListener* listener);
119495676caSIngo Weinhold			void				RemoveListener(JobListener* listener);
120495676caSIngo Weinhold			void				NotifyListeners();
121495676caSIngo Weinhold
122495676caSIngo Weinholdprivate:
123495676caSIngo Weinhold	typedef BObjectList<JobListener> ListenerList;
124495676caSIngo Weinhold
125495676caSIngo Weinholdprivate:
126495676caSIngo Weinhold			Worker*				fWorker;
127495676caSIngo Weinhold			job_state			fState;
128495676caSIngo Weinhold			Job*				fDependency;
129495676caSIngo Weinhold			JobList				fDependentJobs;
130495676caSIngo Weinhold			job_wait_status		fWaitStatus;
131495676caSIngo Weinhold			ListenerList		fListeners;
1329d9c74ecSRene Gollent			BString				fDescription;
1335147963dSStephan Aßmus
1345147963dSStephan Aßmuspublic:
1355147963dSStephan Aßmus			Job*				fNext;
136495676caSIngo Weinhold};
137495676caSIngo Weinhold
138495676caSIngo Weinhold
139495676caSIngo Weinholdclass Worker {
140495676caSIngo Weinholdpublic:
141495676caSIngo Weinhold								Worker();
142495676caSIngo Weinhold								~Worker();
143495676caSIngo Weinhold
144495676caSIngo Weinhold			status_t			Init();
145495676caSIngo Weinhold			void				ShutDown();
146495676caSIngo Weinhold
147495676caSIngo Weinhold			bool				Lock()		{ return fLock.Lock(); }
148495676caSIngo Weinhold			void				Unlock()	{ fLock.Unlock(); }
149495676caSIngo Weinhold
150495676caSIngo Weinhold			status_t			ScheduleJob(Job* job,
151495676caSIngo Weinhold									JobListener* listener = NULL);
152da4d62dbSIngo Weinhold										// always takes over reference
153495676caSIngo Weinhold			void				AbortJob(const JobKey& key);
1548b5ee111SIngo Weinhold			Job*				GetJob(const JobKey& key);
155495676caSIngo Weinhold
1564605febaSRene Gollent			status_t			ResumeJob(Job* job);
1574605febaSRene Gollent									// only valid for jobs that are
1584605febaSRene Gollent									// suspended pending user input
1594605febaSRene Gollent
160667361d7SRene Gollent			bool				HasPendingJobs();
161667361d7SRene Gollent
162495676caSIngo Weinhold			status_t			AddListener(const JobKey& key,
163495676caSIngo Weinhold									JobListener* listener);
164495676caSIngo Weinhold			void				RemoveListener(const JobKey& key,
165495676caSIngo Weinhold									JobListener* listener);
166495676caSIngo Weinhold
167495676caSIngo Weinholdprivate:
168495676caSIngo Weinhold			friend class Job;
169495676caSIngo Weinhold
170495676caSIngo Weinhold			struct JobHashDefinition {
171495676caSIngo Weinhold				typedef JobKey	KeyType;
172495676caSIngo Weinhold				typedef	Job		ValueType;
173495676caSIngo Weinhold
174495676caSIngo Weinhold				size_t HashKey(const JobKey& key) const
175495676caSIngo Weinhold				{
176495676caSIngo Weinhold					return key.HashValue();
177495676caSIngo Weinhold				}
178495676caSIngo Weinhold
179495676caSIngo Weinhold				size_t Hash(Job* value) const
180495676caSIngo Weinhold				{
181495676caSIngo Weinhold					return HashKey(value->Key());
182495676caSIngo Weinhold				}
183495676caSIngo Weinhold
1845147963dSStephan Aßmus				bool Compare(const JobKey& key, Job* value) const
185495676caSIngo Weinhold				{
186495676caSIngo Weinhold					return value->Key() == key;
187495676caSIngo Weinhold				}
188495676caSIngo Weinhold
1895147963dSStephan Aßmus				Job*& GetLink(Job* value) const
190495676caSIngo Weinhold				{
1915147963dSStephan Aßmus					return value->fNext;
192495676caSIngo Weinhold				}
193495676caSIngo Weinhold			};
194495676caSIngo Weinhold
1955147963dSStephan Aßmus			typedef BOpenHashTable<JobHashDefinition> JobTable;
196495676caSIngo Weinhold
197495676caSIngo Weinholdprivate:
198495676caSIngo Weinhold			job_wait_status		WaitForJob(Job* waitingJob, const JobKey& key);
1994605febaSRene Gollent			status_t			WaitForUserInput(Job* waitingJob);
200495676caSIngo Weinhold
201495676caSIngo Weinhold	static	status_t			_WorkerLoopEntry(void* data);
202495676caSIngo Weinhold			status_t			_WorkerLoop();
203495676caSIngo Weinhold
2041f80f2eeSRene Gollent			void				_ProcessJobs();
205495676caSIngo Weinhold			void				_AbortJob(Job* job, bool removeFromTable);
206495676caSIngo Weinhold			void				_FinishJob(Job* job);
207495676caSIngo Weinhold
208495676caSIngo Weinholdprivate:
209495676caSIngo Weinhold			BLocker				fLock;
210495676caSIngo Weinhold			JobTable			fJobs;
211495676caSIngo Weinhold			JobList				fUnscheduledJobs;
212495676caSIngo Weinhold			JobList				fAbortedJobs;
2134605febaSRene Gollent			JobList				fSuspendedJobs;
214495676caSIngo Weinhold			sem_id				fWorkToDoSem;
215495676caSIngo Weinhold			thread_id			fWorkerThread;
216495676caSIngo Weinhold	volatile bool				fTerminating;
217495676caSIngo Weinhold};
218495676caSIngo Weinhold
219495676caSIngo Weinhold
220495676caSIngo Weinhold#endif	// WORKER_H
221