Example #1
0
 void ITaskTimerOwner.AddToPending(TaskTimer timer, TaskEnv env, TaskTimerStatus next)
 {
     env.Acquire();
     if(timer.Env != null) {
         timer.Env.Release();
     }
     if(_running) {
         lock(_pending) {
             timer.Env = env;
             timer.SetStatus(next);
             _pending[timer] = null;
         }
     } else {
         env.Release();
         timer.Env = null;
         timer.SetStatus(TaskTimerStatus.Done);
     }
 }
Example #2
0
 void ITaskTimerOwner.AddToQueue(TaskTimer timer, TaskEnv env, TaskTimerStatus next)
 {
     env.Acquire();
     if(timer.Env != null) {
         timer.Env.Release();
     }
     if(_running) {
         lock(_queue) {
             timer.Env = env;
             timer.SetStatus(next);
             _queue.Enqueue(timer);
         }
     } else {
         env.Release();
         timer.Env = null;
         timer.SetStatus(TaskTimerStatus.Done);
     }
 }
Example #3
0
        /// <summary>
        /// Change when the timer will execute.
        /// </summary>
        /// <param name="when">The absolute time.</param>
        /// <param name="env">The environment to use for invocation.</param>
        public void Change(DateTime when, TaskEnv env)
        {
            DateTime now = DateTime.UtcNow;

            // determine new status
            int next;

            if (when <= now.AddSeconds(QUEUE_CUTOFF))
            {
                next = (int)TaskTimerStatus.Queued;
            }
            else if (when < DateTime.MaxValue)
            {
                next = (int)TaskTimerStatus.Pending;
            }
            else
            {
                next = (int)TaskTimerStatus.Done;
            }

            // ensure we have a behavior if we need one and we don't if we do not
            if (next != (int)TaskTimerStatus.Done)
            {
                if (env == null)
                {
                    throw new ArgumentNullException("env");
                }
            }
            else
            {
                env = null;
            }

            // attempt to change current status
retry:
            int current;

            switch (_status)
            {
            case (int)TaskTimerStatus.Done:

                // nothing to do
                break;

            case (int)TaskTimerStatus.Pending:

                // attempt to remove timer from pending list
                current = Interlocked.CompareExchange(ref _status, (int)TaskTimerStatus.Done, (int)TaskTimerStatus.Pending);
                switch (current)
                {
                case (int)TaskTimerStatus.Done:

                    // nothing to do
                    break;

                case (int)TaskTimerStatus.Pending:

                    // remove timer from pending list
                    _owner.RemoveFromPending(this);
                    break;

                case (int)TaskTimerStatus.Queued:

                    // we changed states; retry
                    Interlocked.Increment(ref _retries);
                    goto retry;

                case (int)TaskTimerStatus.Locked:

                    // somebody else is already changing the timer; no need to compete
                    return;
                }
                break;

            case (int)TaskTimerStatus.Queued:

                // attempto remove timer from queue
                current = Interlocked.CompareExchange(ref _status, (int)TaskTimerStatus.Done, (int)TaskTimerStatus.Queued);
                switch (current)
                {
                case (int)TaskTimerStatus.Done:

                    // nothing to do
                    break;

                case (int)TaskTimerStatus.Pending:

                    // we changed states; retry
                    Interlocked.Increment(ref _retries);
                    goto retry;

                case (int)TaskTimerStatus.Queued:

                    // remove timer from queue
                    _owner.RemoveFromQueue(this);
                    break;

                case (int)TaskTimerStatus.Locked:

                    // somebody else is already changing the timer; no need to compete
                    return;
                }
                break;

            case (int)TaskTimerStatus.Locked:

                // somebody else is already changing the timer; no need to compete
                return;
            }

            // register timer according to new status
            if (Interlocked.CompareExchange(ref _status, (int)TaskTimerStatus.Locked, (int)TaskTimerStatus.Done) == (int)TaskTimerStatus.Done)
            {
                _when = when;
                switch (next)
                {
                case (int)TaskTimerStatus.Done:

                    // release Task Environment
                    if (Env != null)
                    {
                        Env.Release();
                    }
                    Env = null;
                    Interlocked.Exchange(ref _status, next);
                    return;

                case (int)TaskTimerStatus.Pending:

                    // add timer to pending list
                    _owner.AddToPending(this, env, (TaskTimerStatus)next);
                    break;

                case (int)TaskTimerStatus.Queued:

                    // add timer to active queue
                    _owner.AddToQueue(this, env, (TaskTimerStatus)next);
                    break;

                case (int)TaskTimerStatus.Locked:
                    Interlocked.Exchange(ref _status, (int)TaskTimerStatus.Done);
                    throw new InvalidOperationException("should never happen");
                }
            }
        }