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