2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
26 * $XConsortium: Notifier.C /main/4 1996/04/21 19:42:47 drk $
28 * RESTRICTED CONFIDENTIAL INFORMATION:
30 * The information in this document is subject to special
31 * restrictions in a confidential disclosure agreement between
32 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
33 * document outside HP, IBM, Sun, USL, SCO, or Univel without
34 * Sun's specific written approval. This document and all copies
35 * and derivative works thereof must be returned or destroyed at
38 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
46 #include "Notifier.hh"
48 NotifyEvent::NotifyEvent(void)
52 NotifyEvent::~NotifyEvent(void)
57 NotifyEvent::eventTriggered(void)
59 assert(!"Pure virtual NotifyEvent::eventTriggered called");
62 Notifier::EventKey::EventKey(void * key)
63 : ObjectKey("Notifier::EventKey")
68 Notifier::EventKey::~EventKey(void)
72 Notifier::EventKey::operator==(ObjectKey & other)
74 EventKey * ok = (EventKey *)&other;
76 return(_key == ok->_key);
79 Notifier::EventKey::operator!=(ObjectKey & other)
81 EventKey * ok = (EventKey *)&other;
83 return(_key != ok->_key);
86 Notifier::EventKey::operator<(ObjectKey & other)
88 EventKey * ok = (EventKey *)&other;
90 return(_key < ok->_key);
93 Notifier::EventKey::operator>(ObjectKey & other)
95 EventKey * ok = (EventKey *)&other;
97 return(_key > ok->_key);
100 Notifier::EventKey::operator<=(ObjectKey & other)
102 EventKey * ok = (EventKey *)&other;
104 return(_key <= ok->_key);
107 Notifier::EventKey::operator>=(ObjectKey & other)
109 EventKey * ok = (EventKey *)&other;
111 return(_key >= ok->_key);
115 Notifier::EventKey::hashValue(void)
117 unsigned long lkey = (unsigned long)_key;
119 return(((lkey >> 16) & 0xffff) ^ (lkey & 0xffff));
122 // These constants are used to keep the ends of the pipe straight.
124 static const int READ = 0;
125 static const int WRITE = 1;
127 Notifier::Notifier(XtAppContext context)
128 : _events(5), // Pending events that need to be sent.
129 _timer_events(8) // Events for timing.
131 // Create a pipe for sending events.
135 // Register the input file descriptor for callback.
137 XtAppAddInput(context,
139 (XtPointer)(XtInputReadMask | XtInputExceptMask),
147 Notifier::deleteTimerEvent(ObjectKey &, TimerEvent * event, void *)
149 XtRemoveTimeOut(event->id);
155 Notifier::~Notifier(void)
159 close(_event_fds[READ]);
160 close(_event_fds[WRITE]);
162 // We need to run through all of the pending events. They may
163 // be interesting to the recipient and should be delivered before
166 while (_events.length()) {
167 NotifyEvent * event = _events[0];
168 event->eventTriggered();
173 // Now we want to throw away all of the events we have laying about
174 // for timers and signals.
176 _timer_events.forEach(deleteTimerEvent, NULL);
180 Notifier::notify(NotifyEvent & event, DtMailBoolean fast_path)
182 // The fast path means use an immediate call. Really pretty
183 // simple. Fire the event and throw away the memory for it.
185 if (fast_path == DTM_TRUE) {
186 event.eventTriggered();
190 // A little more complex. We will add the event to the queue, and
191 // send a byte through the pipe. This will cause us to wake up
192 // later, after going through the queue.
194 _events.append(&event);
197 write(_event_fds[WRITE], &bogus_buf, 1);
202 Notifier::addInterval(int interval_ms,
203 DtMailBoolean multi_shot,
206 TimerEvent * t_event = new TimerEvent;
208 t_event->interval = interval_ms;
209 t_event->multi_shot = multi_shot;
210 t_event->event = &event;
212 t_event->id = XtAppAddTimeOut(_context, interval_ms, timerProc, this);
214 EventKey * key = new EventKey((void *)t_event->id);
215 _timer_events.set(*key, t_event);
221 Notifier::removeInterval(IntervalId id)
223 // The Id is really the TimerEvent structure pointer. We don't have
224 // a key for these objects so we will have to enumerate the entire
225 // list of timer events until we find the appropriate key.
227 TimerEvent * t_event = (TimerEvent *)id;
230 t_srch.srch_event = t_event;
233 _timer_events.forEach(searchTimer, &t_srch);
236 _timer_events.remove(*t_srch.key);
237 delete t_event->event;
245 Notifier::eventProc(XtPointer client_data, int * fd, XtInputId *)
247 Notifier * self = (Notifier *)client_data;
249 // There was activity on the pipe. Read one byte, and fire one
250 // event. We don't want to fire more than that or we will run
251 // the risk of spending too much time in the callbacks.
254 read(*fd, &bogus_buf, 1);
256 if (self->_events.length()) {
257 NotifyEvent * event = self->_events[0];
258 event->eventTriggered();
260 self->_events.remove(0);
267 Notifier::timerProc(XtPointer client_data, XtIntervalId *id)
269 Notifier * self = (Notifier *)client_data;
270 EventKey key((void *)*id);
272 TimerEvent * t_event = self->_timer_events.lookup(key);
278 t_event->event->eventTriggered();
280 // We remove the event from the list. We do this because the
281 // key will change because we will get a new interval id.
283 self->_timer_events.remove(key);
285 // If this is a multi-shot event we have to register it again.
287 if (t_event->multi_shot == DTM_TRUE) {
288 t_event->id = XtAppAddTimeOut(self->_context,
292 EventKey * new_key = new EventKey((void *)t_event->id);
293 self->_timer_events.set(*new_key, t_event);
296 delete t_event->event;
302 Notifier::searchTimer(ObjectKey & key, TimerEvent * event, void * client_data)
304 TimerSearch * srch = (TimerSearch *)client_data;
306 if (event == srch->srch_event) {
307 srch->key = (EventKey *)&key;