1 | #include "msgqueue.h"
|
---|
2 |
|
---|
3 | #include <iostream>
|
---|
4 |
|
---|
5 | using namespace std;
|
---|
6 |
|
---|
7 | // --------------------------------------------------------------------------
|
---|
8 | //
|
---|
9 | // This creates the Message queue thread,
|
---|
10 | //
|
---|
11 | MsgQueue::MsgQueue() : fState(kRun), fThread(std::bind(&MsgQueue::Thread, this))
|
---|
12 | {
|
---|
13 | }
|
---|
14 |
|
---|
15 | // --------------------------------------------------------------------------
|
---|
16 | //
|
---|
17 | // The destructor terminates the thread.
|
---|
18 | //
|
---|
19 | MsgQueue::~MsgQueue()
|
---|
20 | {
|
---|
21 | CancelThread();
|
---|
22 | }
|
---|
23 |
|
---|
24 | void MsgQueue::CancelThread()
|
---|
25 | {
|
---|
26 | const std::lock_guard<std::mutex> lock(fMutex);
|
---|
27 | if (fState!=kIdle)
|
---|
28 | return;
|
---|
29 |
|
---|
30 | fState = kAbort;
|
---|
31 | fCond.notify_one();
|
---|
32 | fThread.join();
|
---|
33 | }
|
---|
34 |
|
---|
35 | // --------------------------------------------------------------------------
|
---|
36 | //
|
---|
37 | // This is the function which must be overloaded.
|
---|
38 | // Here you process the messages. mp is a pointer which you can
|
---|
39 | // specify when posting the message.
|
---|
40 | //
|
---|
41 | // If a new messages is posted while the old one is not yet
|
---|
42 | // finished the fBreak flag is set. Please test this flag with
|
---|
43 | // Break() and try to finish (or stop) the current action as soon
|
---|
44 | // as possible. This makes sure, that before a new action is started
|
---|
45 | // the old action can be finished correctly by the user.
|
---|
46 | //
|
---|
47 | int MsgQueue::Proc(int msg, void *mp)
|
---|
48 | {
|
---|
49 | return 0;
|
---|
50 | }
|
---|
51 |
|
---|
52 | int MsgQueue::Break() const
|
---|
53 | {
|
---|
54 | return fSize>0 || fState!=kRun;
|
---|
55 | }
|
---|
56 |
|
---|
57 | // --------------------------------------------------------------------------
|
---|
58 | //
|
---|
59 | // This is the thread which handles the processing.
|
---|
60 | // As soon as a message is posted the fBreak flag is set (see PostMsg)
|
---|
61 | // And as soon as the current action is finished the new action is executed
|
---|
62 | // in this thread. This makes sure, that the calling program is not stalled.
|
---|
63 | //
|
---|
64 | void MsgQueue::Thread()
|
---|
65 | {
|
---|
66 | std::unique_lock<std::mutex> lock(fMutex);
|
---|
67 |
|
---|
68 | while (1)
|
---|
69 | {
|
---|
70 | while (fList.empty() && fState==kRun)
|
---|
71 | fCond.wait(lock);
|
---|
72 |
|
---|
73 | if (fState==kAbort)
|
---|
74 | break;
|
---|
75 |
|
---|
76 | if (fState==kStop && fList.empty())
|
---|
77 | break;
|
---|
78 |
|
---|
79 | const auto &val = fList.front();
|
---|
80 | fSize--;
|
---|
81 |
|
---|
82 | lock.unlock();
|
---|
83 | Proc(val.first, const_cast<char*>(val.second.data()));
|
---|
84 | lock.lock();
|
---|
85 |
|
---|
86 | fList.pop_front();
|
---|
87 | }
|
---|
88 |
|
---|
89 | fList.clear();
|
---|
90 | fSize = 0;
|
---|
91 |
|
---|
92 | fState = kIdle;
|
---|
93 | }
|
---|
94 |
|
---|
95 |
|
---|
96 | // --------------------------------------------------------------------------
|
---|
97 | //
|
---|
98 | // Use this function to post a message.
|
---|
99 | // mp can be a pointer to a data structure. size should be the size of it.
|
---|
100 | // size bytes of this structure are copied and a pointer to the copy
|
---|
101 | // is forwarded to the Proc function.
|
---|
102 | //
|
---|
103 | void *MsgQueue::PostMsg(int msg, void *mp, int size)
|
---|
104 | {
|
---|
105 | const std::lock_guard<std::mutex> lock(fMutex);
|
---|
106 | if (fState==kIdle)
|
---|
107 | return false;
|
---|
108 |
|
---|
109 | fSize++;
|
---|
110 | fList.emplace_back(msg, vector<char>(reinterpret_cast<char*>(mp),reinterpret_cast<char*>(mp)+size));
|
---|
111 |
|
---|
112 | fCond.notify_one();
|
---|
113 |
|
---|
114 | return 0;
|
---|
115 |
|
---|
116 | }
|
---|