xref: /haiku/headers/private/debugger/util/Worker.h (revision 385ee03ba83b7a40d315e17b03031b3ca37820c0)
1 /*
2  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2014, Rene Gollent, rene@gollent.com.
4  * Distributed under the terms of the MIT License.
5  */
6 #ifndef WORKER_H
7 #define WORKER_H
8 
9 #include <Locker.h>
10 
11 #include <ObjectList.h>
12 #include <Referenceable.h>
13 #include <String.h>
14 #include <util/DoublyLinkedList.h>
15 #include <util/OpenHashTable.h>
16 
17 
18 class Job;
19 class Worker;
20 
21 
22 enum job_state {
23 	JOB_STATE_UNSCHEDULED,
24 	JOB_STATE_WAITING,
25 	JOB_STATE_ACTIVE,
26 	JOB_STATE_ABORTED,
27 	JOB_STATE_FAILED,
28 	JOB_STATE_SUCCEEDED
29 };
30 
31 enum job_wait_status {
32 	JOB_DEPENDENCY_NOT_FOUND,
33 	JOB_DEPENDENCY_SUCCEEDED,
34 	JOB_DEPENDENCY_FAILED,
35 	JOB_DEPENDENCY_ABORTED,
36 	JOB_DEPENDENCY_ACTIVE,
37 
38 	JOB_USER_INPUT_WAITING
39 		// internal only
40 };
41 
42 
43 class JobKey {
44 public:
45 	virtual						~JobKey();
46 
47 	virtual	size_t				HashValue() const = 0;
48 
49 	virtual	bool				operator==(const JobKey& other) const = 0;
50 };
51 
52 
53 struct SimpleJobKey : public JobKey {
54 			const void*			object;
55 			uint32				type;
56 
57 public:
58 								SimpleJobKey(const void* object, uint32 type);
59 								SimpleJobKey(const SimpleJobKey& other);
60 
61 	virtual	size_t				HashValue() const;
62 
63 	virtual	bool				operator==(const JobKey& other) const;
64 
65 			SimpleJobKey&		operator=(const SimpleJobKey& other);
66 };
67 
68 
69 class JobListener {
70 public:
71 	virtual						~JobListener();
72 
73 	virtual	void				JobStarted(Job* job);
74 	virtual	void				JobDone(Job* job);
75 	virtual	void				JobWaitingForInput(Job* job);
76 	virtual	void				JobFailed(Job* job);
77 	virtual	void				JobAborted(Job* job);
78 };
79 
80 
81 typedef DoublyLinkedList<Job> JobList;
82 
83 
84 class Job : public BReferenceable, public DoublyLinkedListLinkImpl<Job> {
85 public:
86 								Job();
87 	virtual						~Job();
88 
89 	virtual	const JobKey&		Key() const = 0;
90 	virtual	status_t			Do() = 0;
91 
92 			Worker*				GetWorker() const	{ return fWorker; }
93 			job_state			State() const		{ return fState; }
94 
95 			const BString&		GetDescription() const
96 									{ return fDescription; }
97 
98 protected:
99 			job_wait_status		WaitFor(const JobKey& key);
100 			status_t			WaitForUserInput();
101 			void				SetDescription(const char* format, ...);
102 
103 private:
104 			friend class Worker;
105 
106 private:
107 			void				SetWorker(Worker* worker);
108 			void				SetState(job_state state);
109 
110 			Job*				Dependency() const	{ return fDependency; }
111 			void				SetDependency(Job* job);
112 
113 			JobList&			DependentJobs()		{ return fDependentJobs; }
114 
115 			job_wait_status		WaitStatus() const	{ return fWaitStatus; }
116 			void				SetWaitStatus(job_wait_status status);
117 
118 			status_t			AddListener(JobListener* listener);
119 			void				RemoveListener(JobListener* listener);
120 			void				NotifyListeners();
121 
122 private:
123 	typedef BObjectList<JobListener> ListenerList;
124 
125 private:
126 			Worker*				fWorker;
127 			job_state			fState;
128 			Job*				fDependency;
129 			JobList				fDependentJobs;
130 			job_wait_status		fWaitStatus;
131 			ListenerList		fListeners;
132 			BString				fDescription;
133 
134 public:
135 			Job*				fNext;
136 };
137 
138 
139 class Worker {
140 public:
141 								Worker();
142 								~Worker();
143 
144 			status_t			Init();
145 			void				ShutDown();
146 
147 			bool				Lock()		{ return fLock.Lock(); }
148 			void				Unlock()	{ fLock.Unlock(); }
149 
150 			status_t			ScheduleJob(Job* job,
151 									JobListener* listener = NULL);
152 										// always takes over reference
153 			void				AbortJob(const JobKey& key);
154 			Job*				GetJob(const JobKey& key);
155 
156 			status_t			ResumeJob(Job* job);
157 									// only valid for jobs that are
158 									// suspended pending user input
159 
160 			bool				HasPendingJobs();
161 
162 			status_t			AddListener(const JobKey& key,
163 									JobListener* listener);
164 			void				RemoveListener(const JobKey& key,
165 									JobListener* listener);
166 
167 private:
168 			friend class Job;
169 
170 			struct JobHashDefinition {
171 				typedef JobKey	KeyType;
172 				typedef	Job		ValueType;
173 
174 				size_t HashKey(const JobKey& key) const
175 				{
176 					return key.HashValue();
177 				}
178 
179 				size_t Hash(Job* value) const
180 				{
181 					return HashKey(value->Key());
182 				}
183 
184 				bool Compare(const JobKey& key, Job* value) const
185 				{
186 					return value->Key() == key;
187 				}
188 
189 				Job*& GetLink(Job* value) const
190 				{
191 					return value->fNext;
192 				}
193 			};
194 
195 			typedef BOpenHashTable<JobHashDefinition> JobTable;
196 
197 private:
198 			job_wait_status		WaitForJob(Job* waitingJob, const JobKey& key);
199 			status_t			WaitForUserInput(Job* waitingJob);
200 
201 	static	status_t			_WorkerLoopEntry(void* data);
202 			status_t			_WorkerLoop();
203 
204 			void				_ProcessJobs();
205 			void				_AbortJob(Job* job, bool removeFromTable);
206 			void				_FinishJob(Job* job);
207 
208 private:
209 			BLocker				fLock;
210 			JobTable			fJobs;
211 			JobList				fUnscheduledJobs;
212 			JobList				fAbortedJobs;
213 			JobList				fSuspendedJobs;
214 			sem_id				fWorkToDoSem;
215 			thread_id			fWorkerThread;
216 	volatile bool				fTerminating;
217 };
218 
219 
220 #endif	// WORKER_H
221