Example #1
0
        public TimerHandler(Notifier n, int milliseconds)
        {
            int i;

            atTime      = (System.DateTime.Now.Ticks - 621355968000000000) / 10000 + milliseconds;
            notifier    = (Notifier)n;
            isCancelled = false;

            /*
             * Add the event to the queue in the correct position (ordered by
             * event firing time).
             *
             * NOTE: it's very important that if two timer handlers have the
             * same atTime, the newer timer handler always goes after the
             * older handler in the list. See comments in
             * Notifier.TimerEvent.processEvent() for details.
             */

            lock ( notifier )
            {
                generation = notifier.timerGeneration;

                for (i = 0; i < notifier.timerList.Count; i++)
                {
                    TimerHandler q = (TimerHandler)notifier.timerList[i];
                    if (atTime < q.atTime)
                    {
                        break;
                    }
                }
                notifier.timerList.Insert(i, this);

                if (System.Threading.Thread.CurrentThread != notifier.primaryThread)
                {
                    System.Threading.Monitor.PulseAll(notifier);
                }
            }
        }
Example #2
0
        public int doOneEvent(int flags)
        // Miscellaneous flag values: may be any
        // combination of TCL.DONT_WAIT,
        // TCL.WINDOW_EVENTS, TCL.FILE_EVENTS,
        // TCL.TIMER_EVENTS, TCL.IDLE_EVENTS,
        // or others defined by event sources.
        {
            int result = 0;

            // No event flags is equivalent to TCL_ALL_EVENTS.

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

            // The core of this procedure is an infinite loop, even though
            // we only service one event.  The reason for this is that we
            // may be processing events that don't do anything inside of Tcl.

            while (true)
            {
                // If idle events are the only things to service, skip the
                // main part of the loop and go directly to handle idle
                // events (i.e. don't wait even if TCL_DONT_WAIT isn't set).

                if ((flags & TCL.ALL_EVENTS) == TCL.IDLE_EVENTS)
                {
                    return(serviceIdle());
                }

                long sysTime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;

                // If some timers have been expired, queue them into the
                // event queue. We can't process expired times right away,
                // because there may already be other events on the queue.

                if (!timerPending && (timerList.Count > 0))
                {
                    TimerHandler h = (TimerHandler)timerList[0];

                    if (h.atTime <= sysTime)
                    {
                        TimerEvent Tevent = new TimerEvent();
                        Tevent.notifier = this;
                        queueEvent(Tevent, TCL.QUEUE_TAIL);
                        timerPending = true;
                    }
                }

                // Service a queued event, if there are any.

                if (serviceEvent(flags) != 0)
                {
                    result = 1;
                    break;
                }

                // There is no event on the queue. Check for idle events.

                if ((flags & TCL.IDLE_EVENTS) != 0)
                {
                    if (serviceIdle() != 0)
                    {
                        result = 1;
                        break;
                    }
                }

                if ((flags & TCL.DONT_WAIT) != 0)
                {
                    break;
                }

                // We don't have any event to service. We'll wait if
                // TCL.DONT_WAIT. When the following wait() call returns,
                // one of the following things may happen:
                //
                // (1) waitTime milliseconds has elasped (if waitTime != 0);
                //
                // (2) The primary notifier has been notify()'ed by other threads:
                //     (a) an event is queued by queueEvent().
                //     (b) a timer handler was created by new TimerHandler();
                //     (c) an idle handler was created by new IdleHandler();
                // (3) We receive an InterruptedException.
                //

                try
                {
                    // Don't acquire the monitor until we are about to wait
                    // for notification from another thread. It is critical
                    // that this entire method not be synchronized since
                    // a call to processEvent via serviceEvent could take
                    // a very long time. We don't want the monitor held
                    // during that time since that would force calls to
                    // queueEvent in other threads to wait.

                    lock (this)
                    {
                        if (timerList.Count > 0)
                        {
                            TimerHandler h        = (TimerHandler)timerList[0];
                            long         waitTime = h.atTime - sysTime;
                            if (waitTime > 0)
                            {
                                System.Threading.Monitor.Wait(this, TimeSpan.FromMilliseconds(waitTime));
                            }
                        }
                        else
                        {
                            System.Threading.Monitor.Wait(this);
                        }
                    } // synchronized (this)
                }
                catch (System.Threading.ThreadInterruptedException e)
                {
                    // We ignore any InterruptedException and loop continuously
                    // until we receive an event.
                }
            }

            return(result);
        }