예제 #1
0
        public void deleteEvents(EventDeleter deleter)
        // The deleter that checks whether an event
        // should be removed.
        {
            lock (this)
            {
                TclEvent evt, prev;
                TclEvent servicedEvent = null;

                // Handle the special case of deletion of a single event that was just
                // processed by the serviceEvent() method.

                if (deleter == this)
                {
                    servicedEvent = this.servicedEvent;
                    if (servicedEvent == null)
                    {
                        throw new TclRuntimeError("servicedEvent was not set by serviceEvent()");
                    }
                    this.servicedEvent = null;
                }

                for (prev = null, evt = firstEvent; evt != null; evt = evt.next)
                {
                    if (((servicedEvent == null) && (deleter.deleteEvent(evt) == 1)) || (evt == servicedEvent))
                    {
                        if (evt == firstEvent)
                        {
                            firstEvent = evt.next;
                        }
                        else
                        {
                            prev.next = evt.next;
                        }
                        if (evt.next == null)
                        {
                            lastEvent = prev;
                        }
                        if (evt == markerEvent)
                        {
                            markerEvent = prev;
                        }
                        if (evt == servicedEvent)
                        {
                            servicedEvent = null;
                            break; // Just service this one event in the special case
                        }
                    }
                    else
                    {
                        prev = evt;
                    }
                }
                if (servicedEvent != null)
                {
                    throw new TclRuntimeError("servicedEvent was not removed from the queue");
                }
            }
        }
예제 #2
0
        private Notifier(System.Threading.Thread primaryTh)
        {
            primaryThread = primaryTh;
            firstEvent    = null;
            lastEvent     = null;
            markerEvent   = null;

            timerList       = new ArrayList(10);
            timerGeneration = 0;
            idleList        = new ArrayList(10);
            idleGeneration  = 0;
            timerPending    = false;
            refCount        = 0;
        }
예제 #3
0
        private TclEvent getAvailableEvent(TclEvent skipEvent)
        // Indicates that the given event should not
        // be returned.  This argument can be null.
        {
            lock (this)
            {
                TclEvent evt;

                for (evt = firstEvent; evt != null; evt = evt.next)
                {
                    if ((evt.isProcessing == false) && (evt.isProcessed == false) && (evt != skipEvent))
                    {
                        return(evt);
                    }
                }
                return(null);
            }
        }
예제 #4
0
		private Notifier(System.Threading.Thread primaryTh)
		{
			primaryThread = primaryTh;
			firstEvent = null;
			lastEvent = null;
			markerEvent = null;
			
			timerList = new ArrayList(10);
			timerGeneration = 0;
			idleList = new ArrayList(10);
			idleGeneration = 0;
			timerPending = false;
			refCount = 0;
		}
예제 #5
0
				private TclEvent getAvailableEvent(TclEvent skipEvent)
		// Indicates that the given event should not
		// be returned.  This argument can be null.
		{
			lock (this)
			{
				TclEvent evt;
				
				for (evt = firstEvent; evt != null; evt = evt.next)
				{
					if ((evt.isProcessing == false) && (evt.isProcessed == false) && (evt != skipEvent))
					{
						return evt;
					}
				}
				return null;
			}
		}
예제 #6
0
		internal  int serviceEvent(int flags)
		// Indicates what events should be processed.
		// May be any combination of TCL.WINDOW_EVENTS
		// TCL.FILE_EVENTS, TCL.TIMER_EVENTS, or other
		// flags defined elsewhere.  Events not
		// matching this will be skipped for processing
		// later.
		{
			TclEvent evt;
			
			// No event flags is equivalent to TCL_ALL_EVENTS.
			
			if ((flags & TCL.ALL_EVENTS) == 0)
			{
				flags |= TCL.ALL_EVENTS;
			}
			
			// Loop through all the events in the queue until we find one
			// that can actually be handled.
			
			evt = null;
			while ((evt = getAvailableEvent(evt)) != null)
			{
				// Call the handler for the event.  If it actually handles the
				// event then free the storage for the event.  There are two
				// tricky things here, both stemming from the fact that the event
				// code may be re-entered while servicing the event:
				//
				// 1. Set the "isProcessing" field to true. This is a signal to
				//    ourselves that we shouldn't reexecute the handler if the
				//    event loop is re-entered.
				// 2. When freeing the event, must search the queue again from the
				//    front to find it.  This is because the event queue could
				//    change almost arbitrarily while handling the event, so we
				//    can't depend on pointers found now still being valid when
				//    the handler returns.
				
				evt.isProcessing = true;
				
				if (evt.processEvent(flags) != 0)
				{
					evt.isProcessed = true;
					// Don't allocate/grab the monitor for the event unless sync()
					// has been called in another thread. This is thread safe
					// since sync() checks the isProcessed flag before calling wait.
					if (evt.needsNotify)
					{
						lock (evt)
						{
							System.Threading.Monitor.PulseAll(evt);
						}
					}
					// Remove this specific event from the queue
					servicedEvent = evt;
					deleteEvents(this);
					return 1;
				}
				else
				{
					// The event wasn't actually handled, so we have to
					// restore the isProcessing field to allow the event to be
					// attempted again.
					
					evt.isProcessing = false;
				}
				
				// The handler for this event asked to defer it.  Just go on to
				// the next event.
				
				continue;
			}
			return 0;
		}
예제 #7
0
		public  int deleteEvent(TclEvent evt)
		{
			throw new TclRuntimeError("The Notifier.deleteEvent() method should not be called");
		}
예제 #8
0
				public  void  deleteEvents(EventDeleter deleter)
		// The deleter that checks whether an event
		// should be removed.
		{
			lock (this)
			{
				TclEvent evt, prev;
				TclEvent servicedEvent = null;
				
				// Handle the special case of deletion of a single event that was just
				// processed by the serviceEvent() method.
				
				if (deleter == this)
				{
					servicedEvent = this.servicedEvent;
					if (servicedEvent == null)
						throw new TclRuntimeError("servicedEvent was not set by serviceEvent()");
					this.servicedEvent = null;
				}
				
				for (prev = null, evt = firstEvent; evt != null; evt = evt.next)
				{
					if (((servicedEvent == null) && (deleter.deleteEvent(evt) == 1)) || (evt == servicedEvent))
					{
						if (evt == firstEvent)
						{
							firstEvent = evt.next;
						}
						else
						{
							prev.next = evt.next;
						}
						if (evt.next == null)
						{
							lastEvent = prev;
						}
						if (evt == markerEvent)
						{
							markerEvent = prev;
						}
						if (evt == servicedEvent)
						{
							servicedEvent = null;
							break; // Just service this one event in the special case
						}
					}
					else
					{
						prev = evt;
					}
				}
				if (servicedEvent != null)
				{
					throw new TclRuntimeError("servicedEvent was not removed from the queue");
				}
			}
		}
예제 #9
0
				public  void  queueEvent(TclEvent evt, int position)
		// One of TCL.QUEUE_TAIL,
		// TCL.QUEUE_HEAD or TCL.QUEUE_MARK.
		{
			lock (this)
			{
				evt.notifier = this;
				
				if (position == TCL.QUEUE_TAIL)
				{
					// Append the event on the end of the queue.
					
					evt.next = null;
					
					if (firstEvent == null)
					{
						firstEvent = evt;
					}
					else
					{
						lastEvent.next = evt;
					}
					lastEvent = evt;
				}
				else if (position == TCL.QUEUE_HEAD)
				{
					// Push the event on the head of the queue.
					
					evt.next = firstEvent;
					if (firstEvent == null)
					{
						lastEvent = evt;
					}
					firstEvent = evt;
				}
				else if (position == TCL.QUEUE_MARK)
				{
					// Insert the event after the current marker event and advance
					// the marker to the new event.
					
					if (markerEvent == null)
					{
						evt.next = firstEvent;
						firstEvent = evt;
					}
					else
					{
						evt.next = markerEvent.next;
						markerEvent.next = evt;
					}
					markerEvent = evt;
					if (evt.next == null)
					{
						lastEvent = evt;
					}
				}
				else
				{
					// Wrong flag.
					
					throw new TclRuntimeError("wrong position \"" + position + "\", must be TCL.QUEUE_HEAD, TCL.QUEUE_TAIL or TCL.QUEUE_MARK");
				}
				
				if (System.Threading.Thread.CurrentThread != primaryThread)
				{
					System.Threading.Monitor.PulseAll(this);
				}
			}
		}
예제 #10
0
        internal int serviceEvent(int flags)
        // Indicates what events should be processed.
        // May be any combination of TCL.WINDOW_EVENTS
        // TCL.FILE_EVENTS, TCL.TIMER_EVENTS, or other
        // flags defined elsewhere.  Events not
        // matching this will be skipped for processing
        // later.
        {
            TclEvent evt;

            // No event flags is equivalent to TCL_ALL_EVENTS.

            if ((flags & TCL.ALL_EVENTS) == 0)
            {
                flags |= TCL.ALL_EVENTS;
            }

            // Loop through all the events in the queue until we find one
            // that can actually be handled.

            evt = null;
            while ((evt = getAvailableEvent(evt)) != null)
            {
                // Call the handler for the event.  If it actually handles the
                // event then free the storage for the event.  There are two
                // tricky things here, both stemming from the fact that the event
                // code may be re-entered while servicing the event:
                //
                // 1. Set the "isProcessing" field to true. This is a signal to
                //    ourselves that we shouldn't reexecute the handler if the
                //    event loop is re-entered.
                // 2. When freeing the event, must search the queue again from the
                //    front to find it.  This is because the event queue could
                //    change almost arbitrarily while handling the event, so we
                //    can't depend on pointers found now still being valid when
                //    the handler returns.

                evt.isProcessing = true;

                if (evt.processEvent(flags) != 0)
                {
                    evt.isProcessed = true;
                    // Don't allocate/grab the monitor for the event unless sync()
                    // has been called in another thread. This is thread safe
                    // since sync() checks the isProcessed flag before calling wait.
                    if (evt.needsNotify)
                    {
                        lock ( evt )
                        {
                            System.Threading.Monitor.PulseAll(evt);
                        }
                    }
                    // Remove this specific event from the queue
                    servicedEvent = evt;
                    deleteEvents(this);
                    return(1);
                }
                else
                {
                    // The event wasn't actually handled, so we have to
                    // restore the isProcessing field to allow the event to be
                    // attempted again.

                    evt.isProcessing = false;
                }

                // The handler for this event asked to defer it.  Just go on to
                // the next event.

                continue;
            }
            return(0);
        }
예제 #11
0
 public int deleteEvent(TclEvent evt)
 {
     throw new TclRuntimeError("The Notifier.deleteEvent() method should not be called");
 }
예제 #12
0
        public void queueEvent(TclEvent evt, int position)
        // One of TCL.QUEUE_TAIL,
        // TCL.QUEUE_HEAD or TCL.QUEUE_MARK.
        {
            lock (this)
            {
                evt.notifier = this;

                if (position == TCL.QUEUE_TAIL)
                {
                    // Append the event on the end of the queue.

                    evt.next = null;

                    if (firstEvent == null)
                    {
                        firstEvent = evt;
                    }
                    else
                    {
                        lastEvent.next = evt;
                    }
                    lastEvent = evt;
                }
                else if (position == TCL.QUEUE_HEAD)
                {
                    // Push the event on the head of the queue.

                    evt.next = firstEvent;
                    if (firstEvent == null)
                    {
                        lastEvent = evt;
                    }
                    firstEvent = evt;
                }
                else if (position == TCL.QUEUE_MARK)
                {
                    // Insert the event after the current marker event and advance
                    // the marker to the new event.

                    if (markerEvent == null)
                    {
                        evt.next   = firstEvent;
                        firstEvent = evt;
                    }
                    else
                    {
                        evt.next         = markerEvent.next;
                        markerEvent.next = evt;
                    }
                    markerEvent = evt;
                    if (evt.next == null)
                    {
                        lastEvent = evt;
                    }
                }
                else
                {
                    // Wrong flag.

                    throw new TclRuntimeError("wrong position \"" + position + "\", must be TCL.QUEUE_HEAD, TCL.QUEUE_TAIL or TCL.QUEUE_MARK");
                }

                if (System.Threading.Thread.CurrentThread != primaryThread)
                {
                    System.Threading.Monitor.PulseAll(this);
                }
            }
        }