diff options
author | Justin Clark-Casey (justincc) | 2013-05-01 19:01:43 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2013-05-01 19:01:43 +0100 |
commit | 206fb306a7820cf593570e35ddfa8e7c5a10e449 (patch) | |
tree | 0ef0fdf42ddc0b63224af52b62b0bad42f62e352 /ThirdParty/SmartThreadPool/CallerThreadContext.cs | |
parent | Fix CAPS to work like they should - do not send caps to the viewer if they're... (diff) | |
download | opensim-SC-206fb306a7820cf593570e35ddfa8e7c5a10e449.zip opensim-SC-206fb306a7820cf593570e35ddfa8e7c5a10e449.tar.gz opensim-SC-206fb306a7820cf593570e35ddfa8e7c5a10e449.tar.bz2 opensim-SC-206fb306a7820cf593570e35ddfa8e7c5a10e449.tar.xz |
Update SmartThreadPool to latest version 2.2.3 with a major and minor change.
SmartThreadPool code comes from http://www.codeproject.com/Articles/7933/Smart-Thread-Pool
This version implements thread abort (via WorkItem.Cancel(true)), threadpool naming, max thread stack, etc. so we no longer need to manually patch those.
However, two changes have been made to stock 2.2.3.
Major change: WorkItem.Cancel(bool abortExecution) in our version does not succeed if the work item was in progress and thread abort was not specified.
This is to match previous behaviour where we handle co-operative termination via another mechanism rather than checking WorkItem.IsCanceled.
Minor change: Did not add STP's StopWatch implementation as this is only used WinCE and Silverlight and causes a build clash with System.Diagnostics.StopWatch
The reason for updating is to see if this improves http://opensimulator.org/mantis/view.php?id=6557 and http://opensimulator.org/mantis/view.php?id=6586
Diffstat (limited to '')
-rw-r--r-- | ThirdParty/SmartThreadPool/CallerThreadContext.cs | 361 |
1 files changed, 138 insertions, 223 deletions
diff --git a/ThirdParty/SmartThreadPool/CallerThreadContext.cs b/ThirdParty/SmartThreadPool/CallerThreadContext.cs index 6ea53f6..2177241 100644 --- a/ThirdParty/SmartThreadPool/CallerThreadContext.cs +++ b/ThirdParty/SmartThreadPool/CallerThreadContext.cs | |||
@@ -1,223 +1,138 @@ | |||
1 | using System; | 1 | |
2 | using System.Diagnostics; | 2 | #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) |
3 | using System.Threading; | 3 | |
4 | using System.Reflection; | 4 | using System; |
5 | using System.Web; | 5 | using System.Diagnostics; |
6 | using System.Runtime.Remoting.Messaging; | 6 | using System.Threading; |
7 | 7 | using System.Reflection; | |
8 | 8 | using System.Web; | |
9 | namespace Amib.Threading | 9 | using System.Runtime.Remoting.Messaging; |
10 | { | 10 | |
11 | #region CallerThreadContext class | 11 | |
12 | 12 | namespace Amib.Threading.Internal | |
13 | /// <summary> | 13 | { |
14 | /// This class stores the caller call context in order to restore | 14 | #region CallerThreadContext class |
15 | /// it when the work item is executed in the thread pool environment. | 15 | |
16 | /// </summary> | 16 | /// <summary> |
17 | internal class CallerThreadContext | 17 | /// This class stores the caller call context in order to restore |
18 | { | 18 | /// it when the work item is executed in the thread pool environment. |
19 | #region Prepare reflection information | 19 | /// </summary> |
20 | 20 | internal class CallerThreadContext | |
21 | // Cached type information. | 21 | { |
22 | private static MethodInfo getLogicalCallContextMethodInfo = | 22 | #region Prepare reflection information |
23 | typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); | 23 | |
24 | 24 | // Cached type information. | |
25 | private static MethodInfo setLogicalCallContextMethodInfo = | 25 | private static readonly MethodInfo getLogicalCallContextMethodInfo = |
26 | typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); | 26 | typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); |
27 | 27 | ||
28 | private static string HttpContextSlotName = GetHttpContextSlotName(); | 28 | private static readonly MethodInfo setLogicalCallContextMethodInfo = |
29 | 29 | typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); | |
30 | private static string GetHttpContextSlotName() | 30 | |
31 | { | 31 | private static string HttpContextSlotName = GetHttpContextSlotName(); |
32 | FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic); | 32 | |
33 | 33 | private static string GetHttpContextSlotName() | |
34 | if( fi != null ) | 34 | { |
35 | return (string)fi.GetValue(null); | 35 | FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic); |
36 | else // Use the default "HttpContext" slot name | 36 | |
37 | return "HttpContext"; | 37 | if (fi != null) |
38 | } | 38 | { |
39 | 39 | return (string) fi.GetValue(null); | |
40 | #endregion | 40 | } |
41 | 41 | ||
42 | #region Private fields | 42 | return "HttpContext"; |
43 | 43 | } | |
44 | private HttpContext _httpContext = null; | 44 | |
45 | private LogicalCallContext _callContext = null; | 45 | #endregion |
46 | 46 | ||
47 | #endregion | 47 | #region Private fields |
48 | 48 | ||
49 | /// <summary> | 49 | private HttpContext _httpContext; |
50 | /// Constructor | 50 | private LogicalCallContext _callContext; |
51 | /// </summary> | 51 | |
52 | private CallerThreadContext() | 52 | #endregion |
53 | { | 53 | |
54 | } | 54 | /// <summary> |
55 | 55 | /// Constructor | |
56 | public bool CapturedCallContext | 56 | /// </summary> |
57 | { | 57 | private CallerThreadContext() |
58 | get | 58 | { |
59 | { | 59 | } |
60 | return (null != _callContext); | 60 | |
61 | } | 61 | public bool CapturedCallContext |
62 | } | 62 | { |
63 | 63 | get | |
64 | public bool CapturedHttpContext | 64 | { |
65 | { | 65 | return (null != _callContext); |
66 | get | 66 | } |
67 | { | 67 | } |
68 | return (null != _httpContext); | 68 | |
69 | } | 69 | public bool CapturedHttpContext |
70 | } | 70 | { |
71 | 71 | get | |
72 | /// <summary> | 72 | { |
73 | /// Captures the current thread context | 73 | return (null != _httpContext); |
74 | /// </summary> | 74 | } |
75 | /// <returns></returns> | 75 | } |
76 | public static CallerThreadContext Capture( | 76 | |
77 | bool captureCallContext, | 77 | /// <summary> |
78 | bool captureHttpContext) | 78 | /// Captures the current thread context |
79 | { | 79 | /// </summary> |
80 | Debug.Assert(captureCallContext || captureHttpContext); | 80 | /// <returns></returns> |
81 | 81 | public static CallerThreadContext Capture( | |
82 | CallerThreadContext callerThreadContext = new CallerThreadContext(); | 82 | bool captureCallContext, |
83 | 83 | bool captureHttpContext) | |
84 | // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture() | 84 | { |
85 | // Capture Call Context | 85 | Debug.Assert(captureCallContext || captureHttpContext); |
86 | if(captureCallContext && (getLogicalCallContextMethodInfo != null)) | 86 | |
87 | { | 87 | CallerThreadContext callerThreadContext = new CallerThreadContext(); |
88 | callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null); | 88 | |
89 | if (callerThreadContext._callContext != null) | 89 | // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture() |
90 | { | 90 | // Capture Call Context |
91 | callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone(); | 91 | if(captureCallContext && (getLogicalCallContextMethodInfo != null)) |
92 | } | 92 | { |
93 | } | 93 | callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null); |
94 | 94 | if (callerThreadContext._callContext != null) | |
95 | // Capture httpContext | 95 | { |
96 | if (captureHttpContext && (null != HttpContext.Current)) | 96 | callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone(); |
97 | { | 97 | } |
98 | callerThreadContext._httpContext = HttpContext.Current; | 98 | } |
99 | } | 99 | |
100 | 100 | // Capture httpContext | |
101 | return callerThreadContext; | 101 | if (captureHttpContext && (null != HttpContext.Current)) |
102 | } | 102 | { |
103 | 103 | callerThreadContext._httpContext = HttpContext.Current; | |
104 | /// <summary> | 104 | } |
105 | /// Applies the thread context stored earlier | 105 | |
106 | /// </summary> | 106 | return callerThreadContext; |
107 | /// <param name="callerThreadContext"></param> | 107 | } |
108 | public static void Apply(CallerThreadContext callerThreadContext) | 108 | |
109 | { | 109 | /// <summary> |
110 | if (null == callerThreadContext) | 110 | /// Applies the thread context stored earlier |
111 | { | 111 | /// </summary> |
112 | throw new ArgumentNullException("callerThreadContext"); | 112 | /// <param name="callerThreadContext"></param> |
113 | } | 113 | public static void Apply(CallerThreadContext callerThreadContext) |
114 | 114 | { | |
115 | // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run() | 115 | if (null == callerThreadContext) |
116 | // Restore call context | 116 | { |
117 | if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) | 117 | throw new ArgumentNullException("callerThreadContext"); |
118 | { | 118 | } |
119 | setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext }); | 119 | |
120 | } | 120 | // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run() |
121 | 121 | // Restore call context | |
122 | // Restore HttpContext | 122 | if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) |
123 | if (callerThreadContext._httpContext != null) | 123 | { |
124 | { | 124 | setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext }); |
125 | CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); | 125 | } |
126 | } | 126 | |
127 | } | 127 | // Restore HttpContext |
128 | } | 128 | if (callerThreadContext._httpContext != null) |
129 | 129 | { | |
130 | #endregion | 130 | HttpContext.Current = callerThreadContext._httpContext; |
131 | 131 | //CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); | |
132 | } | 132 | } |
133 | 133 | } | |
134 | 134 | } | |
135 | /* | 135 | |
136 | // Ami Bar | 136 | #endregion |
137 | // amibar@gmail.com | 137 | } |
138 | 138 | #endif | |
139 | using System; | ||
140 | using System.Threading; | ||
141 | using System.Globalization; | ||
142 | using System.Security.Principal; | ||
143 | using System.Reflection; | ||
144 | using System.Runtime.Remoting.Contexts; | ||
145 | |||
146 | namespace Amib.Threading.Internal | ||
147 | { | ||
148 | #region CallerThreadContext class | ||
149 | |||
150 | /// <summary> | ||
151 | /// This class stores the caller thread context in order to restore | ||
152 | /// it when the work item is executed in the context of the thread | ||
153 | /// from the pool. | ||
154 | /// Note that we can't store the thread's CompressedStack, because | ||
155 | /// it throws a security exception | ||
156 | /// </summary> | ||
157 | public class CallerThreadContext | ||
158 | { | ||
159 | private CultureInfo _culture = null; | ||
160 | private CultureInfo _cultureUI = null; | ||
161 | private IPrincipal _principal; | ||
162 | private System.Runtime.Remoting.Contexts.Context _context; | ||
163 | |||
164 | private static FieldInfo _fieldInfo = GetFieldInfo(); | ||
165 | |||
166 | private static FieldInfo GetFieldInfo() | ||
167 | { | ||
168 | Type threadType = typeof(Thread); | ||
169 | return threadType.GetField( | ||
170 | "m_Context", | ||
171 | BindingFlags.Instance | BindingFlags.NonPublic); | ||
172 | } | ||
173 | |||
174 | /// <summary> | ||
175 | /// Constructor | ||
176 | /// </summary> | ||
177 | private CallerThreadContext() | ||
178 | { | ||
179 | } | ||
180 | |||
181 | /// <summary> | ||
182 | /// Captures the current thread context | ||
183 | /// </summary> | ||
184 | /// <returns></returns> | ||
185 | public static CallerThreadContext Capture() | ||
186 | { | ||
187 | CallerThreadContext callerThreadContext = new CallerThreadContext(); | ||
188 | |||
189 | Thread thread = Thread.CurrentThread; | ||
190 | callerThreadContext._culture = thread.CurrentCulture; | ||
191 | callerThreadContext._cultureUI = thread.CurrentUICulture; | ||
192 | callerThreadContext._principal = Thread.CurrentPrincipal; | ||
193 | callerThreadContext._context = Thread.CurrentContext; | ||
194 | return callerThreadContext; | ||
195 | } | ||
196 | |||
197 | /// <summary> | ||
198 | /// Applies the thread context stored earlier | ||
199 | /// </summary> | ||
200 | /// <param name="callerThreadContext"></param> | ||
201 | public static void Apply(CallerThreadContext callerThreadContext) | ||
202 | { | ||
203 | Thread thread = Thread.CurrentThread; | ||
204 | thread.CurrentCulture = callerThreadContext._culture; | ||
205 | thread.CurrentUICulture = callerThreadContext._cultureUI; | ||
206 | Thread.CurrentPrincipal = callerThreadContext._principal; | ||
207 | |||
208 | // Uncomment the following block to enable the Thread.CurrentThread | ||
209 | /* | ||
210 | if (null != _fieldInfo) | ||
211 | { | ||
212 | _fieldInfo.SetValue( | ||
213 | Thread.CurrentThread, | ||
214 | callerThreadContext._context); | ||
215 | } | ||
216 | * / | ||
217 | } | ||
218 | } | ||
219 | |||
220 | #endregion | ||
221 | } | ||
222 | */ | ||
223 | |||