Ejemplo n.º 1
0
 private RwVaultInternalLockedResource([NotNull] ReadWriteVault <T> owner, [NotNull] Box b, [CanBeNull] Action <TimeSpan?, CancellationToken> upgradeAction, [CanBeNull] Action upgradeForeverAction, AcquisitionMode mode)
 {
     _mode                 = mode.ValueOrThrowIfNDef();
     _b                    = b ?? throw new ArgumentNullException(nameof(b));
     _upgradeAction        = upgradeAction;
     _upgradeForeverAction = upgradeForeverAction;
     _owner                = owner ?? throw new ArgumentNullException(nameof(owner));
     _releaseFlag          = default;
     _isGood               = true;
     Debug.Assert((_upgradeAction == null) == (_upgradeForeverAction == null),
                  "Both ok, neither ok.  Exactly one not ok.");
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Try to get the resource until earliest of following happens
 ///     1- get it successfully,
 ///     2- cancellation requested via <paramref name="token"/>
 ///     3- time specified by <paramref name="timeout"/> exceeded
 /// </summary>
 /// <param name="timeout">how long should we wait?  Null indicates potential infinite wait .</param>
 /// <param name="token">token by which another thread can cancel the attempt to obtain resource</param>
 /// <param name="mode">acquisition mode</param>
 /// <returns>the resource</returns>
 /// <exception cref="ArgumentOutOfRangeException">non-null, non-positive <paramref name="timeout"/> argument; OR mode not
 /// a defined value of the <see cref="AcquisitionMode"/> <see langword="enum"/></exception>
 /// <exception cref="TimeoutException">didn't obtain it within time specified by <paramref name="timeout"/></exception>
 /// <exception cref="OperationCanceledException">operation was cancelled</exception>
 /// <exception cref="ObjectDisposedException">the object was disposed</exception>
 /// <exception cref="LockAlreadyHeldThreadException">the thread attempting to obtain the lock already holds the lock.</exception>
 /// <remarks>After method returns value, you are responsible for disposal until passing to ultimate user behind a method whose return
 /// value is annotated by the <see cref="UsingMandatoryAttribute"/>.  This means you must dispose of it yourself in all failure/exceptional
 /// cases after this method returns a value but before ultimately passed to user.</remarks>
 protected RwVaultInternalLockedResource ExecuteGetInternalLockedResource(TimeSpan?timeout, CancellationToken token, AcquisitionMode mode)
 {
     ThrowIfDisposingOrDisposed();
     if (timeout.HasValue && timeout.Value <= TimeSpan.Zero)
     {
         throw new ArgumentOutOfRangeException(nameof(timeout), timeout, @"Must be positive.");
     }
     return(RwVaultInternalLockedResource.CreateInternalLockedResource(this, timeout, token, mode.ValueOrThrowIfNDef()));
 }
Ejemplo n.º 3
0
            CreateInternalLockedResource <TV>([NotNull] TV owner, TimeSpan?timeout,
                                              CancellationToken token, AcquisitionMode mode, bool vaultDisposing = false) where TV : ReadWriteVault <T>
            {
                if (owner == null)
                {
                    throw new ArgumentNullException(nameof(owner));
                }
                if (timeout == null && token == CancellationToken.None)
                {
                    throw new ArgumentException("Cancellation token may not be none if no timeout is specified.");
                }
                if (vaultDisposing && !owner.DisposeInProgress)
                {
                    throw new InvalidOperationException($"The {nameof(vaultDisposing)} parameter indicates this call is part of a vault disposal routine." +
                                                        "  The vault, however, is not performing such a routine.");
                }
                if (!vaultDisposing && owner.IsDisposed)
                {
                    throw new ArgumentException(@"The vault is disposed.", nameof(owner));
                }
                mode = mode.ValueOrThrowIfNDef();
                (Box AcquiredBox, bool Cancelled, bool TimedOut)boxRes = default;
                try
                {
                    boxRes = AcquireBoxPointer(owner, timeout, mode, token);
                    if (boxRes.Cancelled)
                    {
                        throw new OperationCanceledException(token);
                    }
                    if (boxRes.TimedOut)
                    {
                        throw new TimeoutException(
                                  "Unable to acquire resource within " +
                                  $"[{(timeout ?? owner.DefaultTimeout).TotalMilliseconds:F3}] milliseconds.");
                    }
                    (Action <TimeSpan?, CancellationToken> upgradeAction, Action upgradeForeverAction) =
                        GetUpgradeActions(mode);
                    Debug.Assert((upgradeForeverAction == null) == (upgradeAction == null));

                    return(new RwVaultInternalLockedResource(owner, boxRes.AcquiredBox, upgradeAction, upgradeForeverAction, mode));
                }
                catch (LockRecursionException ex)
                {
                    Debug.Assert(boxRes.AcquiredBox == null);
                    throw new RwLockAlreadyHeldThreadException(Thread.CurrentThread.ManagedThreadId, ex);
                }
                catch (Exception)
                {
                    if (boxRes.AcquiredBox != null)
                    {
                        ReleaseLock(owner._locker, mode);
                    }
                    throw;
                }

                (Action <TimeSpan?, CancellationToken> UpgradeAction, Action UpgradeForeverAction) GetUpgradeActions(AcquisitionMode m)
                {
                    return(m == AcquisitionMode.UpgradableReadOnly
                        ? (
                               (TimeSpan? ts, CancellationToken tkn) =>
                               Upgrade(ts, tkn), () => UpgradeForever()) : (NullUpgradeAction, NullUpgradeForeverAction));
                }

                void Upgrade(TimeSpan?ts, CancellationToken tkn) =>
                CreateInternalLockedResource(owner, ts, tkn, AcquisitionMode.ReadWrite);

                void UpgradeForever() => CreateInternalLockedResourceBlockForever(owner, AcquisitionMode.ReadWrite);
            }
Ejemplo n.º 4
0
 /// <summary>
 /// Try to get the locked resource.  This thread will block (potentially forever)
 /// until the resource is obtained or an exception is thrown.
 /// </summary>
 /// <returns>The locked resource</returns>
 /// <exception cref="ObjectDisposedException">object was disposed</exception>
 /// <exception cref="LockAlreadyHeldThreadException">the thread attempting to obtain the lock,
 /// already holds the lock.</exception>
 protected RwVaultInternalLockedResource ExecuteGetInternalLockedResourceBlockForever(AcquisitionMode mode)
 {
     ThrowIfDisposingOrDisposed();
     return(RwVaultInternalLockedResource.CreateInternalLockedResourceBlockForever(this, mode.ValueOrThrowIfNDef()));
 }