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

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