Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace System.Threading
//
public sealed partial class RegisteredWaitHandle : MarshalByRefObject
{
private readonly object? _lock;
private readonly Lock? _lock;
private bool _unregistering;

// Handle to this object to keep it alive
Expand All @@ -30,7 +30,7 @@ internal unsafe RegisteredWaitHandle(SafeWaitHandle waitHandle, _ThreadPoolWaitO
{
Debug.Assert(ThreadPool.UseWindowsThreadPool);

_lock = new object();
_lock = new Lock();

waitHandle.DangerousAddRef();
_waitHandle = waitHandle;
Expand Down Expand Up @@ -194,7 +194,7 @@ private void FinishUnregisteringAsync(object? waitObject)
// If this object gets resurrected and another thread calls Unregister, that creates a race condition.
// Do not block the finalizer thread. If another thread is running Unregister, it will clean up for us.
// The _lock may be null in case of OOM in the constructor.
if ((_lock != null) && Monitor.TryEnter(_lock))
if ((_lock != null) && _lock.TryEnter())
{
try
{
Expand All @@ -218,7 +218,7 @@ private void FinishUnregisteringAsync(object? waitObject)
}
finally
{
Monitor.Exit(_lock);
_lock.Exit();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ public class ThreadLocal<T> : IDisposable
// when the instance is disposed.
private volatile bool _initialized;

// IdManager assigns and reuses slot IDs. Additionally, the object is also used as a global lock.
// IdManager assigns and reuses slot IDs.
private static readonly IdManager s_idManager = new IdManager();

// Global Lock for the IdManager.
private static readonly Lock s_idManagerLock = new Lock();

// A linked list of all values associated with this ThreadLocal<T> instance.
// We create a dummy head node. That allows us to remove any (non-dummy) node without having to locate the m_linkedSlot field.
private LinkedSlot? _linkedSlot = new LinkedSlot(null);
Expand Down Expand Up @@ -165,7 +168,7 @@ protected virtual void Dispose(bool disposing)
{
int id;

lock (s_idManager)
lock (s_idManagerLock)
{
id = ~_idComplement;
_idComplement = 0;
Expand Down Expand Up @@ -384,7 +387,7 @@ private void CreateLinkedSlot(LinkedSlotVolatile[] slotArray, int id, T value)
var linkedSlot = new LinkedSlot(slotArray);

// Insert the LinkedSlot into the linked list maintained by this ThreadLocal<> instance and into the slot array
lock (s_idManager)
lock (s_idManagerLock)
{
// Check that the instance has not been disposed. It is important to check this under a lock, since
// Dispose also executes under a lock.
Expand Down Expand Up @@ -525,7 +528,7 @@ private static void GrowTable(ref LinkedSlotVolatile[] table, int minLength)
// Dispose could use a stale SlotArray reference and clear out a slot in the old array only, while
// the value continues to be referenced from the new (larger) array.
//
lock (s_idManager)
lock (s_idManagerLock)
{
for (int i = 0; i < table.Length; i++)
{
Expand Down Expand Up @@ -614,13 +617,15 @@ private sealed class IdManager
// Stores IDs that are used, and if each ID tracksAllValues or not.
private readonly Dictionary<int, bool> _usedIdToTracksAllValuesMap = new Dictionary<int, bool>();

// Stores IDs that were previously used and are now free to reuse. Additionally, the object is also used as a lock
// for the IdManager.
// Stores IDs that were previously used and are now free to reuse.
private readonly List<int> _freeIds = new List<int>();

// Lock for the IdManager.
private readonly Lock _freeIdsLock = new Lock();

internal int GetId(bool trackAllValues)
{
lock (_freeIds)
lock (_freeIdsLock)
{
int availableId;
int freeIdCount = _freeIds.Count;
Expand Down Expand Up @@ -658,7 +663,7 @@ internal int GetId(bool trackAllValues)
// Identify if an allocated id tracks all values or not
internal bool IdTracksAllValues(int id)
{
lock (_freeIds)
lock (_freeIdsLock)
{
return _usedIdToTracksAllValuesMap.TryGetValue(id, out bool tracksAllValues) && tracksAllValues;
}
Expand All @@ -669,7 +674,7 @@ internal bool IdTracksAllValues(int id)
// Return an ID to the pool
internal void ReturnId(int id, bool idTracksAllValues)
{
lock (_freeIds)
lock (_freeIdsLock)
{
if (!idTracksAllValues)
_idsThatDoNotTrackAllValues--;
Expand Down Expand Up @@ -728,7 +733,7 @@ internal FinalizationHelper(LinkedSlotVolatile[] slotArray)
{
// Remove the LinkedSlot from the linked list. Once the FinalizationHelper is done, all back-references to
// the table will be have been removed, and so the table can get GC'd.
lock (s_idManager)
lock (s_idManagerLock)
{
// If the slot wasn't disposed between reading it above and entering the lock
// decrement idsThatDoNotTrackAllValuesCountRemaining
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ internal sealed partial class TimerQueue : IThreadPoolWorkItem
/// </summary>
private static readonly AutoResetEvent s_timerEvent = new AutoResetEvent(false);

private static readonly Lock s_timerEventLock = new Lock();

// this means that it's in the s_scheduledTimers collection, not that it's the one which would run on the next TimeoutCallback
private bool _isScheduled;
private long _scheduledDueTimeMs;
Expand Down Expand Up @@ -50,7 +52,9 @@ private bool SetTimerPortable(uint actualDuration)
Debug.Assert((int)actualDuration >= 0);
long dueTimeMs = TickCount64 + (int)actualDuration;
AutoResetEvent timerEvent = s_timerEvent;
lock (timerEvent)
Lock timerEventLock = s_timerEventLock;

lock (timerEventLock)
{
if (!_isScheduled)
{
Expand All @@ -74,9 +78,11 @@ private bool SetTimerPortable(uint actualDuration)
private static void TimerThread()
{
AutoResetEvent timerEvent = s_timerEvent;
Lock timerEventLock = s_timerEventLock;
List<TimerQueue> timersToFire = s_scheduledTimersToFire!;
List<TimerQueue> timers;
lock (timerEvent)

lock (timerEventLock)
{
timers = s_scheduledTimers!;
}
Expand All @@ -88,7 +94,7 @@ private static void TimerThread()

long currentTimeMs = TickCount64;
shortestWaitDurationMs = int.MaxValue;
lock (timerEvent)
lock (timerEventLock)
{
for (int i = timers.Count - 1; i >= 0; --i)
{
Expand Down