Skip to content

Commit

Permalink
Changed promise locking again
Browse files Browse the repository at this point in the history
  • Loading branch information
Craig Neuwirt committed Jul 29, 2019
1 parent a9884bc commit e8d12a1
Showing 1 changed file with 52 additions and 93 deletions.
145 changes: 52 additions & 93 deletions Source/Miruken/Concurrency/Promise.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public abstract partial class Promise : AbstractAsyncResult
{
protected ResolveCallback _fulfilled;
protected RejectCallback _rejected;
protected readonly ReaderWriterLockSlim _lock;
protected readonly object _guard = new object();

public PromiseState State { get; protected set; }

Expand All @@ -61,7 +61,6 @@ public abstract partial class Promise : AbstractAsyncResult
protected Promise()
{
State = PromiseState.Pending;
_lock = new ReaderWriterLockSlim();
}

#region Then
Expand Down Expand Up @@ -177,39 +176,21 @@ public void Cancelled(CancelledCallback cancelled)
{
if (cancelled == null) return;

if (IsCompleted)
lock (_guard)
{
if (State == PromiseState.Cancelled)
cancelled(_exception as CancelledException);
return;
}

_lock.EnterUpgradeableReadLock();

if (IsCompleted)
{
_lock.ExitUpgradeableReadLock();

if (State == PromiseState.Cancelled)
cancelled(_exception as CancelledException);
return;
}

_lock.EnterWriteLock();

try
{
_rejected += (ex, s) =>
if (!IsCompleted)
{
if (ex is CancelledException cancel)
cancelled(cancel);
};
}
finally
{
_lock.ExitWriteLock();
_lock.ExitUpgradeableReadLock();
_rejected += (ex, s) =>
{
if (ex is CancelledException cancel)
cancelled(cancel);
};
return;
}
}

if (State == PromiseState.Cancelled)
cancelled(_exception as CancelledException);
}

#endregion
Expand Down Expand Up @@ -1041,58 +1022,56 @@ public new T Wait(int? millisecondsTimeout = null)

protected void Resolve(T result, bool synchronous)
{
Complete(result, synchronous, () =>
ResolveCallback fulfilled = null;

lock (_guard)
{
ResolveCallback fulfilled;
_lock.EnterWriteLock();
try
Complete(result, synchronous, () =>
{
State = PromiseState.Fulfilled;
fulfilled = _fulfilled;
_fulfilled = null;
_rejected = null;
}
finally
{
_lock.ExitWriteLock();
}
fulfilled?.Invoke((T) _result, synchronous);
});
});
}

fulfilled?.Invoke((T)_result, synchronous);
}

protected void Reject(Exception exception, bool synchronous)
{
Complete(exception, synchronous, () =>
Action onCancel = null;
RejectCallback rejected = null;

lock (_guard)
{
if (_onCancel != null && exception is CancelledException)
Complete(exception, synchronous, () =>
{
try
{
_onCancel();
}
catch
{
// consume errors
}
}
if (_onCancel != null && exception is CancelledException)
onCancel = _onCancel;
RejectCallback rejected;
_lock.EnterWriteLock();
try
{
State = exception is CancelledException
? PromiseState.Cancelled
: PromiseState.Rejected;
rejected = _rejected;
_fulfilled = null;
_rejected = null;
});
}

if (onCancel != null)
{
try
{
onCancel();
}
finally
catch
{
_lock.ExitWriteLock();
// consume errors
}
rejected?.Invoke(exception, synchronous);
});
}

rejected?.Invoke(exception, synchronous);
}

protected virtual Promise<R> CreateChild<R>(Promise<R>.PromiseOwner owner)
Expand Down Expand Up @@ -1120,40 +1099,20 @@ protected virtual Promise<R> CreateChild<R>(Promise<R>.PromiseOwner owner)

protected void Subscribe(ResolveCallback resolve, RejectCallback reject)
{
if (IsCompleted)
lock (_guard)
{
if (State == PromiseState.Fulfilled)
resolve(_result, CompletedSynchronously);
else
reject(_exception, CompletedSynchronously);
return;
}

_lock.EnterUpgradeableReadLock();

if (IsCompleted)
{
_lock.ExitUpgradeableReadLock();

if (State == PromiseState.Fulfilled)
resolve(_result, CompletedSynchronously);
else
reject(_exception, CompletedSynchronously);
return;
if (!IsCompleted)
{
_fulfilled += resolve;
_rejected += reject;
return;
}
}

_lock.EnterWriteLock();

try
{
_fulfilled += resolve;
_rejected += reject;
}
finally
{
_lock.ExitWriteLock();
_lock.ExitUpgradeableReadLock();
}
if (State == PromiseState.Fulfilled)
resolve(_result, CompletedSynchronously);
else
reject(_exception, CompletedSynchronously);
}

#region Build
Expand Down

0 comments on commit e8d12a1

Please sign in to comment.