Skip to content

Commit

Permalink
Release same token twice throws InvalidOperation
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Rogers committed Dec 2, 2013
1 parent a6f0c7b commit 02f966e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 21 deletions.
30 changes: 10 additions & 20 deletions projects/LockSample/source/LockSample.Core/ExclusiveLock.cs
Expand Up @@ -11,21 +11,18 @@ namespace LockSample

public class ExclusiveLock
{
private readonly LockState state;

private Token owner;
private TaskCompletionSource<Token> nextOwner;

public ExclusiveLock()
{
this.state = new LockState();
}

public Task<Token> AcquireAsync()
{
if (this.owner.State == null)
if (this.owner == null)
{
this.owner = new Token(this.state);
this.owner = new OwnerToken();
}
else
{
Expand All @@ -47,36 +44,29 @@ public Task<Token> AcquireAsync()

public void Release(Token token)
{
if (token.State != this.state)
if (this.owner != token)
{
throw new InvalidOperationException("The token is invalid.");
throw new InvalidOperationException("The token is not valid.");
}

this.owner = null;
if (this.nextOwner != null)
{
this.owner = new Token(this.state);
this.owner = new OwnerToken();
this.nextOwner.SetResult(this.owner);
}
}

public struct Token
public abstract class Token
{
private readonly object state;

public Token(object state)
{
this.state = state;
}

public object State
protected Token()
{
get { return this.state; }
}
}

private sealed class LockState
private sealed class OwnerToken : Token
{
public LockState()
public OwnerToken()
{
}
}
Expand Down
Expand Up @@ -44,7 +44,19 @@ public void Release_invalid_token_throws_InvalidOperation()
{
ExclusiveLock l = new ExclusiveLock();

Assert.Throws<InvalidOperationException>(() => l.Release(new ExclusiveLock.Token()));
Assert.Throws<InvalidOperationException>(() => l.Release(new MyToken()));
}

[Fact]
public void Release_same_token_twice_throws_InvalidOperation()
{
ExclusiveLock l = new ExclusiveLock();

ExclusiveLock.Token token = AssertTaskCompleted(l.AcquireAsync());

l.Release(token);

Assert.Throws<InvalidOperationException>(() => l.Release(token));
}

private static TResult AssertTaskCompleted<TResult>(Task<TResult> task)
Expand All @@ -59,5 +71,12 @@ private static Task<TResult> AssertTaskPending<TResult>(Task<TResult> task)
Assert.False(task.IsFaulted, "Task should not be faulted: " + task.Exception);
return task;
}

private sealed class MyToken : ExclusiveLock.Token
{
public MyToken()
{
}
}
}
}

0 comments on commit 02f966e

Please sign in to comment.