Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ActivityTracker.cs
Go to the documentation of this file.
3
5
6internal sealed class ActivityTracker
7{
8 private sealed class ActivityInfo
9 {
10 internal readonly string m_name;
11
12 private readonly long m_uniqueId;
13
14 internal readonly Guid m_guid;
15
16 internal readonly int m_activityPathGuidOffset;
17
18 internal readonly int m_level;
19
21
22 internal long m_lastChildID;
23
24 internal int m_stopped;
25
26 internal readonly ActivityInfo m_creator;
27
28 internal readonly Guid m_activityIdToRestore;
29
31
32 public ActivityInfo(string name, long uniqueId, ActivityInfo creator, Guid activityIDToRestore, EventActivityOptions options)
33 {
34 m_name = name;
36 m_creator = creator;
37 m_uniqueId = uniqueId;
38 m_level = ((creator != null) ? (creator.m_level + 1) : 0);
39 m_activityIdToRestore = activityIDToRestore;
41 }
42
43 public static string Path(ActivityInfo activityInfo)
44 {
45 if (activityInfo == null)
46 {
47 return "";
48 }
49 return $"{Path(activityInfo.m_creator)}/{activityInfo.m_uniqueId}";
50 }
51
52 public override string ToString()
53 {
54 return m_name + "(" + Path(this) + ((m_stopped != 0) ? ",DEAD)" : ")");
55 }
56
57 public static string LiveActivities(ActivityInfo list)
58 {
59 if (list == null)
60 {
61 return "";
62 }
63 return list.ToString() + ";" + LiveActivities(list.m_creator);
64 }
65
66 public bool CanBeOrphan()
67 {
68 if ((m_eventOptions & EventActivityOptions.Detachable) != 0)
69 {
70 return true;
71 }
72 return false;
73 }
74
75 private unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathGuidOffset)
76 {
77 fixed (Guid* outPtr = &idRet)
78 {
79 int whereToAddId = 0;
80 if (m_creator != null)
81 {
83 idRet = m_creator.m_guid;
84 }
85 else
86 {
87 int num = 0;
88 num = Thread.GetDomainID();
89 whereToAddId = AddIdToGuid(outPtr, whereToAddId, (uint)num);
90 }
91 activityPathGuidOffset = AddIdToGuid(outPtr, whereToAddId, (uint)m_uniqueId);
92 if (12 < activityPathGuidOffset)
93 {
94 CreateOverflowGuid(outPtr);
95 }
96 }
97 }
98
99 private unsafe void CreateOverflowGuid(Guid* outPtr)
100 {
101 for (ActivityInfo creator = m_creator; creator != null; creator = creator.m_creator)
102 {
103 if (creator.m_activityPathGuidOffset <= 10)
104 {
105 uint id = (uint)Interlocked.Increment(ref creator.m_lastChildID);
106 *outPtr = creator.m_guid;
107 int num = AddIdToGuid(outPtr, creator.m_activityPathGuidOffset, id, overflow: true);
108 if (num <= 12)
109 {
110 break;
111 }
112 }
113 }
114 }
115
116 private unsafe static int AddIdToGuid(Guid* outPtr, int whereToAddId, uint id, bool overflow = false)
117 {
118 byte* ptr = (byte*)outPtr;
119 byte* ptr2 = ptr + 12;
120 ptr += whereToAddId;
121 if (ptr2 <= ptr)
122 {
123 return 13;
124 }
125 if (0 < id && id <= 10 && !overflow)
126 {
127 WriteNibble(ref ptr, ptr2, id);
128 }
129 else
130 {
131 uint num = 4u;
132 if (id <= 255)
133 {
134 num = 1u;
135 }
136 else if (id <= 65535)
137 {
138 num = 2u;
139 }
140 else if (id <= 16777215)
141 {
142 num = 3u;
143 }
144 if (overflow)
145 {
146 if (ptr2 <= ptr + 2)
147 {
148 return 13;
149 }
150 WriteNibble(ref ptr, ptr2, 11u);
151 }
152 WriteNibble(ref ptr, ptr2, 12 + (num - 1));
153 if (ptr < ptr2 && *ptr != 0)
154 {
155 if (id < 4096)
156 {
157 *ptr = (byte)(192 + (id >> 8));
158 id &= 0xFFu;
159 }
160 ptr++;
161 }
162 while (0 < num)
163 {
164 if (ptr2 <= ptr)
165 {
166 ptr++;
167 break;
168 }
169 *(ptr++) = (byte)id;
170 id >>= 8;
171 num--;
172 }
173 }
174 *(int*)((byte*)outPtr + (nint)3 * (nint)4) = (int)(*(uint*)outPtr + *(uint*)((byte*)outPtr + 4) + *(uint*)((byte*)outPtr + (nint)2 * (nint)4) + 1503500717) ^ Environment.ProcessId;
175 return (int)(ptr - (byte*)outPtr);
176 }
177
178 private unsafe static void WriteNibble(ref byte* ptr, byte* endPtr, uint value)
179 {
180 if (*ptr != 0)
181 {
182 byte* intPtr = ptr++;
183 *intPtr |= (byte)value;
184 }
185 else
186 {
187 *ptr = (byte)(value << 4);
188 }
189 }
190 }
191
193
194 private bool m_checkedForEnable;
195
197
198 private static long m_nextId;
199
201
202 public void OnStart(string providerName, string activityName, int task, ref Guid activityId, ref Guid relatedActivityId, EventActivityOptions options, bool useTplSource = true)
203 {
204 if (m_current == null)
205 {
207 {
208 return;
209 }
210 m_checkedForEnable = true;
211 if (useTplSource && TplEventSource.Log.IsEnabled(EventLevel.Informational, (EventKeywords)128L))
212 {
213 Enable();
214 }
215 if (m_current == null)
216 {
217 return;
218 }
219 }
221 string text = NormalizeActivityName(providerName, activityName, task);
222 TplEventSource tplEventSource = (useTplSource ? TplEventSource.Log : null);
223 bool flag = tplEventSource?.Debug ?? false;
224 if (flag)
225 {
226 tplEventSource.DebugFacilityMessage("OnStartEnter", text);
227 tplEventSource.DebugFacilityMessage("OnStartEnterActivityState", ActivityInfo.LiveActivities(value));
228 }
229 if (value != null)
230 {
231 if (value.m_level >= 100)
232 {
233 activityId = Guid.Empty;
234 relatedActivityId = Guid.Empty;
235 if (flag)
236 {
237 tplEventSource.DebugFacilityMessage("OnStartRET", "Fail");
238 }
239 return;
240 }
241 if ((options & EventActivityOptions.Recursive) == 0)
242 {
243 ActivityInfo activityInfo = FindActiveActivity(text, value);
244 if (activityInfo != null)
245 {
246 OnStop(providerName, activityName, task, ref activityId);
247 value = m_current.Value;
248 }
249 }
250 }
251 long uniqueId = ((value != null) ? Interlocked.Increment(ref value.m_lastChildID) : Interlocked.Increment(ref m_nextId));
252 relatedActivityId = EventSource.CurrentThreadActivityId;
253 ActivityInfo activityInfo2 = new ActivityInfo(text, uniqueId, value, relatedActivityId, options);
254 m_current.Value = activityInfo2;
255 activityId = activityInfo2.ActivityId;
256 if (flag)
257 {
258 tplEventSource.DebugFacilityMessage("OnStartRetActivityState", ActivityInfo.LiveActivities(activityInfo2));
259 tplEventSource.DebugFacilityMessage1("OnStartRet", activityId.ToString(), relatedActivityId.ToString());
260 }
261 }
262
263 public void OnStop(string providerName, string activityName, int task, ref Guid activityId, bool useTplSource = true)
264 {
265 if (m_current == null)
266 {
267 return;
268 }
269 string text = NormalizeActivityName(providerName, activityName, task);
270 TplEventSource tplEventSource = (useTplSource ? TplEventSource.Log : null);
271 bool flag = tplEventSource?.Debug ?? false;
272 if (flag)
273 {
274 tplEventSource.DebugFacilityMessage("OnStopEnter", text);
275 tplEventSource.DebugFacilityMessage("OnStopEnterActivityState", ActivityInfo.LiveActivities(m_current.Value));
276 }
277 ActivityInfo activityInfo;
278 ActivityInfo activityInfo2;
279 do
280 {
282 activityInfo = null;
283 activityInfo2 = FindActiveActivity(text, value);
284 if (activityInfo2 == null)
285 {
286 activityId = Guid.Empty;
287 if (flag)
288 {
289 tplEventSource.DebugFacilityMessage("OnStopRET", "Fail");
290 }
291 return;
292 }
293 activityId = activityInfo2.ActivityId;
294 ActivityInfo activityInfo3 = value;
295 while (activityInfo3 != activityInfo2 && activityInfo3 != null)
296 {
297 if (activityInfo3.m_stopped != 0)
298 {
299 activityInfo3 = activityInfo3.m_creator;
300 continue;
301 }
302 if (activityInfo3.CanBeOrphan())
303 {
304 if (activityInfo == null)
305 {
306 activityInfo = activityInfo3;
307 }
308 }
309 else
310 {
311 activityInfo3.m_stopped = 1;
312 }
313 activityInfo3 = activityInfo3.m_creator;
314 }
315 }
316 while (Interlocked.CompareExchange(ref activityInfo2.m_stopped, 1, 0) != 0);
317 if (activityInfo == null)
318 {
319 activityInfo = activityInfo2.m_creator;
320 }
321 m_current.Value = activityInfo;
322 if (flag)
323 {
324 tplEventSource.DebugFacilityMessage("OnStopRetActivityState", ActivityInfo.LiveActivities(activityInfo));
325 tplEventSource.DebugFacilityMessage("OnStopRet", activityId.ToString());
326 }
327 }
328
329 public void Enable()
330 {
331 if (m_current == null)
332 {
333 try
334 {
336 }
338 {
339 Debugger.Log(0, null, "Activity Enabled() called but AsyncLocals Not Supported (pre V4.6). Ignoring Enable");
340 }
341 }
342 }
343
344 private static ActivityInfo FindActiveActivity(string name, ActivityInfo startLocation)
345 {
346 for (ActivityInfo activityInfo = startLocation; activityInfo != null; activityInfo = activityInfo.m_creator)
347 {
348 if (name == activityInfo.m_name && activityInfo.m_stopped == 0)
349 {
350 return activityInfo;
351 }
352 }
353 return null;
354 }
355
356 private static string NormalizeActivityName(string providerName, string activityName, int task)
357 {
358 if (activityName.EndsWith("Start", StringComparison.Ordinal))
359 {
360 return providerName + activityName.AsSpan(0, activityName.Length - "Start".Length);
361 }
362 if (activityName.EndsWith("Stop", StringComparison.Ordinal))
363 {
364 return providerName + activityName.AsSpan(0, activityName.Length - "Stop".Length);
365 }
366 if (task != 0)
367 {
368 return providerName + "task" + task;
369 }
370 return providerName + activityName;
371 }
372
374 {
375 ActivityInfo activityInfo = args.CurrentValue;
376 ActivityInfo previousValue = args.PreviousValue;
377 if (previousValue != null && previousValue.m_creator == activityInfo && (activityInfo == null || previousValue.m_activityIdToRestore != activityInfo.ActivityId))
378 {
380 return;
381 }
382 while (activityInfo != null)
383 {
384 if (activityInfo.m_stopped == 0)
385 {
387 return;
388 }
389 activityInfo = activityInfo.m_creator;
390 }
392 }
393}
static void Log(int level, string? category, string? message)
Definition Debugger.cs:55
static unsafe int AddIdToGuid(Guid *outPtr, int whereToAddId, uint id, bool overflow=false)
static string Path(ActivityInfo activityInfo)
unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathGuidOffset)
ActivityInfo(string name, long uniqueId, ActivityInfo creator, Guid activityIDToRestore, EventActivityOptions options)
static unsafe void WriteNibble(ref byte *ptr, byte *endPtr, uint value)
static ActivityInfo FindActiveActivity(string name, ActivityInfo startLocation)
static string NormalizeActivityName(string providerName, string activityName, int task)
void OnStart(string providerName, string activityName, int task, ref Guid activityId, ref Guid relatedActivityId, EventActivityOptions options, bool useTplSource=true)
void ActivityChanging(AsyncLocalValueChangedArgs< ActivityInfo > args)
void OnStop(string providerName, string activityName, int task, ref Guid activityId, bool useTplSource=true)
static readonly ActivityTracker s_activityTrackerInstance
static void SetCurrentThreadActivityId(Guid activityId)
static int ProcessId
static int CompareExchange(ref int location1, int value, int comparand)
static int Increment(ref int location)
void DebugFacilityMessage1(string Facility, string Message, string Value1)
static readonly TplEventSource Log
void DebugFacilityMessage(string Facility, string Message)
static int GetDomainID()
Definition Thread.cs:807
static readonly Guid Empty
Definition Guid.cs:86