You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,95 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ActivityIdHelper.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Diagnostics.Tracing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
internal sealed class ActivityIdHelper {
|
||||
|
||||
private delegate Guid GetCurrentDelegate();
|
||||
private delegate void SetAndDestroyDelegate(Guid activityId);
|
||||
private delegate void SetAndPreserveDelegate(Guid activityId, out Guid oldActivityThatWillContinue);
|
||||
|
||||
// Note to callers: this field can be null.
|
||||
internal static readonly ActivityIdHelper Instance = GetSingleton();
|
||||
|
||||
private static readonly Guid _baseGuid = Guid.NewGuid();
|
||||
private static long _counter;
|
||||
|
||||
private readonly GetCurrentDelegate _getCurrentDel;
|
||||
private readonly SetAndDestroyDelegate _setAndDestroyDel;
|
||||
private readonly SetAndPreserveDelegate _setAndPreserveDel;
|
||||
|
||||
// use the factory to create an instance of this type
|
||||
private ActivityIdHelper(GetCurrentDelegate getCurrentDel, SetAndDestroyDelegate setAndDestroyDel, SetAndPreserveDelegate setAndPreserveDel) {
|
||||
_getCurrentDel = getCurrentDel;
|
||||
_setAndDestroyDel = setAndDestroyDel;
|
||||
_setAndPreserveDel = setAndPreserveDel;
|
||||
}
|
||||
|
||||
// Gets the current thread's activity ID.
|
||||
public Guid CurrentThreadActivityId {
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get { return _getCurrentDel(); }
|
||||
}
|
||||
|
||||
private static ActivityIdHelper GetSingleton() {
|
||||
try {
|
||||
// The mscorlib APIs we depend on weren't added until Blue, so we can't
|
||||
// take a direct dependency. Need to light up instead.
|
||||
|
||||
var getCurrentDel = (GetCurrentDelegate)Delegate.CreateDelegate(
|
||||
typeof(GetCurrentDelegate), typeof(EventSource), "get_CurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
|
||||
|
||||
var setAndDestroyDel = (SetAndDestroyDelegate)Delegate.CreateDelegate(
|
||||
typeof(SetAndDestroyDelegate), typeof(EventSource), "SetCurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
|
||||
|
||||
var setAndPreserveDel = (SetAndPreserveDelegate)Delegate.CreateDelegate(
|
||||
typeof(SetAndPreserveDelegate), typeof(EventSource), "SetCurrentThreadActivityId", ignoreCase: false, throwOnBindFailure: false);
|
||||
|
||||
if (getCurrentDel != null && setAndDestroyDel != null && setAndPreserveDel != null) {
|
||||
return new ActivityIdHelper(getCurrentDel, setAndDestroyDel, setAndPreserveDel);
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// exceptions are not fatal; we just won't be able to call the new APIs
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Disposes of the thread's existing activity ID, then sets the new activity ID on this thread.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetCurrentThreadActivityId(Guid activityId) {
|
||||
_setAndDestroyDel(activityId);
|
||||
}
|
||||
|
||||
// Suspends (but does not dispose of) the thread's existing activity ID, then sets a new activity ID on this thread.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue) {
|
||||
_setAndPreserveDel(activityId, out oldActivityThatWillContinue);
|
||||
}
|
||||
|
||||
// !! SECURITY WARNING !!
|
||||
// The GUIDs created by this method are predictable and should be used ONLY for tracing.
|
||||
// Any other use (such as leaking them to the user) constitutes information disclosure.
|
||||
//
|
||||
// This is a perf-sensitive method since it could potentially be called many times per
|
||||
// request. Guid.NewGuid() is slow since it eventually calls CAPI, and we did actually
|
||||
// see it show up as a bottleneck when developing MVC 2. The below implementation has
|
||||
// measurably better performance characteristics than calling the other Guid ctors.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe Guid UnsafeCreateNewActivityId() {
|
||||
Guid guidCopy = _baseGuid;
|
||||
*(long*)(&guidCopy) ^= Interlocked.Increment(ref _counter); // operate on the copy, not the original
|
||||
return guidCopy;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user