Merge branch 'sgen-disable-gc'
[mono.git] / mcs / class / corlib / System.Threading.Tasks / TaskScheduler.cs
1 // 
2 // TaskScheduler.cs
3 //  
4 // Author:
5 //       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
6 // 
7 // Copyright (c) 2009 Jérémie "Garuma" Laval
8 // 
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 // 
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 // 
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26
27 #if NET_4_0 || MOBILE
28 using System;
29 using System.Threading;
30 using System.Collections.Generic;
31
32 namespace System.Threading.Tasks
33 {
34         [System.Diagnostics.DebuggerDisplay ("Id={Id}")]
35         [System.Diagnostics.DebuggerTypeProxy ("System.Threading.Tasks.TaskScheduler+SystemThreadingTasks_TaskSchedulerDebugView")]
36         public abstract class TaskScheduler
37         {
38                 static TaskScheduler defaultScheduler =
39                         Environment.GetEnvironmentVariable ("USE_OLD_TASK_SCHED") != null ? (TaskScheduler)new Scheduler () : (TaskScheduler)new TpScheduler ();
40                 SchedulerProxy proxy;
41                 
42                 [ThreadStatic]
43                 static TaskScheduler currentScheduler;
44                 
45                 int id;
46                 static int lastId = int.MinValue;
47                 
48                 public static event EventHandler<UnobservedTaskExceptionEventArgs> UnobservedTaskException;
49                 
50                 protected TaskScheduler ()
51                 {
52                         this.id = Interlocked.Increment (ref lastId);
53                         this.proxy = new SchedulerProxy (this);
54                 }
55
56                 public static TaskScheduler FromCurrentSynchronizationContext ()
57                 {
58                         var syncCtx = SynchronizationContext.Current;
59                         return new SynchronizationContextScheduler (syncCtx);
60                 }
61                 
62                 public static TaskScheduler Default  {
63                         get {
64                                 return defaultScheduler;
65                         }
66                 }
67                 
68                 public static TaskScheduler Current  {
69                         get {
70                                 if (currentScheduler != null)
71                                         return currentScheduler;
72                                 
73                                 return defaultScheduler;
74                         }
75                         internal set {
76                                 currentScheduler = value;
77                         }
78                 }
79                 
80                 public int Id {
81                         get {
82                                 return id;
83                         }
84                 }
85                 
86                 public virtual int MaximumConcurrencyLevel {
87                         get {
88                                 return Environment.ProcessorCount;
89                         }
90                 }
91
92                 internal virtual void ParticipateUntil (Task task)
93                 {
94                         proxy.ParticipateUntil (task);
95                 }
96
97                 internal virtual bool ParticipateUntil (Task task, ManualResetEventSlim predicateEvt, int millisecondsTimeout)
98                 {
99                         return proxy.ParticipateUntil (task, predicateEvt, millisecondsTimeout);
100                 }
101
102                 internal virtual void PulseAll ()
103                 {
104                         proxy.PulseAll ();
105                 }
106
107                 protected abstract IEnumerable<Task> GetScheduledTasks ();
108                 protected internal abstract void QueueTask (Task task);
109                 protected internal virtual bool TryDequeue (Task task)
110                 {
111                         throw new NotSupportedException ();
112                 }
113
114                 internal protected bool TryExecuteTask (Task task)
115                 {
116                         return TryExecuteTaskInline (task, false);
117                 }
118
119                 protected abstract bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued);
120                 
121                 internal UnobservedTaskExceptionEventArgs FireUnobservedEvent (AggregateException e)
122                 {
123                         UnobservedTaskExceptionEventArgs args = new UnobservedTaskExceptionEventArgs (e);
124                         
125                         EventHandler<UnobservedTaskExceptionEventArgs> temp = UnobservedTaskException;
126                         if (temp == null)
127                                 return args;
128                         
129                         temp (this, args);
130                         
131                         return args;
132                 }
133         }
134 }
135 #endif