Beispiel #1
0
        internal static Task <TResult> FromAsyncBeginEnd <TArg1, TArg2, TArg3> (Func <TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod, Func <IAsyncResult, TResult> endMethod,
                                                                                TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
        {
            if (beginMethod == null)
            {
                throw new ArgumentNullException("beginMethod");
            }

            if (endMethod == null)
            {
                throw new ArgumentNullException("endMethod");
            }

            if ((creationOptions & Task.WorkerTaskNotSupportedOptions) != 0)
            {
                throw new ArgumentOutOfRangeException("creationOptions");
            }

            var tcs            = new TaskCompletionSource <TResult> (state, creationOptions);
            var alreadyInvoked = new AtomicBoolean();
            var iar            = beginMethod(arg1, arg2, arg3, l => {
                if (alreadyInvoked.TryRelaxedSet())
                {
                    InnerInvoke(tcs, endMethod, l);
                }
            }, state);

            if (iar != null && iar.CompletedSynchronously && alreadyInvoked.TryRelaxedSet())
            {
                InnerInvoke(tcs, endMethod, iar);
            }

            return(tcs.Task);
        }
Beispiel #2
0
        protected override void EnsureProcessing()
        {
            if (!started.TryRelaxedSet())
            {
                return;
            }

            Task[] tasks = new Task[dataflowBlockOptions.MaxDegreeOfParallelism];
            for (int i = 0; i < tasks.Length; ++i)
            {
                tasks[i] = Task.Factory.StartNew(processQueue);
            }
            Task.Factory.ContinueWhenAll(tasks, (_) => {
                started.Value = false;
                // Re-run ourselves in case of a race when data is available in the end
                if (messageQueue.Count > 0)
                {
                    EnsureProcessing();
                }
                else if (messageQueue.IsCompleted)
                {
                    compHelper.Complete();
                }
            });
        }
Beispiel #3
0
        internal void ContinueWithCore(Task continuation, TaskContinuationOptions kind,
                                       TaskScheduler scheduler, Func <bool> predicate)
        {
            // Already set the scheduler so that user can call Wait and that sort of stuff
            continuation.scheduler = scheduler;
            continuation.schedWait.Set();
            continuation.status = TaskStatus.WaitingForActivation;

            AtomicBoolean launched = new AtomicBoolean();
            EventHandler  action   = delegate(object sender, EventArgs e) {
                if (launched.TryRelaxedSet())
                {
                    if (!predicate())
                    {
                        return;
                    }

                    if (!ContinuationStatusCheck(kind))
                    {
                        continuation.CancelReal();
                        continuation.Dispose();

                        return;
                    }

                    CheckAndSchedule(continuation, kind, scheduler, sender == null);
                }
            };

            if (IsCompleted)
            {
                action(null, EventArgs.Empty);
                return;
            }

            if (completed == null)
            {
                Interlocked.CompareExchange(ref completed, new ConcurrentQueue <EventHandler> (), null);
            }
            completed.Enqueue(action);

            // Retry in case completion was achieved but event adding was too late
            if (IsCompleted)
            {
                action(null, EventArgs.Empty);
            }
        }
        //
        // Taking the Upgradable read lock is like taking a read lock
        // but we limit it to a single upgradable at a time.
        //
        public bool TryEnterUpgradeableReadLock(int millisecondsTimeout)
        {
            var ctstate = CurrentThreadState;

            if (CheckState(ctstate, millisecondsTimeout, LockState.Upgradable))
            {
                ++ctstate.UpgradeableRecursiveCount;
                return(true);
            }

            if (ctstate.LockState.Has(LockState.Read))
            {
                throw new LockRecursionException("The current thread has already entered read mode");
            }

            ++_numUpgradeWaiters;
            var start   = millisecondsTimeout == -1 ? 0 : _stopwatch.ElapsedMilliseconds;
            var taken   = false;
            var success = false;

            // We first try to obtain the upgradeable right
            try
            {
                while (!_upgradableEvent.IsSet() || !taken)
                {
                    try
                    {
                    }
                    finally
                    {
                        taken = _upgradableTaken.TryRelaxedSet();
                    }
                    if (taken)
                    {
                        break;
                    }

                    if (millisecondsTimeout != -1 && (_stopwatch.ElapsedMilliseconds - start) > millisecondsTimeout)
                    {
                        --_numUpgradeWaiters;
                        return(false);
                    }

                    _upgradableEvent.Wait(ComputeTimeout(millisecondsTimeout, start));
                }

                _upgradableEvent.Reset();

                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    // Then it's a simple reader lock acquiring
                    TryEnterReadLock(ComputeTimeout(millisecondsTimeout, start), ref success);
                }
                finally
                {
                    if (success)
                    {
                        ctstate.LockState |= LockState.Upgradable;
                        ctstate.LockState &= ~LockState.Read;
                        --ctstate.ReaderRecursiveCount;
                        ++ctstate.UpgradeableRecursiveCount;
                    }
                    else
                    {
                        _upgradableTaken.Value = false;
                        _upgradableEvent.Set();
                    }
                }

                --_numUpgradeWaiters;
            }
            catch (Exception ex)
            {
                GC.KeepAlive(ex);
                // An async exception occured, if we had taken the upgradable mode, release it
                _upgradableTaken.Value &= (!taken || success);
            }

            return(success);
        }