1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#ifndef JOBQUEUE_H
#define JOBQUEUE_H 1
#include <string>
#include <map>
#include <list>
#include <wx/frame.h>
#include <wx/thread.h>
#include <wx/menu.h>
#include <wx/app.h>
#include "UpdateFactory.hpp"
class JobArgs
{
public:
JobArgs()
: jobid(-1), hostname(""), port(0),
update_file(""), password("") {}
JobArgs(int jobid, UpdateFactory& uf)
: jobid(jobid), hostname(uf.getHostname()),
port(uf.getPort()), update_file(uf.getUpdateFile()),
password(uf.getPassword()) {}
JobArgs(int jobid, const char *hostname, int port,
const char *update_file, const char *password)
: jobid(jobid), hostname(hostname), port(port),
update_file(update_file), password(password) {}
JobArgs(int jobid, std::string& hostname, int port,
std::string& update_file, std::string& password)
: jobid(jobid), hostname(hostname), port(port),
update_file(update_file), password(password) {}
/** randomized (not unique) Job ID */
int jobid;
/* minimum required data for our UpdateFactory */
std::string hostname;
int port;
std::string update_file;
std::string password;
};
class Job
{
public:
enum JobEvents
{
/* thread should exit or wants to exit */
eID_THREAD_EXIT = wxID_HIGHEST + 1000,
/* dummy command */
eID_THREAD_NULL,
/* worker thread has started OK */
eID_THREAD_STARTED,
/* process normal job */
eID_THREAD_JOB,
/* process different messages in the frontend */
eID_THREAD_MSG,
eID_THREAD_MSGOK,
eID_THREAD_MSGERR
};
Job() : m_cmd(eID_THREAD_NULL) {}
Job(JobEvents cmd, JobArgs arg) : m_cmd(cmd), m_Arg(arg) {}
Job(JobEvents cmd, int jobid, UpdateFactory& uf) : m_cmd(cmd), m_Arg(jobid, uf) {}
JobEvents m_cmd;
JobArgs m_Arg;
};
class Queue
{
public:
enum JobPriority { eHIGHEST, eHIGHER, eNORMAL, eBELOW_NORMAL, eLOW, eIDLE };
Queue(wxEvtHandler *pParent) : m_pParent(pParent), m_busyWorker(0), m_totalJobsDone(0) {}
/* push a job with given priority class onto the FIFO */
void AddJob(const Job& job, const JobPriority& priority = eNORMAL);
Job Pop();
/* report back to parent */
void Report(const Job::JobEvents& cmd, const wxString& sArg = wxEmptyString, int iArg = 0);
size_t Stacksize()
{
wxMutexLocker lock(m_MutexQueue);
return m_Jobs.size();
}
size_t getBusyWorker() {
wxMutexLocker lock(m_MutexBusyWorker);
return m_busyWorker;
}
size_t getTotalJobsDone() {
wxMutexLocker lock(m_MutexBusyWorker);
return m_totalJobsDone;
}
void resetTotalJobsDone() {
wxMutexLocker lock(m_MutexBusyWorker);
m_totalJobsDone = 0;
}
void incBusyWorker() {
wxMutexLocker lock(m_MutexBusyWorker);
m_busyWorker++;
}
void decBusyWorker() {
wxMutexLocker lock(m_MutexBusyWorker);
if (m_busyWorker > 0) m_busyWorker--;
m_totalJobsDone++;
}
private:
/** main GUI EventHandler */
wxEvtHandler *m_pParent;
/** a priority Queue using std::multimap */
std::multimap<JobPriority, Job> m_Jobs;
wxMutex m_MutexQueue, m_MutexBusyWorker;
wxSemaphore m_QueueCount;
size_t m_busyWorker, m_totalJobsDone;
};
class WorkerThread : public wxThread
{
public:
WorkerThread(Queue *pQueue, int id = 0) : m_pQueue(pQueue), m_ID(id) { assert(pQueue); wxThread::Create(); }
private:
Queue *m_pQueue;
int m_ID;
wxThread::ExitCode doWork();
virtual wxThread::ExitCode Entry() { return this->doWork(); }
void doJob();
virtual void OnJob() { return this->doJob(); }
};
#endif
|