Beispiel #1
0
        /// <summary>A wrapper over DispatchSync that calls a value-producing function and returns it's result</summary>
        /// <typeparam name="T">Result type</typeparam>
        /// <param name="queue">The queue to execute the function on</param>
        /// <param name="func">The function to execute</param>
        /// <returns>The return value of func</returns>
        public static T DispatchSync <T>(this IDispatchQueue queue, Func <T> func)
        {
            T result = default(T);

            queue.DispatchSync(() => { result = func(); });
            return(result);
        }
Beispiel #2
0
        //--- Constructors ---

        /// <summary>
        /// Create an instance of the work queue.
        /// </summary>
        /// <param name="handler">Dispatch action for work item Type and with completion callback.</param>
        /// <param name="maxParallelism">Maximum number of items being dispatch simultaneously against the dispatch queue.</param>
        /// <param name="dispatchQueue">Dispatch queue for work items.</param>
        public ProcessingQueue(Action <T, Action> handler, int maxParallelism, IDispatchQueue dispatchQueue)
        {
            if (dispatchQueue == null)
            {
                throw new ArgumentNullException("dispatchQueue");
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            if ((maxParallelism <= 0) || (maxParallelism > MAX_PARALLELISM))
            {
                throw new ArgumentException(string.Format("maxParallelism must be between 1 and {0:#,##0}", MAX_PARALLELISM), "maxParallelism");
            }
            _handler       = handler;
            _dispatchQueue = dispatchQueue;

            // prime the pending queue with dispatchers
            for (var i = 0; i < maxParallelism; ++i)
            {
                if (!_pending.TryEnqueue(StartWorkItem))
                {
                    throw new NotSupportedException();
                }
            }
        }
 //init
 public DirectSignalProvider(IEventQueue <TKey> eventQueues, IDispatchQueue <TKey> dispatchQueues,
                             IMonitor <TKey> eventSink, ISignalEventQueries <TKey> eventQueries,
                             ISignalDispatchQueries <TKey> dispatchQueries, SenderSettings senderSettings)
     : base(eventQueues, dispatchQueues, eventSink, eventQueries, dispatchQueries, senderSettings)
 {
     _isStarted = false;
 }
Beispiel #4
0
 //ctor
 public SendDispatchCommand(IDispatchChannelRegistry <TKey> channelRegistry, ILogger logger,
                            IDispatchQueue <TKey> dispatchQueue, IMonitor <TKey> monitor)
 {
     _channelRegistry = channelRegistry;
     _logger          = logger;
     _dispatchQueue   = dispatchQueue;
     _monitor         = monitor;
 }
Beispiel #5
0
 /// <summary>
 /// Create a new environment.
 /// </summary>
 /// <param name="dispatchQueue">Dispatch queue to use for the environment.</param>
 /// <param name="taskTimerFactory"><see cref="TaskTimer"/> factory to use for the environment.</param>
 /// <returns>A new <see cref="TaskEnv"/> instance.</returns>
 public static TaskEnv New(IDispatchQueue dispatchQueue, TaskTimerFactory taskTimerFactory)
 {
     if (dispatchQueue == null)
     {
         throw new ArgumentNullException("dispatchQueue");
     }
     return(new TaskEnv(dispatchQueue, taskTimerFactory));
 }
 public DatabaseDispatchProvider(IDispatchQueue <TKey> dispatchQueues, IMonitor <TKey> eventSink, SenderSettings senderSettings,
                                 IDispatchChannelRegistry <TKey> dispatcherRegistry, ISignalDispatchQueries <TKey> dispatchQueries,
                                 ILogger logger, IChangeNotifier <SignalDispatch <TKey> > changeNotifier,
                                 ILockTracker <TKey> lockTracker, IConsolidationLockTracker <TKey> consolidationLockTracker)
     : this(dispatchQueues, eventSink, senderSettings, dispatcherRegistry, dispatchQueries, logger, lockTracker, consolidationLockTracker)
 {
     _changeNotifier = changeNotifier;
 }
Beispiel #7
0
 /// <summary>
 /// Clone the current task environment with a provided dispatch queue.
 /// </summary>
 /// <param name="dispatchQueue">Dispatch queue to use for the environment.</param>
 /// <returns>A new <see cref="TaskEnv"/> instance.</returns>
 public static TaskEnv Clone(IDispatchQueue dispatchQueue)
 {
     if (dispatchQueue == null)
     {
         throw new ArgumentNullException("dispatchQueue");
     }
     return(new TaskEnv(_currentEnv, dispatchQueue, CurrentTimerFactoryOrNull));
 }
        public TimerQueue(IDispatchQueue dispatchQueue, IDispatcher dispatcher)
        {
            mDispatchQueue = dispatchQueue ?? throw new ArgumentNullException("dispatchQueue");
            mDispatcher    = dispatcher ?? throw new ArgumentNullException("dispatcher");

            mTimer = new Timer(OnTimerExecute);

            mScheduleWorkForExecutionCallback = OnScheduleWorkForExecution;
        }
Beispiel #9
0
 //ctor
 public CheckConsolidationLockExpirationCommand(IConsolidationLockTracker <TKey> lockTracker,
                                                IConsolidationLockQueries <TKey> consolidationLockQueries, SenderSettings settings,
                                                IDispatchQueue <TKey> dispatchQueue)
 {
     _consolidationLockTracker = lockTracker;
     _consolidationLockQueries = consolidationLockQueries;
     _settings      = settings;
     _dispatchQueue = dispatchQueue;
 }
Beispiel #10
0
 /// <summary>
 /// Enqueue a callback as a work item to be invoked with a provided <see cref="TaskEnv"/>.
 /// </summary>
 /// <typeparam name="T">Result value type of callback.</typeparam>
 /// <param name="dispatchQueue">DispatchQueue to enqueue work into.</param>
 /// <param name="callback">Work item callback.</param>
 /// <param name="env">Environment for work item invocation.</param>
 /// <param name="result">Synchronization handle for work item.</param>
 /// <returns>The synchronization handle provided to the method.</returns>
 public static Result <T> QueueWorkItemWithEnv <T>(this IDispatchQueue dispatchQueue, Func <T> callback, TaskEnv env, Result <T> result)
 {
     if (env == null)
     {
         throw new ArgumentException("env");
     }
     dispatchQueue.QueueWorkItem(env.MakeAction(callback, result));
     return(result);
 }
        public void PinTo(IDispatchQueue dispatchQueue)
        {
            // TODO 2.0 (steveb): remove implementation

            if (_dispatchQueue != null)
            {
                throw new InvalidOperationException("RendezVousEvent is already pinned to an IDispatchQueue");
            }
            _dispatchQueue = dispatchQueue;
        }
Beispiel #12
0
 //init
 public BaseSignalProvider(IEventQueue <TKey> eventQueue, IDispatchQueue <TKey> dispatchQueue, IMonitor <TKey> eventSink,
                           ISignalEventQueries <TKey> eventQueries, ISignalDispatchQueries <TKey> dispatchQueries, SenderSettings senderSettings)
 {
     _eventQueue      = eventQueue;
     _dispatchQueue   = dispatchQueue;
     _monitor         = eventSink;
     _eventQueries    = eventQueries;
     _dispatchQueries = dispatchQueries;
     _senderSettings  = senderSettings;
 }
 //ctor
 public ConsolidateDispatchCommand(ILogger logger, ISignalDispatchQueries <TKey> signalDispatchQueries,
                                   IDispatchQueue <TKey> dispatchQueue, IEnumerable <ITemplateDataConsolidator> consolidators,
                                   IEventSettingsQueries <TKey> eventSettingsQueries)
 {
     _logger = logger;
     _signalDispatchQueries = signalDispatchQueries;
     _dispatchQueue         = dispatchQueue;
     _consolidators         = consolidators.ToArray();
     _eventSettingsQueries  = eventSettingsQueries;
 }
Beispiel #14
0
        private static void FibonacciThreadPool(IDispatchQueue stp, int n, TimeSpan delay, out int value, out TimeSpan elapsed)
        {
            _log.Debug("FibonacciThreadPool");

            var sw = Stopwatch.StartNew();

            value = Fibonacci(stp, n, delay, new Result <int>(TimeSpan.MaxValue, TaskEnv.New(stp))).Wait();
            sw.Stop();
            elapsed = sw.Elapsed;
        }
Beispiel #15
0
 //init
 public SignalServiceInstanceProvider(IEventQueue <TKey> eventQueues, IDispatchQueue <TKey> dispatchQueues,
                                      IMonitor <TKey> eventSink, ISignalEventQueries <TKey> eventQueries,
                                      ISignalDispatchQueries <TKey> dispatchQueries, SenderSettings senderSettings)
 {
     _eventQueues     = eventQueues;
     _dispatchQueues  = dispatchQueues;
     _monitor         = eventSink;
     _eventQueries    = eventQueries;
     _dispatchQueries = dispatchQueries;
     _senderSettings  = senderSettings;
 }
Beispiel #16
0
        //--- Class Methods ---
        public static bool TryQueueWorkItem(IDispatchQueue queue, Action callback)
        {
            DispatchThread current = CurrentThread;

            if ((current != null) && ReferenceEquals(AsyncUtil.CurrentDispatchQueue, queue))
            {
                // NOTE (steveb): next call can never fail since we're calling the queue work-item method of the current thread
                current.QueueWorkItem(callback);
                return(true);
            }
            return(false);
        }
        public static void DispatchSync(this IDispatchQueue queue, object?context, WaitCallback?work)
        {
            TaskCompletionSource <object?> tcs = new TaskCompletionSource <object?>();

            queue.DispatchAsync(context, (context) =>
            {
                work?.Invoke(context);
                tcs.SetResult(null);
            });

            tcs.Task.Wait();
        }
Beispiel #18
0
 private TaskEnv(TaskEnv env, IDispatchQueue dispatchQueue, TaskTimerFactory taskTimerFactory)
 {
     if (env != null)
     {
         foreach (var entry in env)
         {
             var cloneable = entry.Value as ITaskLifespan;
             Add(entry.Key, cloneable == null ? entry.Value : cloneable.Clone());
         }
     }
     _taskTimerFactory = taskTimerFactory;
     _dispatchQueue    = (dispatchQueue is ImmediateDispatchQueue) ? null : dispatchQueue;
 }
Beispiel #19
0
        /// <summary>A wrapper over DispatchAsync that calls a value-producing function on the queue and returns it's result via a Task</summary>
        /// <remarks>Note: the task "completes" on the dispatch queue, so if you use ConfigureAwait(false) or
        /// TaskContinuationOptions.ExecuteSychronously, you will still be running on the dispatch queue</remarks>
        /// <typeparam name="T">Result type</typeparam>
        /// <param name="queue">The queue to execute the function on</param>
        /// <param name="func">The function to execute</param>
        /// <returns>A task wrapping the return value (or exception) the func produced.</returns>
        public static Task <T> DispatchAsync <T>(this IDispatchQueue queue, Func <T> func)
        {
            var tcs = new TaskCompletionSource <T>();

            queue.DispatchAsync(() => {
                try {
                    tcs.SetResult(func());
                }
                catch (Exception e) {
                    tcs.TrySetException(e);
                }
            });
            return(tcs.Task);
        }
Beispiel #20
0
        //init
        public DispatchProcessor(SenderState <TKey> hubState, IDispatchQueue <TKey> dispatchQueue,
                                 ILogger logger, SenderSettings senderSettings, IDispatchChannelRegistry <TKey> channelRegistry,
                                 IEnumerable <IDispatchProcessingCommand <TKey> > processingCommands)
            : base(logger)
        {
            _hubState           = hubState;
            _dispatchQueue      = dispatchQueue;
            _channelRegistry    = channelRegistry;
            _processingCommands = processingCommands
                                  .OrderBy(x => x.Order)
                                  .ToArray();

            MaxParallelItems = senderSettings.MaxParallelDispatchesProcessed;
        }
Beispiel #21
0
        //init
        public EventProcessor(SenderState <TKey> hubState, IMonitor <TKey> eventSink
                              , ILogger logger, SenderSettings senderSettings
                              , IEventQueue <TKey> eventQueue, IDispatchQueue <TKey> dispatchQueue
                              , IEventHandlerRegistry <TKey> handlerRegistry, IEventSettingsQueries <TKey> eventSettingsQueries)
            : base(logger)
        {
            _hubState             = hubState;
            _monitor              = eventSink;
            _eventQueue           = eventQueue;
            _dispatchQueue        = dispatchQueue;
            _handlerRegistry      = handlerRegistry;
            _eventSettingsQueries = eventSettingsQueries;

            MaxParallelItems = senderSettings.MaxParallelEventsProcessed;
        }
 public NewRoomRequestHandler(
     IDispatchQueue centralDispatchQueue,
     IRoomRepository roomRepository,
     IRoomFactory roomFactory,
     IObserver <TransceiverMetadataUpdatedEvent> transceiverMetadataUpdatedObserver)
 {
     _centralDispatchQueue = centralDispatchQueue
                             ?? throw new ArgumentNullException(nameof(centralDispatchQueue));
     _roomRepository = roomRepository
                       ?? throw new ArgumentNullException(nameof(roomRepository));
     _roomFactory = roomFactory
                    ?? throw new ArgumentNullException(nameof(roomFactory));
     _transceiverMetadataUpdatedObserver = transceiverMetadataUpdatedObserver
                                           ?? throw new ArgumentNullException(nameof(transceiverMetadataUpdatedObserver));
 }
Beispiel #23
0
        //--- Constructors ---
        static Async()
        {
            if (!int.TryParse(System.Configuration.ConfigurationManager.AppSettings["threadpool-min"], out _minThreads))
            {
                _minThreads = 4;
            }
            if (!int.TryParse(System.Configuration.ConfigurationManager.AppSettings["threadpool-max"], out _maxThreads))
            {
                _maxThreads = 200;
            }
            int maxStackSize;

            if (int.TryParse(System.Configuration.ConfigurationManager.AppSettings["max-stacksize"], out maxStackSize))
            {
                _maxStackSize = maxStackSize;
            }

            // check which global dispatch queue implementation to use
            int dummy;

            switch (System.Configuration.ConfigurationManager.AppSettings["threadpool"])
            {
            default:
            case "elastic":
                ThreadPool.GetMinThreads(out dummy, out _minPorts);
                ThreadPool.GetMaxThreads(out dummy, out _maxPorts);
                _log.DebugFormat("Using ElasticThreadPool with {0}min / {1}max", _minThreads, _maxThreads);
                var elasticThreadPool = new ElasticThreadPool(_minThreads, _maxThreads);
                GlobalDispatchQueue       = elasticThreadPool;
                _inplaceActivation        = false;
                _availableThreadsCallback = delegate(out int threads, out int ports) {
                    int dummy2;
                    ThreadPool.GetAvailableThreads(out dummy2, out ports);
                    threads = elasticThreadPool.MaxParallelThreads - elasticThreadPool.ThreadCount;
                };
                break;

            case "legacy":
                ThreadPool.GetMinThreads(out dummy, out _minPorts);
                ThreadPool.GetMaxThreads(out dummy, out _maxPorts);
                ThreadPool.SetMinThreads(_minThreads, _minPorts);
                ThreadPool.SetMaxThreads(_maxThreads, _maxPorts);
                _log.Debug("Using LegacyThreadPool");
                GlobalDispatchQueue       = LegacyThreadPool.Instance;
                _availableThreadsCallback = ThreadPool.GetAvailableThreads;
                break;
            }
        }
        //init
        public Sender(SenderState <TKey> hubState, IEventQueue <TKey> eventQueue,
                      IDispatchQueue <TKey> dispatchQueue, IEnumerable <IRegularJob> regularJobs,
                      IEnumerable <ISignalProviderControl> signalEndpoints)
        {
            _hubState        = hubState;
            _regularJobs     = regularJobs.ToList();
            _eventQueue      = eventQueue;
            _dispatchQueue   = dispatchQueue;
            _signalEndpoints = signalEndpoints.ToList();

            _regularJobTimers = _regularJobs.Select(x => new NonReentrantTimer(x.Tick
                                                                               , NotificationsConstants.REGULAR_JOB_TICK_INTERVAL, intervalFromCallbackStarted: false))
                                .ToList();
            _stopMonitorTimer = new NonReentrantTimer(StopTimers
                                                      , NotificationsConstants.REGULAR_JOB_TICK_INTERVAL, intervalFromCallbackStarted: false);
            _stopEventHandle = new ManualResetEventSlim(false);
        }
        //init
        public DatabaseDispatchProvider(IDispatchQueue <TKey> dispatchQueue, IMonitor <TKey> eventSink, SenderSettings senderSettings,
                                        IDispatchChannelRegistry <TKey> dispatcherRegistry, ISignalDispatchQueries <TKey> dispatchQueries, ILogger logger,
                                        ILockTracker <TKey> lockTracker, IConsolidationLockTracker <TKey> consolidationLockTracker)
        {
            _dispatchQueue            = dispatchQueue;
            _monitor                  = eventSink;
            _dispatcherRegistry       = dispatcherRegistry;
            _dispatchQueries          = dispatchQueries;
            _logger                   = logger;
            _lockTracker              = lockTracker;
            _consolidationLockTracker = consolidationLockTracker;
            _senderSettings           = senderSettings;

            QueryPeriod       = senderSettings.DatabaseSignalProviderQueryPeriod;
            ItemsQueryCount   = senderSettings.DatabaseSignalProviderItemsQueryCount;
            MaxFailedAttempts = senderSettings.DatabaseSignalProviderItemsMaxFailedAttempts;
        }
Beispiel #26
0
        // (yurig): This method has been intentionally split from DispatchLoop()
        // result.Block() inside causes Result<DispatchWorkItem> to never be disposed.
        // By moving it into its own method we ensure its garbage collection as it is
        // popped off the stack. Do NOT inline this method into DispatchLoop().
        private bool GetNextWorkItem(out Action callback)
        {
            if (!_inbox.TryPop(out callback))
            {
                var result = new Result <DispatchWorkItem>(TimeSpan.MaxValue);

                // reset the dispatch queue for this thread
                AsyncUtil.CurrentDispatchQueue = null;
                _queue = null;

                // check if thread is associated with a host already
                if (_host == null)
                {
                    // NOTE (steveb): this is a brand new thread without a host yet

                    // return the thread to the dispatch scheduler
                    DispatchThreadScheduler.ReleaseThread(this, result);
                }
                else
                {
                    // request another work-item
                    _host.RequestWorkItem(this, result);
                }

                // block until a work item is available
                result.Block();

                // check if we received a work item or an exception to shutdown
                if (result.HasException && (result.Exception is DispatchThreadShutdownException))
                {
                    // time to shut down
                    _log.DebugFormat("DispatchThread #{0} destroyed", _id);
                    return(false);
                }
                callback = result.Value.WorkItem;
                _queue   = result.Value.DispatchQueue;

                // TODO (steveb): handle the weird case where _queue is null

                // set the dispatch queue for this thread
                AsyncUtil.CurrentDispatchQueue = _queue;
            }
            return(true);
        }
        private bool TryQueueWorkItem(int priority, Action callback)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("ElasticThreadPool has already been disposed");
            }

            // check if we can enqueue work-item into current dispatch thread
            IDispatchQueue queue = this[priority];

            if (DispatchThread.TryQueueWorkItem(queue, callback))
            {
                return(true);
            }

            // check if there are available threads to which the work-item can be given to
            KeyValuePair <DispatchThread, Result <DispatchWorkItem> > entry;

            if (_reservedThreads.TryPop(out entry))
            {
                lock (_syncRoot) {
                    RegisterThread("new item", entry.Key);
                }

                // found an available thread, let's resume it with the work-item
                entry.Value.Return(new DispatchWorkItem(callback, queue));
                return(true);
            }

            // no threads available, keep work-item for later
            if (!_inbox.TryEnqueue(priority, callback))
            {
                return(false);
            }

            // check if we need to request a thread to kick things off
            if (ThreadCount == 0)
            {
                ((IDispatchHost)this).IncreaseThreadCount("request first thread");
            }
            return(true);
        }
Beispiel #28
0
        private static Result <int> Fibonacci(IDispatchQueue stp, int n, TimeSpan delay, Result <int> result)
        {
            if (!ReferenceEquals(result.Env.DispatchQueue, stp))
            {
                _log.Error(string.Format("ERROR: wrong task env {0}, expected {1}.", result.Env.DispatchQueue, stp));
            }
            stp.QueueWorkItem(delegate {
                Interlocked.Increment(ref _counter);
                switch (n)
                {
                case 0:
                    if (delay > TimeSpan.Zero)
                    {
                        Thread.Sleep(delay);
                    }
                    result.Return(0);
                    break;

                case 1:
                    if (delay > TimeSpan.Zero)
                    {
                        Thread.Sleep(delay);
                    }
                    result.Return(1);
                    break;

                default:
                    Result <int> a = Fibonacci(stp, n - 1, delay, new Result <int>(TimeSpan.MaxValue, TaskEnv.New(stp)));
                    Result <int> b = Fibonacci(stp, n - 2, delay, new Result <int>(TimeSpan.MaxValue, TaskEnv.New(stp)));
                    new AResult[] { a, b }.Join(new Result(TimeSpan.MaxValue, TaskEnv.New(stp))).WhenDone(_ => {
                        if (!ReferenceEquals(AsyncUtil.CurrentDispatchQueue, stp))
                        {
                            _log.Error(string.Format("ERROR: wrong queue {0}, expected {1}.", AsyncUtil.CurrentDispatchQueue, stp));
                        }
                        result.Return(a.Value + b.Value);
                    });
                    break;
                }
            });
            return(result);
        }
Beispiel #29
0
        /// <summary>
        /// Enqueue a callback as a work item to be invoked with the current <see cref="TaskEnv"/>.
        /// </summary>
        /// <typeparam name="T">Result value type of callback.</typeparam>
        /// <param name="dispatchQueue">DispatchQueue to enqueue work into.</param>
        /// <param name="callback">Work item callback.</param>
        /// <param name="result">Synchronization handle for work item.</param>
        /// <returns>The synchronization handle provided to the method.</returns>
        public static Result <T> QueueWorkItemWithCurrentEnv <T>(this IDispatchQueue dispatchQueue, Func <T> callback, Result <T> result)
        {
            var current = TaskEnv.CurrentOrNull;

            if (current != null)
            {
                return(dispatchQueue.QueueWorkItemWithEnv(callback, current, result));
            }
            if (result != null)
            {
                dispatchQueue.QueueWorkItem(delegate() {
                    try {
                        result.Return(callback());
                    } catch (Exception e) {
                        result.Throw(e);
                    }
                });
                return(result);
            }
            dispatchQueue.QueueWorkItem(() => callback());
            return(null);
        }
Beispiel #30
0
        /// <summary>
        /// Enqueue a callback as a work item to be invoked with the current <see cref="TaskEnv"/>.
        /// </summary>
        /// <param name="dispatchQueue">DispatchQueue to enqueue work into.</param>
        /// <param name="callback">Work item callback.</param>
        /// <param name="result">Synchronization handle for work item.</param>
        /// <returns>The synchronization handle provided to the method.</returns>
        public static Result QueueWorkItemWithCurrentEnv(this IDispatchQueue dispatchQueue, Action callback, Result result)
        {
            var current = TaskEnv.CurrentOrNull;

            if (current != null)
            {
                return(dispatchQueue.QueueWorkItemWithEnv(callback, current, result));
            }
            if (result != null)
            {
                dispatchQueue.QueueWorkItem(() => {
                    try {
                        callback();
                        result.Return();
                    } catch (Exception e) {
                        result.Throw(e);
                    }
                });
                return(result);
            }
            dispatchQueue.QueueWorkItem(callback);
            return(null);
        }
Beispiel #31
0
 //--- Constructors ---
 /// <summary>
 /// Create new work-item instance.
 /// </summary>
 /// <param name="workitem">Work-item callback.</param>
 /// <param name="queue">Dispatch queue associated with work-item.</param>
 public DispatchWorkItem(Action workitem, IDispatchQueue queue)
 {
     this.WorkItem = workitem;
     this.DispatchQueue = queue;
 }
Beispiel #32
0
        private static void FibonacciThreadPool(IDispatchQueue stp, int n, TimeSpan delay, out int value, out TimeSpan elapsed)
        {
            _log.Debug("FibonacciThreadPool");

            var sw = Stopwatch.StartNew();
            value = Fibonacci(stp, n, delay, new Result<int>(TimeSpan.MaxValue, TaskEnv.New(stp))).Wait();
            sw.Stop();
            elapsed = sw.Elapsed;
        }
Beispiel #33
0
 private static Result<int> Fibonacci(IDispatchQueue stp, int n, TimeSpan delay, Result<int> result)
 {
     if(!ReferenceEquals(result.Env.DispatchQueue, stp)) {
         _log.Error(string.Format("ERROR: wrong task env {0}, expected {1}.", result.Env.DispatchQueue, stp));
     }
     stp.QueueWorkItem(delegate {
         Interlocked.Increment(ref _counter);
         switch(n) {
         case 0:
             if(delay > TimeSpan.Zero) {
                 Thread.Sleep(delay);
             }
             result.Return(0);
             break;
         case 1:
             if(delay > TimeSpan.Zero) {
                 Thread.Sleep(delay);
             }
             result.Return(1);
             break;
         default:
             Result<int> a = Fibonacci(stp, n - 1, delay, new Result<int>(TimeSpan.MaxValue, TaskEnv.New(stp)));
             Result<int> b = Fibonacci(stp, n - 2, delay, new Result<int>(TimeSpan.MaxValue, TaskEnv.New(stp)));
             new AResult[] { a, b }.Join(new Result(TimeSpan.MaxValue, TaskEnv.New(stp))).WhenDone(_ => {
                 if(!ReferenceEquals(Async.CurrentDispatchQueue, stp)) {
                     _log.Error(string.Format("ERROR: wrong queue {0}, expected {1}.", Async.CurrentDispatchQueue, stp));
                 }
                 result.Return(a.Value + b.Value);
             });
             break;
         }
     });
     return result;
 }
Beispiel #34
0
        public void PinTo(IDispatchQueue dispatchQueue)
        {
            // TODO 2.0 (steveb): remove implementation

            if(_dispatchQueue != null) {
                throw new InvalidOperationException("RendezVousEvent is already pinned to an IDispatchQueue");
            }
            _dispatchQueue = dispatchQueue;
        }
Beispiel #35
0
        // (yurig): This method has been intentionally split from DispatchLoop()
        // result.Block() inside causes Result<DispatchWorkItem> to never be disposed.
        // By moving it into its own method we ensure its garbage collection as it is
        // popped off the stack. Do NOT inline this method into DispatchLoop().
        private bool GetNextWorkItem(out Action callback)
        {
            if(!_inbox.TryPop(out callback)) {
                var result = new Result<DispatchWorkItem>(TimeSpan.MaxValue);

                // reset the dispatch queue for this thread
                AsyncUtil.CurrentDispatchQueue = null;
                _queue = null;

                // check if thread is associated with a host already
                if(_host == null) {

                    // NOTE (steveb): this is a brand new thread without a host yet

                    // return the thread to the dispatch scheduler
                    DispatchThreadScheduler.ReleaseThread(this, result);
                } else {

                    // request another work-item
                    _host.RequestWorkItem(this, result);
                }

                // block until a work item is available
                result.Block();

                // check if we received a work item or an exception to shutdown
                if(result.HasException && (result.Exception is DispatchThreadShutdownException)) {

                    // time to shut down
                    _log.DebugFormat("DispatchThread #{0} destroyed", _id);
                    return false;
                }
                callback = result.Value.WorkItem;
                _queue = result.Value.DispatchQueue;

                // TODO (steveb): handle the weird case where _queue is null

                // set the dispatch queue for this thread
                AsyncUtil.CurrentDispatchQueue = _queue;
            }
            return true;
        }
Beispiel #36
0
        private void DispatchLoop()
        {
            // set thread-local self-reference
            CurrentThread = this;

            // begin thread loop
            try {
                while(true) {

                    // check if queue has a work-item
                    Action callback;
                    if(!_inbox.TryPop(out callback)) {
                        var result = new Result<DispatchWorkItem>(TimeSpan.MaxValue);

                        // reset the dispatch queue for this thread
                        Async.CurrentDispatchQueue = null;

                        // check if thread is associated with a host already
                        if(_host == null) {

                            // NOTE (steveb): this is a brand new thread without a host yet

                            // return the thread to the dispatch scheduler
                            DispatchThreadScheduler.ReleaseThread(this, result);
                        } else {

                            // request another work-item
                            _host.RequestWorkItem(this, result);
                        }

                        // block until a work item is available
                        result.Block();

                        // check if we received a work item or an exception to shutdown
                        if(result.HasException && (result.Exception is DispatchThreadShutdownException)) {

                            // time to shut down
                            _log.DebugFormat("DispatchThread #{0} destroyed", _id);
                            return;
                        }
                        callback = result.Value.WorkItem;
                        _queue = result.Value.DispatchQueue;

                        // TODO (steveb): handle the weird case where _queue is null

                        // set the dispatch queue for this thread
                        Async.CurrentDispatchQueue = _queue;
                    }

                    // execute work-item
                    if(callback != null) {
                        try {
                            callback();
                        } catch(Exception e) {
                            _log.Warn("an unhandled exception occurred while executing the work-item", e);
                        }
                    }
                }
            } catch(Exception e) {

                // something went wrong that shouldn't have!
                _log.ErrorExceptionMethodCall(e, string.Format("DispatchLoop #{0}: FATAL ERROR", _id));

                // TODO (steveb): tell _host about untimely exit; post items in queue to host inbox (o/w we lose them)

            } finally {
                CurrentThread = null;
            }
        }
Beispiel #37
0
        //--- Class Methods ---
        public static bool TryQueueWorkItem(IDispatchQueue queue, Action callback)
        {
            DispatchThread current = CurrentThread;
            if((current != null) && ReferenceEquals(Async.CurrentDispatchQueue, queue)) {

                // NOTE (steveb): next call can never fail since we're calling the queue work-item method of the current thread
                current.QueueWorkItem(callback);
                return true;
            }
            return false;
        }