コード例 #1
0
ファイル: PausableTask.cs プロジェクト: Hengle/otiose
        /// <summary>
        /// A Pausable Task cannot be recycled from the pool if hasn't been
        /// previously completed.
        /// A task can actually be restarted, but this will stop the previous
        /// enumeration, even if the enumerator didn't change.
        /// However since an enumerator can be enumerated on another runner
        /// a task cannot set as completed immediatly, but it must wait for
        /// the next MoveNext. This is what the Pending logic is about.
        /// </summary>
        /// <param name="task"></param>
        void InternalStart()
        {
            DBC.Check.Require(_pendingRestart == false, "a task has been reused while is pending to start");
            DBC.Check.Require(_taskGenerator != null || _taskEnumerator != null, "An enumerator or enumerator provider is required to enable this function, please use SetEnumeratorProvider/SetEnumerator before to call start");

            Resume(); //if it's paused, must resume

            var originalEnumerator = _taskEnumerator ?? _taskGenerator();

            //TaskRoutine case only!!
            ThreadUtility.MemoryBarrier();
            if (_pool == null &&
                _completed == false &&
                _started == true &&
                _explicitlyStopped == true)
            {
                _pendingEnumerator          = originalEnumerator;
                _pendingContinuationWrapper = _continuationWrapper;
                _pendingRestart             = true;

                _continuationWrapper = new ContinuationWrapper();

                ThreadUtility.MemoryBarrier();

                return;
            }

            Restart(originalEnumerator);
        }
コード例 #2
0
        public void OnCompleted(Action continuation)
        {
            var wrapper = new ContinuationWrapper(continuation);

            if (_cancellationToken.IsCancellationRequested)
            {
                ThreadPool.QueueUserWorkItem(ThreadPoolCallback, wrapper);
                return;
            }

            _mainThread.Post(wrapper.Invoke);
            var registration = _cancellationToken.Register(CancellationTokenCallback, wrapper, false);

            var disposeRegistration = false;

            lock (wrapper) {
                // wrapper.Action == null means that ContinuationWrapper.Invoke has been called before CancellationTokenRegistration was set
                // In this case, registration should be disposed explicitly
                if (wrapper.Action == null)
                {
                    disposeRegistration = true;
                }
                else
                {
                    wrapper.CancellationTokenRegistration = registration;
                }
            }

            if (disposeRegistration)
            {
                registration.Dispose();
            }
        }
コード例 #3
0
ファイル: PausableTask.cs プロジェクト: Hengle/otiose
        internal PausableTask()
        {
            _coroutineWrapper    = new SerialTaskCollection(1);
            _continuationWrapper = new ContinuationWrapper();

            Reset();
        }
コード例 #4
0
        /// <summary>
        /// A PausableTask cannot be recycled from the pool if hasn't been previously completed.
        /// A task can actually be restarted, but this will stop the previous enumeration, even if the enumerator didn't
        /// change.
        /// However since an enumerator can be enumerated on another runner a task cannot set as completed immediately,
        /// but it must wait for the next MoveNext. This is what the Pending logic is about.
        /// </summary>
        /// <param name="task"></param>
        void InternalStart()
        {
            DBC.Tasks.Check.Require(_pendingRestart == false, "a task has been reused while is pending to start");
            DBC.Tasks.Check.Require(_taskGenerator != null || _taskEnumerator != null,
                                    "An enumerator or enumerator provider is required to enable this function, please use SetEnumeratorProvider/SetEnumerator before to call start");

            Resume(); //if it's paused, must resume

            var originalEnumerator = _taskEnumerator ?? _taskGenerator();

            //TaskRoutine case only!!
            bool isTaskRoutineIsAlreadyIn = _pool == null &&
                                            _completed == false &&
                                            _started == true;

            if (isTaskRoutineIsAlreadyIn == true &&
                _explicitlyStopped == true)
            {
                //Stop() Start() cauess this (previous continuation wrapper will stop before to start the new one)
                //Start() Start() will not make the _continuationWrapper stop until the task is really completed
                _pendingEnumerator          = originalEnumerator;
                _pendingContinuationWrapper = _continuationWrapper;
                _pendingRestart             = true;

                _continuationWrapper = new ContinuationWrapper();

                return;
            }

            Restart(originalEnumerator, isTaskRoutineIsAlreadyIn);
        }
コード例 #5
0
        public ContinuationWrapper Start(Action <SveltoTaskException> onFail = null, Action onStop = null)
        {
            DBC.Tasks.Check.Require(_taskGenerator != null || _taskEnumerator != null,
                                    "An enumerator or enumerator provider is required to enable this function, please use SetEnumeratorProvider/SetEnumerator before to call start");

            _onStop = onStop;
            _onFail = onFail;

            _sveltoTask._threadSafeStates.paused = true;
            _sveltoTask.OnTaskInterrupted();

            var continuationWrapper = _continuationWrapper;

            var newTask = _taskGenerator != null?_taskGenerator() : _taskEnumerator;

            if (_sveltoTask._threadSafeStates.isRunning == true &&
                _sveltoTask._threadSafeStates.explicitlyStopped == true)
            {
                //Stop() Start() causes this (previous continuation wrapper will stop before to start the new one)
                //Start() Start() is perceived as a continuation of the previous task therefore it won't
                //cause the continuation wrapper to stop
                _pendingTask = newTask;
                _previousContinuationWrapper = _continuationWrapper;

                continuationWrapper = _continuationWrapper = new ContinuationWrapper();

                Resume(); //if it's paused, must resume
            }
            else
            {
                DBC.Tasks.Check.Require(_runner != null, "SetScheduler function has never been called");

                if (_taskGenerator == null && _sveltoTask._threadSafeStates.taskEnumeratorJustSet == false)
                {
#if DEBUG && !PROFILER
                    DBC.Tasks.Check.Assert(newTask.GetType().IsCompilerGenerated() == false, "Cannot restart a compiler generated iterator block, use SetEnumeratorProvider instead ".FastConcat(_sveltoTask._name));
#endif
                    newTask.Reset();
                }

                _sveltoTask.SetTask(newTask);
                _continuationWrapper.Reset();
                _sveltoTask.ClearInvokes();

                if (_sveltoTask._threadSafeStates.isRunning == false)
                {
                    _sveltoTask._threadSafeStates = new SveltoTask <T> .State();

                    _sveltoTask._threadSafeStates.started = true;
                    _runner.StartCoroutine(this);
                }
                else
                {
                    _sveltoTask._threadSafeStates.paused = false;
                }
            }

            return(continuationWrapper);
        }
コード例 #6
0
        /// <summary>
        /// Reset task on reuse, when fetched from the Pool
        /// </summary>
        public void Reset()
        {
            CleanUpOnRecycle();

            _continuationWrapper = new ContinuationWrapper();

            _paused = false;
            _taskEnumeratorJustSet = false;
            _completed             = false;
            _started           = false;
            _explicitlyStopped = false;
#if DEBUG && !PROFILER
            _compilerGenerated = false;
#endif
            _pendingRestart = false;
            _name           = string.Empty;
        }
コード例 #7
0
ファイル: PausableTask.cs プロジェクト: Hengle/Svelto.Tasks
        /// <summary>
        /// Reset task on reuse, when fetched from the Pool
        /// </summary>
        public void Reset()
        {
            CleanUpOnRecycle();

            //_enumeratorWrap.Reset cannot be inside
            //CleanUp because it could be iterated way
            //after the task is completed.
            _continuationWrapper = new ContinuationWrapper();

            _paused = false;
            _taskEnumeratorJustSet = false;
            _completed             = false;
            _started           = false;
            _explicitlyStopped = false;
            _compilerGenerated = false;
            _pendingRestart    = false;
            _name = string.Empty;
        }
コード例 #8
0
 internal static void Push(ContinuationWrapper task)
 {
     _pool.Enqueue(task);
 }
コード例 #9
0
 public TaskRoutine(IRunner <T> runner)
 {
     _sveltoTask          = new SveltoTask <T>();
     _runner              = runner;
     _continuationWrapper = new ContinuationWrapper();
 }
コード例 #10
0
 internal static void Push(ContinuationWrapper task)
 {
     GC.SuppressFinalize(task); //will be register again once pulled from the pool
     _pool.Enqueue(task);
 }