source: branches/eraser6/Manager/DirectExecutor.cs @ 163

Revision 163, 4.5 KB checked in by lowjoel, 6 years ago (diff)

Added Docs for the DirectExecutor? class.

Line 
1using System;
2using System.Collections.Generic;
3using System.Collections.Specialized;
4using System.Text;
5using System.Threading;
6
7namespace Eraser.Manager
8{
9    /// <summary>
10    /// The DirectExecutor class is used by the Eraser GUI directly when the program
11    /// is run without the help of a Service.
12    /// </summary>
13    public class DirectExecutor : Executor
14    {
15        public DirectExecutor()
16        {
17            thread = new Thread(delegate()
18            {
19                this.Main();
20            });
21
22            thread.Start();
23            Thread.Sleep(0);
24        }
25
26        public override void AddTask(ref Task task)
27        {
28            lock (unusedIdsLock)
29            {
30                if (unusedIds.Count != 0)
31                {
32                    task.ID = unusedIds[0];
33                    unusedIds.RemoveAt(0);
34                }
35                else
36                    task.ID = ++nextId;
37            }
38
39            //Add the task to the set of tasks
40            lock (tasksLock)
41            {
42                tasks.Add(task.ID, task);
43
44                //If the task is scheduled to run now, break the waiting thread and
45                //run it immediately
46                if (task.Schedule == Schedule.RunNow)
47                {
48                    scheduledTasks.Add(DateTime.Now, task);
49                    schedulerInterrupt.Set();
50                }
51                //If the task is scheduled, add the next execution time to the list
52                //of schduled tasks.
53                else if (task.Schedule != Schedule.RunOnRestart)
54                {
55                    scheduledTasks.Add((task.Schedule as RecurringSchedule).NextRun, task);
56                }
57            }
58        }
59
60        public override bool DeleteTask(uint taskId)
61        {
62            lock (tasksLock)
63            {
64                if (!tasks.ContainsKey(taskId))
65                    return false;
66
67                lock (unusedIdsLock)
68                    unusedIds.Add(taskId);
69                tasks.Remove(taskId);
70            }
71            return true;
72        }
73
74        public override Task GetTask(uint taskId)
75        {
76            lock (tasksLock)
77            {
78                if (!tasks.ContainsKey(taskId))
79                    return null;
80                return tasks[taskId];
81            }
82        }
83
84        public override Dictionary<uint, Task>.Enumerator GetIterator()
85        {
86            return tasks.GetEnumerator();
87        }
88
89        /// <summary>
90        /// The thread entry point for this object. This object operates on a queue
91        /// and hence the thread will sequentially execute tasks.
92        /// </summary>
93        private void Main()
94        {
95            //The waiting thread will utilize a polling loop to check for new
96            //scheduled tasks. This will be checked every 30 seconds. However,
97            //when the thread is waiting for a new task, it can be interrupted.
98            while (thread.ThreadState != ThreadState.AbortRequested)
99            {
100                //Check for a new task
101                Task task = null;
102                lock (tasksLock)
103                {
104                    if (scheduledTasks.Count != 0 &&
105                        (scheduledTasks.Values[0].Schedule == Schedule.RunNow ||
106                         scheduledTasks.Keys[0] <= DateTime.Now))
107                    {
108                        task = scheduledTasks.Values[0];
109                        scheduledTasks.RemoveAt(0);
110                    }
111                }
112
113                if (task != null)
114                {
115                    //Run the task
116                    ;
117
118                    //If the task is a recurring task, reschedule it since we are done.
119                    if (task.Schedule is RecurringSchedule)
120                        ((RecurringSchedule)task.Schedule).Reschedule(DateTime.Now);
121                }
122
123                //Wait for half a minute to check for the next scheduled task.
124                schedulerInterrupt.WaitOne(30000, false);
125            }
126        }
127
128        /// <summary>
129        /// The thread object.
130        /// </summary>
131        private Thread thread;
132
133        /// <summary>
134        /// The lock preventing concurrent access for the tasks list and the
135        /// tasks queue.
136        /// </summary>
137        private object tasksLock = new object();
138
139        /// <summary>
140        /// The list of tasks. Includes all immediate, reboot, and recurring tasks
141        /// </summary>
142        private Dictionary<uint, Task> tasks = new Dictionary<uint, Task>();
143
144        /// <summary>
145        /// The queue of tasks. This queue is executed when the first element's
146        /// timestamp (the key) has been past. This list assumes that all tasks
147        /// are sorted by timestamp, smallest one first.
148        /// </summary>
149        private SortedList<DateTime, Task> scheduledTasks =
150            new SortedList<DateTime, Task>();
151
152        /// <summary>
153        /// The list of task IDs for recycling.
154        /// </summary>
155        private List<uint> unusedIds = new List<uint>();
156
157        /// <summary>
158        /// Lock preventing concurrent access for the IDs.
159        /// </summary>
160        private object unusedIdsLock = new object();
161
162        /// <summary>
163        /// Incrementing ID. This value is incremented by one every time an ID
164        /// is required by no unused IDs remain.
165        /// </summary>
166        private uint nextId = 0;
167
168        /// <summary>
169        /// An automatically reset event allowing the addition of new tasks to
170        /// interrupt the thread's sleeping state waiting for the next recurring
171        /// task to be due.
172        /// </summary>
173        AutoResetEvent schedulerInterrupt = new AutoResetEvent(true);
174    }
175}
Note: See TracBrowser for help on using the repository browser.