Example #1
0
        /// <summary>
        /// Asynchronously waits for a signal from another thread, aborting if the operation is cancelled
        /// </summary>
        /// <param name="token"></param>
        /// <returns>True, if the operation succeeds. False if the operation is cancelled</returns>
        public async Task <bool> WaitAsync(CancellationToken token)
        {
            //The SyncLock to use
            SyncLock blocker;

            //The lock wrapper
            DisposableWrapper wrapper;

            //Next acquires the lock for this instance, and enqueues our wrapped lock
            using (await _sync.GetLockAsync().ConfigureAwait(false))
            {
                //If we have leftover pulses, consume one instead of waiting.
                if (pulses > 0)
                {
                    pulses--;
                    return(true);
                }

                //Otherwise create the SyncLock
                blocker = new SyncLock();

                //And wrap up a lock from it for eventual release
                queue.Enqueue(wrapper = new DisposableWrapper(await blocker.GetLockAsync()));
            }

            //Finally, waits for the lock, and if we time out, we release it ourselves.
            //If on the rare chance the lock is released between the time we stop waiting and the time we try to release it, say we were signalled successfully
            if (!await blocker.TryGetLockAsync(token, l => l.Dispose()))
            {
                return(!wrapper.Dispose());
            }

            //say we were signalled successfully.
            return(true);
        }
Example #2
0
        /// <summary>
        /// Waits for a signal from another thread, aborting if the operation is cancelled
        /// </summary>
        /// <param name="token"></param>
        /// <returns>True, if the operation succeeds. False if the operation is cancelled</returns>
        public bool Wait(CancellationToken token)
        {
            //Create a new lock to wait for
            SyncLock blocker;

            //Then acquires the lock and wraps it up in preperation to offering it to the queue
            DisposableWrapper wrapper;

            //Next acquires the lock for this instance, and enqueues our wrapped lock
            using (_sync.GetLock())
            {
                if (pulses > 0)
                {
                    pulses--;
                    return(true);
                }
                blocker = new SyncLock();
                queue.Enqueue(wrapper = new DisposableWrapper(blocker.GetLock()));
            }

            //Finally, waits for the lock, and if we time out, we release it ourselves.
            //If on the rare chance the lock is released between the time we stop waiting and the time we try to release it, say we were signalled successfully
            if (!blocker.TryGetLock(token, out IDisposable @lock))
            {
                return(!wrapper.Dispose()); //Just in case a last minute call lets us return true;
            }
            //If we did get a lock however, release that
            @lock.Dispose();

            //Before finally signaling that we were successfuly
            return(true);
        }