source: trunk/MagicSoft/Cosy/base/msgqueue.cc@ 8618

Last change on this file since 8618 was 8376, checked in by tbretz, 18 years ago
*** empty log message ***
File size: 6.5 KB
Line 
1#include "msgqueue.h"
2
3#include <iostream>
4
5#include <unistd.h> // usleep
6#include <sys/resource.h> // PRIO_PROCESS
7
8#undef DEBUG
9
10using namespace std;
11
12// --------------------------------------------------------------------------
13//
14// This creates the Message queue thread,
15//
16MsgQueue::MsgQueue() : fBreak(0)
17{
18 fMp = new unsigned char;
19 pthread_create(&fThread, NULL, MapThread, this);
20}
21
22// --------------------------------------------------------------------------
23//
24// The destructor terminates the thread.
25//
26MsgQueue::~MsgQueue()
27{
28#ifdef DEBUG
29 cout << "~MsgQueue::MsgQueue" << endl;
30#endif
31 pthread_cancel(fThread);
32 delete (unsigned char*)fMp;
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//
47void *MsgQueue::Proc(int msg, void *mp)
48{
49 return NULL;
50}
51
52// --------------------------------------------------------------------------
53//
54// This is the thread mapper.
55//
56void *MsgQueue::MapThread(void *arg)
57{
58 pthread_detach(pthread_self());
59
60 setpriority(PRIO_PROCESS, 0, -5);
61
62 ((MsgQueue*)arg)->Thread();
63
64 return NULL;
65}
66
67// --------------------------------------------------------------------------
68//
69// This is the thread which handles the processing.
70// As soon as a message is posted the fBreak flag is set (see PostMsg)
71// And as soon as the current action is finished the new action is executed
72// in this thread. This makes sure, that the calling program is not stalled.
73//
74void MsgQueue::Thread()
75{
76 //
77 // Tell the poster that processing is done
78 //
79 fStart = 0;
80 while (!fBreak)
81 usleep(1);
82
83 while(1)
84 {
85 while (!fStart)
86 usleep(1);
87 fStart = 0;
88
89 //
90 // This makes sure that also a very fast Break() after
91 // a PostMsg is processed correctly
92 //
93 if (fMuxMsg.Lock()==13)
94 cout << "MsgQueue::Thread - mutex is already locked by this thread." << endl;
95 fBreak = 0;
96 if (fMuxMsg.UnLock()==13)
97 cout << "MsgQueue::Thread - tried to unlock mutex locked by other thread." << endl;
98
99#ifdef DEBUG
100 cout << "MsgQueue::Thread: Processing Msg 0x" << hex << fMsg << endl;
101#endif
102 // --- bool quit = fMsg==WM_QUIT;
103 fRc=Proc(fMsg, fMp);
104#ifdef DEBUG
105 cout << "MsgQueue::PostMsg: Msg 0x" << hex << fMsg << " processed (rc=" << fRc << ")" << endl;
106#endif
107
108 // --- if (quit)
109 // --- break;
110 }
111
112 // --- fStart = 0;
113 // --- cout << "WM_QUIT posted... leaving msg queue." << endl;
114}
115
116// --------------------------------------------------------------------------
117//
118// Use this function to post a message.
119// mp can be a pointer to a data structure. size should be the size of it.
120// size bytes of this structure are copied and a pointer to the copy
121// is forwarded to the Proc function.
122//
123void *MsgQueue::PostMsg(int msg, void *mp, int size)
124{
125 //
126 // Lock Mutex, put msg on stack and tell thread to process message
127 //
128
129 //
130 // Make sure that only one Proc() is running and can be stopped
131 // stopped and the messages are processed serialized
132 //
133#ifdef DEBUG
134 cout << "MsgQueue::PostMsg: Locking MsgQueue mutex..." << flush;
135#endif
136 if (fMuxMsg.Lock()==13)
137 cout << "MsgQueue::PostMsg - mutex is already locked by this thread." << endl;
138#ifdef DEBUG
139 cout << "done." << endl;
140#endif
141
142 //
143 // Set break state and wait until Proc() returned (break state deleted)
144 // This means, that a new command is invoked and (if forseen) the
145 // running command should stop execution.
146 //
147 // This is some kind of controlled user break without using signals
148 //
149 /**** NEW 20/01/2003 ****/
150 if (fBreak)
151 {
152 if (fMuxMsg.UnLock()==13)
153 cout << "MsgQueue::PostMsg - tried to unlock mutex locked by other thread." << endl;
154#ifdef DEBUG
155 cout << "------------> MsgQueue::PostMsg: Proc still pending... Message IGNORED." << endl;
156#endif
157 return NULL;
158 }
159 /**** NEW 20/01/2003 ****/
160#ifdef DEBUG
161 cout << "MsgQueue::PostMsg: ---> Break <---" << endl;
162#endif
163 fBreak = 1;
164
165 //
166 // copy return code from Proc() and set new message
167 //
168 void *rc = fRc;
169
170 fMsg = msg;
171
172 delete (unsigned char*)fMp;
173 fMp = new unsigned char[size];
174
175 memcpy(fMp, mp, size);
176
177 //
178 // Start Proc()
179 //
180#ifdef DEBUG
181 cout << "MsgQueue::PostMsg: Releasing MsgQueue mutex..." << flush;
182#endif
183 fStart = 1;
184 if (fMuxMsg.UnLock()==13)
185 cout << "MsgQueue::PostMsg - tried to unlock mutex locked by other thread." << endl;
186#ifdef DEBUG
187 cout << "done." << endl;
188#endif
189
190 /*
191 * **** NEW 20/01/2003 ***
192 *
193 * This can halt the main thread, because it is waiting until
194 * Proc has finished its execution which can take a while
195 *
196 * A side effect is, because you don't wait for the end of
197 * the execution of Proc, if a new message is posted fBreak
198 * and fStart is set again, new values are copied to fMsg and
199 * fMp (FIXME? Harmefull?) and the message is not processed at all.
200 */
201 //while (fStart)
202 // usleep(1);
203
204#ifdef DEBUG
205 cout << "MsgQueue::PostMsg: Returning rc = " << hex << rc << endl;
206#endif
207 return rc;
208}
209/*
210Start positioning.
211MsgQueue::PostMsg: Locking MsgQueue mutex...done.
212MsgQueue::PostMsg: ---> Break <---
213+++++ MsgQueue::PostMsg: Releasing MsgQueue mutex...done.
214
215===== MsgQueue::PostMsg: Returning rc = (nil)
216PostMsg (WM_Position) returned.
217done.
218Stopping movement...Movement stopped.
219WM_Position: done. (return 0x7777)
220MsgQueue::PostMsg: Msg 0x1001 processed (rc=0x7777)
221MsgQueue::Thread: Processing Msg 0x1001
222WM_Position: start.
223Positioning to Target...
224 */
225/*
226Start positioning.
227MsgQueue::PostMsg: Locking MsgQueue mutex...done.
228MsgQueue::PostMsg: ---> Break <---
229+++++ MsgQueue::PostMsg: Releasing MsgQueue mutex...done.
230
231done.
232Stopping movement...Movement stopped.
233WM_Position: done. (return 0x7777)
234MsgQueue::PostMsg: Msg 0x1001 processed (rc=0x7777)
235MsgQueue::Thread: Processing Msg 0x1001
236WM_Position: start.
237Positioning to Target...
238===== MsgQueue::PostMsg: Returning rc = (nil)
239*/
Note: See TracBrowser for help on using the repository browser.