Skip to content

Commit 8b0b574

Browse files
committed
Split inner types
1 parent a2b441b commit 8b0b574

File tree

4 files changed

+144
-130
lines changed

4 files changed

+144
-130
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using System.Runtime.InteropServices;
3+
4+
namespace DotNext.Threading;
5+
6+
public partial class AsyncReaderWriterLock
7+
{
8+
/// <summary>
9+
/// Represents lock stamp used for optimistic reading.
10+
/// </summary>
11+
[StructLayout(LayoutKind.Auto)]
12+
public readonly struct LockStamp : IEquatable<LockStamp>
13+
{
14+
private readonly ulong version;
15+
private readonly bool valid;
16+
17+
internal LockStamp(in State state)
18+
{
19+
version = state.Version;
20+
valid = true;
21+
}
22+
23+
internal bool IsValid(in State state)
24+
=> valid && state.Version == version && !state.WriteLock;
25+
26+
private bool Equals(in LockStamp other) => version == other.version && valid == other.valid;
27+
28+
/// <summary>
29+
/// Determines whether this stamp represents the same version of the lock state
30+
/// as the given stamp.
31+
/// </summary>
32+
/// <param name="other">The lock stamp to compare.</param>
33+
/// <returns><see langword="true"/> of this stamp is equal to <paramref name="other"/>; otherwise, <see langword="false"/>.</returns>
34+
public bool Equals(LockStamp other) => Equals(in other);
35+
36+
/// <summary>
37+
/// Determines whether this stamp represents the same version of the lock state
38+
/// as the given stamp.
39+
/// </summary>
40+
/// <param name="other">The lock stamp to compare.</param>
41+
/// <returns><see langword="true"/> of this stamp is equal to <paramref name="other"/>; otherwise, <see langword="false"/>.</returns>
42+
public override bool Equals([NotNullWhen(true)] object? other) => other is LockStamp stamp && Equals(in stamp);
43+
44+
/// <summary>
45+
/// Computes hash code for this stamp.
46+
/// </summary>
47+
/// <returns>The hash code of this stamp.</returns>
48+
public override int GetHashCode() => HashCode.Combine(valid, version);
49+
50+
/// <summary>
51+
/// Determines whether the first stamp represents the same version of the lock state
52+
/// as the second stamp.
53+
/// </summary>
54+
/// <param name="first">The first lock stamp to compare.</param>
55+
/// <param name="second">The second lock stamp to compare.</param>
56+
/// <returns><see langword="true"/> of <paramref name="first"/> stamp is equal to <paramref name="second"/>; otherwise, <see langword="false"/>.</returns>
57+
public static bool operator ==(in LockStamp first, in LockStamp second)
58+
=> first.Equals(in second);
59+
60+
/// <summary>
61+
/// Determines whether the first stamp represents the different version of the lock state
62+
/// as the second stamp.
63+
/// </summary>
64+
/// <param name="first">The first lock stamp to compare.</param>
65+
/// <param name="second">The second lock stamp to compare.</param>
66+
/// <returns><see langword="true"/> of <paramref name="first"/> stamp is not equal to <paramref name="second"/>; otherwise, <see langword="false"/>.</returns>
67+
public static bool operator !=(in LockStamp first, in LockStamp second)
68+
=> !first.Equals(in second);
69+
}
70+
}

src/DotNext.Threading/Threading/AsyncReaderWriterLock.cs

Lines changed: 1 addition & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace DotNext.Threading;
1414
/// This lock doesn't support recursion.
1515
/// </remarks>
1616
[DebuggerDisplay($"Readers = {{{nameof(CurrentReadCount)}}}, WriteLockHeld = {{{nameof(IsWriteLockHeld)}}}")]
17-
public class AsyncReaderWriterLock : QueuedSynchronizer, IAsyncDisposable
17+
public partial class AsyncReaderWriterLock : QueuedSynchronizer, IAsyncDisposable
1818
{
1919
private new sealed class WaitNode :
2020
QueuedSynchronizer.WaitNode,
@@ -121,69 +121,6 @@ public static void Initialize(WaitNode node)
121121
=> node.IsWriteLock = node.DrainOnReturn = true;
122122
}
123123

124-
/// <summary>
125-
/// Represents lock stamp used for optimistic reading.
126-
/// </summary>
127-
[StructLayout(LayoutKind.Auto)]
128-
public readonly struct LockStamp : IEquatable<LockStamp>
129-
{
130-
private readonly ulong version;
131-
private readonly bool valid;
132-
133-
internal LockStamp(in State state)
134-
{
135-
version = state.Version;
136-
valid = true;
137-
}
138-
139-
internal bool IsValid(in State state)
140-
=> valid && state.Version == version && !state.WriteLock;
141-
142-
private bool Equals(in LockStamp other) => version == other.version && valid == other.valid;
143-
144-
/// <summary>
145-
/// Determines whether this stamp represents the same version of the lock state
146-
/// as the given stamp.
147-
/// </summary>
148-
/// <param name="other">The lock stamp to compare.</param>
149-
/// <returns><see langword="true"/> of this stamp is equal to <paramref name="other"/>; otherwise, <see langword="false"/>.</returns>
150-
public bool Equals(LockStamp other) => Equals(in other);
151-
152-
/// <summary>
153-
/// Determines whether this stamp represents the same version of the lock state
154-
/// as the given stamp.
155-
/// </summary>
156-
/// <param name="other">The lock stamp to compare.</param>
157-
/// <returns><see langword="true"/> of this stamp is equal to <paramref name="other"/>; otherwise, <see langword="false"/>.</returns>
158-
public override bool Equals([NotNullWhen(true)] object? other) => other is LockStamp stamp && Equals(in stamp);
159-
160-
/// <summary>
161-
/// Computes hash code for this stamp.
162-
/// </summary>
163-
/// <returns>The hash code of this stamp.</returns>
164-
public override int GetHashCode() => HashCode.Combine(valid, version);
165-
166-
/// <summary>
167-
/// Determines whether the first stamp represents the same version of the lock state
168-
/// as the second stamp.
169-
/// </summary>
170-
/// <param name="first">The first lock stamp to compare.</param>
171-
/// <param name="second">The second lock stamp to compare.</param>
172-
/// <returns><see langword="true"/> of <paramref name="first"/> stamp is equal to <paramref name="second"/>; otherwise, <see langword="false"/>.</returns>
173-
public static bool operator ==(in LockStamp first, in LockStamp second)
174-
=> first.Equals(in second);
175-
176-
/// <summary>
177-
/// Determines whether the first stamp represents the different version of the lock state
178-
/// as the second stamp.
179-
/// </summary>
180-
/// <param name="first">The first lock stamp to compare.</param>
181-
/// <param name="second">The second lock stamp to compare.</param>
182-
/// <returns><see langword="true"/> of <paramref name="first"/> stamp is not equal to <paramref name="second"/>; otherwise, <see langword="false"/>.</returns>
183-
public static bool operator !=(in LockStamp first, in LockStamp second)
184-
=> !first.Equals(in second);
185-
}
186-
187124
private State state;
188125
private ThreadLocal<bool>? lockOwnerState;
189126

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
using System.Runtime.InteropServices;
3+
4+
namespace DotNext.Threading;
5+
6+
partial struct ReaderWriterSpinLock
7+
{
8+
/// <summary>
9+
/// Represents lock stamp used for optimistic reading.
10+
/// </summary>
11+
[StructLayout(LayoutKind.Auto)]
12+
public readonly struct LockStamp : IEquatable<LockStamp>
13+
{
14+
private readonly uint version;
15+
private readonly bool valid;
16+
17+
internal LockStamp(ref readonly uint version)
18+
{
19+
this.version = Volatile.Read(in version);
20+
valid = true;
21+
}
22+
23+
internal bool IsValid(in uint version) => valid && this.version == Volatile.Read(in version);
24+
25+
private bool Equals(in LockStamp other)
26+
=> version == other.version && valid == other.valid;
27+
28+
/// <summary>
29+
/// Determines whether this stamp represents the same version of the lock state
30+
/// as the given stamp.
31+
/// </summary>
32+
/// <param name="other">The lock stamp to compare.</param>
33+
/// <returns><see langword="true"/> of this stamp is equal to <paramref name="other"/>; otherwise, <see langword="false"/>.</returns>
34+
public bool Equals(LockStamp other) => Equals(in other);
35+
36+
/// <summary>
37+
/// Determines whether this stamp represents the same version of the lock state
38+
/// as the given stamp.
39+
/// </summary>
40+
/// <param name="other">The lock stamp to compare.</param>
41+
/// <returns><see langword="true"/> of this stamp is equal to <paramref name="other"/>; otherwise, <see langword="false"/>.</returns>
42+
public override bool Equals([NotNullWhen(true)] object? other) => other is LockStamp stamp && Equals(in stamp);
43+
44+
/// <summary>
45+
/// Computes hash code for this stamp.
46+
/// </summary>
47+
/// <returns>The hash code of this stamp.</returns>
48+
public override int GetHashCode() => HashCode.Combine(valid, version);
49+
50+
/// <summary>
51+
/// Determines whether the first stamp represents the same version of the lock state
52+
/// as the second stamp.
53+
/// </summary>
54+
/// <param name="first">The first lock stamp to compare.</param>
55+
/// <param name="second">The second lock stamp to compare.</param>
56+
/// <returns><see langword="true"/> of <paramref name="first"/> stamp is equal to <paramref name="second"/>; otherwise, <see langword="false"/>.</returns>
57+
public static bool operator ==(in LockStamp first, in LockStamp second)
58+
=> first.Equals(in second);
59+
60+
/// <summary>
61+
/// Determines whether the first stamp represents the different version of the lock state
62+
/// as the second stamp.
63+
/// </summary>
64+
/// <param name="first">The first lock stamp to compare.</param>
65+
/// <param name="second">The second lock stamp to compare.</param>
66+
/// <returns><see langword="true"/> of <paramref name="first"/> stamp is not equal to <paramref name="second"/>; otherwise, <see langword="false"/>.</returns>
67+
public static bool operator !=(in LockStamp first, in LockStamp second)
68+
=> !first.Equals(in second);
69+
}
70+
}

src/DotNext/Threading/ReaderWriterSpinLock.cs

Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10,73 +10,10 @@ namespace DotNext.Threading;
1010
/// This type should not be used to synchronize access to the I/O intensive resources.
1111
/// </remarks>
1212
[StructLayout(LayoutKind.Auto)]
13-
public struct ReaderWriterSpinLock
13+
public partial struct ReaderWriterSpinLock
1414
{
15-
/// <summary>
16-
/// Represents lock stamp used for optimistic reading.
17-
/// </summary>
18-
[StructLayout(LayoutKind.Auto)]
19-
public readonly struct LockStamp : IEquatable<LockStamp>
20-
{
21-
private readonly uint version;
22-
private readonly bool valid;
23-
24-
internal LockStamp(ref readonly uint version)
25-
{
26-
this.version = Volatile.Read(in version);
27-
valid = true;
28-
}
29-
30-
internal bool IsValid(in uint version) => valid && this.version == Volatile.Read(in version);
31-
32-
private bool Equals(in LockStamp other)
33-
=> version == other.version && valid == other.valid;
34-
35-
/// <summary>
36-
/// Determines whether this stamp represents the same version of the lock state
37-
/// as the given stamp.
38-
/// </summary>
39-
/// <param name="other">The lock stamp to compare.</param>
40-
/// <returns><see langword="true"/> of this stamp is equal to <paramref name="other"/>; otherwise, <see langword="false"/>.</returns>
41-
public bool Equals(LockStamp other) => Equals(in other);
42-
43-
/// <summary>
44-
/// Determines whether this stamp represents the same version of the lock state
45-
/// as the given stamp.
46-
/// </summary>
47-
/// <param name="other">The lock stamp to compare.</param>
48-
/// <returns><see langword="true"/> of this stamp is equal to <paramref name="other"/>; otherwise, <see langword="false"/>.</returns>
49-
public override bool Equals([NotNullWhen(true)] object? other) => other is LockStamp stamp && Equals(in stamp);
50-
51-
/// <summary>
52-
/// Computes hash code for this stamp.
53-
/// </summary>
54-
/// <returns>The hash code of this stamp.</returns>
55-
public override int GetHashCode() => HashCode.Combine(valid, version);
56-
57-
/// <summary>
58-
/// Determines whether the first stamp represents the same version of the lock state
59-
/// as the second stamp.
60-
/// </summary>
61-
/// <param name="first">The first lock stamp to compare.</param>
62-
/// <param name="second">The second lock stamp to compare.</param>
63-
/// <returns><see langword="true"/> of <paramref name="first"/> stamp is equal to <paramref name="second"/>; otherwise, <see langword="false"/>.</returns>
64-
public static bool operator ==(in LockStamp first, in LockStamp second)
65-
=> first.Equals(in second);
66-
67-
/// <summary>
68-
/// Determines whether the first stamp represents the different version of the lock state
69-
/// as the second stamp.
70-
/// </summary>
71-
/// <param name="first">The first lock stamp to compare.</param>
72-
/// <param name="second">The second lock stamp to compare.</param>
73-
/// <returns><see langword="true"/> of <paramref name="first"/> stamp is not equal to <paramref name="second"/>; otherwise, <see langword="false"/>.</returns>
74-
public static bool operator !=(in LockStamp first, in LockStamp second)
75-
=> !first.Equals(in second);
76-
}
77-
7815
private const int WriteLockState = int.MinValue;
79-
private const int NoLockState = default;
16+
private const int NoLockState = 0;
8017
private const int SingleReaderState = 1;
8118

8219
private volatile int state;
@@ -90,7 +27,7 @@ public readonly LockStamp TryOptimisticRead()
9027
{
9128
// Ordering of version and lock state must be respected:
9229
// Write lock acquisition changes the state to Acquired and then increments the version.
93-
// Optimistic read lock reads the version and then checks Acquired lock state to avoid false positivies.
30+
// Optimistic read lock reads the version and then checks Acquired lock state to avoid false positives.
9431
var stamp = new LockStamp(in version);
9532
return state is WriteLockState ? default : stamp;
9633
}

0 commit comments

Comments
 (0)