Example #1
0
        public void New_TaskEnv_does_not_carry_state()
        {
            var state = new State();

            TaskEnv.Current.SetState("foo", state);
            Assert.IsNull(TaskEnv.New().GetState <State>("foo"));
        }
 private void CheckTimer(DateTime when)
 {
     if (_expireTimer.Status == TaskTimerStatus.Done || _expireTimer.When > when)
     {
         _expireTimer.Change(when, TaskEnv.New());
     }
 }
Example #3
0
        /// <summary>
        /// Asynchronous copying of one stream to another.
        /// </summary>
        /// <param name="source">Source <see cref="Stream"/>.</param>
        /// <param name="target">Target <see cref="Stream"/>.</param>
        /// <param name="length">Number of bytes to copy from source to target.</param>
        /// <param name="result">The <see cref="Result"/> instance to be returned by the call.</param>
        /// <returns>Synchronization handle for the number of bytes copied.</returns>
        public static Result <long> CopyToStream(this Stream source, Stream target, long length, Result <long> result)
        {
            if (!SysUtil.UseAsyncIO)
            {
                return(AsyncUtil.Fork(() => CopyToStream(source, target, length), result));
            }

            // NOTE (steveb): intermediary copy steps already have a timeout operation, no need to limit the duration of the entire copy operation

            if ((source == Stream.Null) || (length == 0))
            {
                result.Return(0);
            }
            else if (source.IsStreamMemorized() && target.IsStreamMemorized())
            {
                // source & target are memory streams; let's do the copy inline as fast as we can
                result.Return(CopyToStream(source, target, length));
            }
            else
            {
                // use new task environment so we don't copy the task state over and over again
                TaskEnv.ExecuteNew(() => Coroutine.Invoke(CopyTo_Helper, source, target, length, result));
            }
            return(result);
        }
Example #4
0
        public void Copied_TaskEnv_has_current_state()
        {
            var state = new State();

            TaskEnv.Current.SetState("foo", state);
            Assert.AreEqual(state, TaskEnv.Clone()["foo"]);
        }
Example #5
0
        private Result <IssueData[]> ProcessIssueBatch(ElasticThreadPool pool, string projectId, string filterId, int pageNumber, int issuesInBatch, Tuplet <bool> canceled, Result <IssueData[]> result)
        {
            pool.QueueWorkItem(HandlerUtil.WithEnv(delegate {
                // TODO (steveb): use result.IsCanceled instead of shared tuple once cancellation is supported on the result object

                // check if request has been canceled
                if (!canceled.Item1)
                {
                    IssueData[] issuesForBatch;
                    if (!string.IsNullOrEmpty(filterId))
                    {
                        issuesForBatch = _service.mc_filter_get_issues(_username, _password, projectId, filterId, pageNumber.ToString(), issuesInBatch.ToString());
                    }
                    else
                    {
                        issuesForBatch = _service.mc_project_get_issues(_username, _password, projectId, pageNumber.ToString(), issuesInBatch.ToString());
                    }
                    result.Return(issuesForBatch);
                }
                else
                {
                    // TODO (steveb): throw a more specific exception
                    result.Throw(new Exception("unspecified error"));
                }
            }, TaskEnv.Clone()));
            return(result);
        }
Example #6
0
        /// <summary>
        /// Asychronously Pad a stream with a sequence of bytes
        /// </summary>
        /// <param name="stream">Target <see cref="Stream"/></param>
        /// <param name="count">Number of bytes to pad</param>
        /// <param name="value">Byte value to use for padding</param>
        /// <param name="result">The <see cref="Result"/> instance to be returned by the call.</param>
        /// <returns>Synchronization handle for completion of padding action.</returns>
        public static Result Pad(this Stream stream, long count, byte value, Result result)
        {
            if (count < 0)
            {
                throw new ArgumentException("count must be non-negative");
            }

            // NOTE (steveb): intermediary copy steps already have a timeout operation, no need to limit the duration of the entire copy operation

            if (count == 0)
            {
                result.Return();
            }
            else
            {
                // initialize buffer so we can write in large chunks if need be
                byte[] bytes = new byte[(int)Math.Min(4096L, count)];
                for (int i = 0; i < bytes.Length; ++i)
                {
                    bytes[i] = value;
                }

                // use new task environment so we don't copy the task state over and over again
                TaskEnv.ExecuteNew(() => Coroutine.Invoke(Pad_Helper, stream, count, bytes, result));
            }
            return(result);
        }
Example #7
0
		public void AttachToCurrentTaskEnv()
		{
			theLogger.Debug("Attaching Context to current TaskEnv");
			lock (this)
			{
				DreamContext dreamCtx = DreamContext.CurrentOrNull;
				if (dreamCtx != null)
				{
					dreamCtx.SetState<Context>(this);
				}
				else
				{
					var env = TaskEnv.Current;
					if (env.GetState<Context>() != null)
					{
						throw new DreamContextAccessException("tried to attach context to env that already has a dreamcontext");
					}
					if (theOwnerEnv != null && theOwnerEnv == env)
					{
						throw new DreamContextAccessException("tried to re-attach dreamcontext to env it is already attached to");
					}
					if (theOwnerEnv != null)
					{
						throw new DreamContextAccessException("tried to attach dreamcontext to an env, when it already is attached to another");
					}
					theOwnerEnv = env;
					env.SetState(this);
				}
			}
		}
Example #8
0
        /// <summary>
        /// Invoke an action in the context of a service feature.
        /// </summary>
        /// <remarks>
        /// Assumes that there exists a current <see cref="DreamContext"/> that belongs to a request to another feature of this service.
        /// </remarks>
        /// <param name="verb">Http verb.</param>
        /// <param name="path">Feature path.</param>
        /// <param name="handler">Action to perform in this context.</param>
        /// <returns>Exception thrown by handler or null.</returns>
        public Exception InvokeInServiceContext(string verb, string path, Action handler)
        {
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            if (string.IsNullOrEmpty(verb))
            {
                throw new ArgumentNullException("verb");
            }
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            // create new new environment for execution
            XUri         uri     = Self.AtPath(path);
            DreamContext current = DreamContext.Current;
            Exception    e       = TaskEnv.ExecuteNew(delegate {
                DreamFeatureStage[] stages = new[] {
                    new DreamFeatureStage("InServiceInvokeHandler", InServiceInvokeHandler, DreamAccess.Private)
                };

                // BUGBUGBUG (steveb): when invoking a remote function this way, we're are not running the proloques and epilogues, which leads to errors;
                //  also dream-access attributes are being ignored (i.e. 'public' vs. 'private')
                DreamMessage message = DreamUtil.AppendHeadersToInternallyForwardedMessage(current.Request, DreamMessage.Ok());
                var context          = current.CreateContext(verb, uri, new DreamFeature(this, Self, 0, stages, verb, path), message);
                context.AttachToCurrentTaskEnv();

                // pass along host and public-uri information
                handler();
            }, TimerFactory);

            return(e);
        }
Example #9
0
        private void InsertRecord(DirectoryRecord record)
        {
            // add value to directory
            lock (_directory) {
                _directory[record.Name] = record;
            }

            // check if value has an expiration time
            if (record.HasExpiration)
            {
                TimerFactory.New(record.Expiration, OnExpire, record.Name, TaskEnv.New());
            }

            SaveToFileSystem(record.Name, record.Value);

            // notify event channel
            XDoc notify = new XDoc("insert").Attr("name", record.Name);

            if (record.HasExpiration)
            {
                notify.Attr("expire", record.Expiration);
            }
            notify.Add(record.Value);
            _events.Post(notify, new Result <DreamMessage>(TimeSpan.MaxValue));
        }
        private static string CachedWebGet(XUri uri, double?ttl, bool?nilIfMissing)
        {
            // fetch message from cache or from the web
            string result;

            lock (_webTextCache) {
                if (_webTextCache.TryGetValue(uri, out result))
                {
                    return(result);
                }
            }

            // do the web request
            Result <DreamMessage> response = new Result <DreamMessage>();

            Plug.New(uri).WithTimeout(DEFAULT_WEB_TIMEOUT).InvokeEx("GET", DreamMessage.Ok(), response);
            DreamMessage message = response.Wait();

            try {
                // check message status
                if (!message.IsSuccessful)
                {
                    if (nilIfMissing.GetValueOrDefault())
                    {
                        return(null);
                    }
                    return(message.Status == DreamStatus.UnableToConnect
                        ? string.Format("(unable to fetch text document from uri [status: {0} ({1}), message: \"{2}\"])", (int)message.Status, message.Status, message.ToDocument()["message"].AsText)
                        : string.Format("(unable to fetch text document from uri [status: {0} ({1})])", (int)message.Status, message.Status));
                }

                // check message size
                Result resMemorize = message.Memorize(InsertTextLimit, new Result()).Block();
                if (resMemorize.HasException)
                {
                    return(nilIfMissing.GetValueOrDefault() ? null : "(text document is too large)");
                }

                // detect encoding and decode response
                var stream   = message.AsStream();
                var encoding = stream.DetectEncoding() ?? message.ContentType.CharSet;
                result = encoding.GetString(stream.ReadBytes(-1));
            } finally {
                message.Close();
            }

            // start timer to clean-up cached result
            lock (_webTextCache) {
                _webTextCache[uri] = result;
            }
            double timeout = Math.Min(60 * 60 * 24, Math.Max(ttl ?? MinCacheTtl, 60));

            TaskEnv.ExecuteNew(() => TaskTimer.New(TimeSpan.FromSeconds(timeout), timer => {
                lock (_webTextCache) {
                    _webTextCache.Remove((XUri)timer.State);
                }
            }, uri, TaskEnv.None));
            return(result);
        }
Example #11
0
        public void TaskEnv_invoke_with_custom_dispatchqueue_sets_task_state()
        {
            var dispatchQueue = new TestDispatchQueue();

            _log.Debug("setting up envs");
            var   currentState = new State();
            State newState     = null;

            TaskEnv.Current.SetState(currentState);
            var  copiedEnv  = TaskEnv.Clone(dispatchQueue);
            var  newEnv     = TaskEnv.New(dispatchQueue);
            var  resetEvent = new AutoResetEvent(false);
            bool?hasState   = null;

            // Note: have to over acquire otherwise env is wiped after invokenow
            copiedEnv.Acquire();
            copiedEnv.Acquire();
            copiedEnv.Invoke(() => {
                _log.Debug("copied env invoke");
                hasState = currentState == TaskEnv.Current.GetState <State>();
                resetEvent.Set();
            });
            resetEvent.WaitOne();
            dispatchQueue.LastItem.Wait();
            Assert.IsTrue(hasState.HasValue);
            Assert.IsTrue(hasState.Value);
            hasState = null;

            // Note: have to over acquire otherwise env is wiped after invokenow
            newEnv.Acquire();
            newEnv.Acquire();
            newEnv.Acquire();
            newEnv.Invoke(() => {
                _log.Debug("new env invoke");
                hasState = currentState == TaskEnv.Current.GetState <State>();
                newState = new State();
                TaskEnv.Current.SetState(newState);
                resetEvent.Set();
            });
            resetEvent.WaitOne();
            dispatchQueue.LastItem.Wait();
            Assert.IsTrue(hasState.HasValue);
            Assert.IsFalse(hasState.Value);
            Assert.IsNotNull(newState);
            Assert.AreEqual(currentState, TaskEnv.Current.GetState <State>());
            Assert.AreNotEqual(currentState, newState);
            hasState = null;
            newEnv.Invoke(() => {
                _log.Debug("new env invoke 2");
                hasState = newState == TaskEnv.Current.GetState <State>();
                newEnv   = TaskEnv.Current;
                resetEvent.Set();
            });
            resetEvent.WaitOne();
            dispatchQueue.LastItem.Wait();
            Assert.IsTrue(hasState.HasValue);
            Assert.IsTrue(hasState.Value);
        }
Example #12
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;
        }
Example #13
0
        //--- Methods ---

        /// <summary>
        /// Change when the timer will execute.
        /// </summary>
        /// <param name="timespan">The relative time.</param>
        /// <param name="env">The environment to use for invocation.</param>
        public void Change(TimeSpan timespan, TaskEnv env)
        {
            if (timespan != TimeSpan.MaxValue)
            {
                Change(DateTime.UtcNow.Add(timespan), env);
            }
            else
            {
                Change(DateTime.MaxValue, env);
            }
        }
Example #14
0
 /// <summary>
 /// Detach the context from the its task environment.
 /// </summary>
 /// <remarks>
 /// Must be done in the context's task environment.
 /// </remarks>
 public void DetachFromTaskEnv()
 {
     lock (this) {
         if (TaskEnv.CurrentOrNull != _ownerEnv)
         {
             _log.Warn("detaching context in env other than owning end");
         }
         _ownerEnv.RemoveState(this);
         _ownerEnv = null;
     }
 }
Example #15
0
        public void TaskEnv_invoke_sets_task_state()
        {
            _log.Debug("setting up envs");
            var   currentState = new State();
            State newState     = null;

            TaskEnv.Current.SetState(currentState);
            var  currentEnv = TaskEnv.Current;
            var  newEnv     = TaskEnv.New();
            var  resetEvent = new AutoResetEvent(false);
            bool?hasState   = null;

            // Note: have to over acquire otherwise env is wiped after invokenow
            currentEnv.Acquire();
            currentEnv.Acquire();
            currentEnv.Invoke(() => {
                _log.Debug("current env invoke");
                hasState = currentState == TaskEnv.Current.GetState <State>();
                resetEvent.Set();
            });
            resetEvent.WaitOne();
            Assert.IsTrue(hasState.HasValue);
            Assert.IsTrue(hasState.Value);
            hasState = null;

            // Note: have to over acquire otherwise env is wiped after invokenow
            newEnv.Acquire();
            newEnv.Acquire();
            newEnv.Acquire();
            newEnv.Invoke(() => {
                _log.Debug("new env invoke");
                hasState = currentState == TaskEnv.Current.GetState <State>();
                newState = new State();
                TaskEnv.Current.SetState(newState);
                resetEvent.Set();
            });
            resetEvent.WaitOne();
            Assert.IsTrue(hasState.HasValue);
            Assert.IsFalse(hasState.Value);
            Assert.IsNotNull(newState);
            Assert.AreEqual(currentState, TaskEnv.Current.GetState <State>());
            Assert.AreNotEqual(currentState, newState);
            hasState = null;
            newEnv.Invoke(() => {
                _log.Debug("new env invoke 2");
                hasState = newState == TaskEnv.Current.GetState <State>();
                newEnv   = TaskEnv.Current;
                resetEvent.Set();
            });
            resetEvent.WaitOne();
            Assert.IsTrue(hasState.HasValue);
            Assert.IsTrue(hasState.Value);
        }
Example #16
0
        public void ITaskCloneable_is_cloned_on_task_copy()
        {
            var state = new TaskLifeSpanState("baz");

            TaskEnv.Current.SetState("foo", state);
            bool?hasState    = null;
            bool stateExists = false;
            var  env         = TaskEnv.Clone();

            env.Acquire();
            env.InvokeNow(() => {
                stateExists = TaskEnv.Current.ContainsKey("foo");
                hasState    = state == TaskEnv.Current.GetState <TaskLifeSpanState>("foo");
            });
            Assert.IsTrue(hasState.HasValue);
            Assert.IsFalse(hasState.Value);
        }
        private void OnExpire(TaskTimer timer)
        {
            var          now         = DateTime.UtcNow;
            List <Entry> expirations = null;

            lock (_expirationLookup) {
                // Note (arnec): Sort is cheap here since we're generally dealing with an already sorted or mostly sorted set at this point
                _orderedExpirations.Sort((a, b) => a.When.CompareTo(b.When));
                while (_orderedExpirations.Count > 0)
                {
                    var entry = _orderedExpirations[0];
                    if (entry.Removed)
                    {
                        // this item was already removed from the set, and no longer requires expiration, but does need removal from ordered set
                        _orderedExpirations.RemoveAt(0);
                        continue;
                    }
                    if (entry.When > now)
                    {
                        _expireTimer.Change(entry.When, TaskEnv.New());
                        break;
                    }
                    entry.Removed = true;
                    _expirationLookup.Remove(entry.Key);
                    _orderedExpirations.RemoveAt(0);
                    _log.DebugFormat("expired item with key '{0}'", entry.Key);
                    if (EntriesExpired == null)
                    {
                        continue;
                    }
                    if (expirations == null)
                    {
                        expirations = new List <Entry>();
                    }
                    expirations.Add(entry);
                }
            }
            if (expirations == null)
            {
                return;
            }
            OnEntriesExpired(expirations);
            OnCollectionChange();
        }
Example #18
0
        public void TaskEnv_invokenow_sets_task_state()
        {
            var   currentState = new State();
            State newState     = null;

            TaskEnv.Current.SetState(currentState);
            var  currentEnv = TaskEnv.Current;
            var  newEnv     = TaskEnv.New();
            bool?hasState   = null;

            // Note: have to over acquire otherwise env is wiped after invokenow
            currentEnv.Acquire();
            currentEnv.Acquire();
            currentEnv.InvokeNow(() => {
                hasState = currentState == TaskEnv.Current.GetState <State>();
            });
            Assert.IsTrue(hasState.HasValue);
            Assert.IsTrue(hasState.Value);
            hasState = null;

            // Note: have to over acquire otherwise env is wiped after invokenow
            newEnv.Acquire();
            newEnv.Acquire();
            newEnv.Acquire();
            newEnv.InvokeNow(() => {
                hasState = currentState == TaskEnv.Current.GetState <State>();
                newState = new State();
                TaskEnv.Current.SetState(newState);
            });
            Assert.IsTrue(hasState.HasValue);
            Assert.IsFalse(hasState.Value);
            Assert.IsNotNull(newState);
            Assert.AreEqual(currentState, TaskEnv.Current.GetState <State>());
            Assert.AreNotEqual(currentState, newState);
            hasState = null;
            newEnv.InvokeNow(() => {
                hasState = newState == TaskEnv.Current.GetState <State>();
                newEnv   = TaskEnv.Current;
            });
            Assert.IsTrue(hasState.HasValue);
            Assert.IsTrue(hasState.Value);
        }
Example #19
0
        /// <summary>
        /// Asynchrounously copy a <see cref="Stream"/> to several targets
        /// </summary>
        /// <param name="source">Source <see cref="Stream"/></param>
        /// <param name="targets">Array of target <see cref="Stream"/> objects</param>
        /// <param name="length">Number of bytes to copy from source to targets</param>
        /// <param name="result">The <see cref="Result"/> instance to be returned by the call.</param>
        /// <returns>Synchronization handle for the number of bytes copied to each target.</returns>
        public static Result <long?[]> CopyTo(this Stream source, Stream[] targets, long length, Result <long?[]> result)
        {
            // NOTE (steveb): intermediary copy steps already have a timeout operation, no need to limit the duration of the entire copy operation

            if ((source == Stream.Null) || (length == 0))
            {
                long?[] totals = new long?[targets.Length];
                for (int i = 0; i < totals.Length; ++i)
                {
                    totals[i] = 0;
                }
                result.Return(totals);
            }
            else
            {
                // use new task environment so we don't copy the task state over and over again
                TaskEnv.ExecuteNew(() => Coroutine.Invoke(CopyTo_Helper, source, targets, length, result));
            }
            return(result);
        }
Example #20
0
        //--- Methods ---

        /// <summary>
        /// Attach the context to the current context.
        /// </summary>
        /// <remarks>
        /// Throws <see cref="DreamContextAccessException"/> if the context is already attached to
        /// a task environemnt of the task environment already has a context.
        /// </remarks>
        /// <exception cref="DreamContextAccessException">Context is either attached to a <see cref="TaskEnv"/> or the current <see cref="TaskEnv"/>
        /// already has a context attached.</exception>
        public void AttachToCurrentTaskEnv()
        {
            lock (this) {
                var env = TaskEnv.Current;
                if (env.GetState <DreamContext>() != null)
                {
                    throw new DreamContextAccessException("tried to attach dreamcontext to env that already has a dreamcontext");
                }
                if (_ownerEnv != null && _ownerEnv == env)
                {
                    throw new DreamContextAccessException("tried to re-attach dreamcontext to env it is already attached to");
                }
                if (_ownerEnv != null)
                {
                    throw new DreamContextAccessException("tried to attach dreamcontext to an env, when it already is attached to another");
                }
                _ownerEnv = env;
                env.SetState(this);
            }
        }
Example #21
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);
        }
Example #22
0
        private void OnExpire(TaskTimer timer)
        {
            string name = (string)timer.State;

            lock (_directory) {
                // check if the record still exists
                DirectoryRecord record;
                if (_directory.TryGetValue(name, out record))
                {
                    // verify if the record should still be deleted
                    if (record.Expiration <= timer.When)
                    {
                        _directory.Remove(record.Name);
                    }
                    else
                    {
                        timer.Change(record.Expiration, TaskEnv.Clone());
                    }
                }
            }
        }
Example #23
0
        public void ElasticThreadPool_Multi_Staged_Fibonacci_Min_1_Max_30()
        {
            const int test = 4;

            // initialize data structures
            ElasticThreadPool[] stp     = new ElasticThreadPool[test];
            Result <int>[]      results = new Result <int> [test];
            for (int i = 0; i < test; ++i)
            {
                stp[i]     = new ElasticThreadPool(1, 30);
                results[i] = new Result <int>(TimeSpan.MaxValue, TaskEnv.New(stp[i]));
            }

            // start test
            var sw = Stopwatch.StartNew();

            for (int i = 0; i < results.Length; ++i)
            {
                _log.DebugFormat("--- FIBONACCI KICK-OFF: {0}", i);
                Fibonacci(stp[i], 30, TimeSpan.Zero, results[i]);
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            results.Join(new Result(TimeSpan.MaxValue)).Wait();
            sw.Stop();
            TimeSpan elapsed = sw.Elapsed;

            // check results
            for (int i = 0; i < test; ++i)
            {
                Assert.AreEqual(832040, results[i].Value, "result {0} did not match", i);
            }
            _log.Debug("Time: " + elapsed);
            _log.Debug("Work items processed: " + _counter);
            for (int i = 0; i < test; ++i)
            {
                stp[i].Dispose();
                Assert.AreEqual(0, stp[i].WorkItemCount, "WorkQueue[{0}] items", i);
                Assert.AreEqual(0, stp[i].ThreadCount, "WorkQueue[{0}] threads", i);
            }
        }
Example #24
0
 private Result <long> CopyStream(Action <string> activity, Stream source, Stream target, long length, Result <long> result)
 {
     // NOTE (steveb): intermediary copy steps already have a timeout operation, no need to limit the duration of the entire copy operation
     if ((source == Stream.Null) || (length == 0))
     {
         activity("return CopyStream 1");
         result.Return(0);
     }
     else if (!SysUtil.UseAsyncIO || (source.IsStreamMemorized() && target.IsStreamMemorized()))
     {
         // source & target are memory streams; let's do the copy inline as fast as we can
         byte[] buffer = new byte[StreamUtil.BUFFER_SIZE];
         long   total  = 0;
         while (length != 0)
         {
             long count = source.Read(buffer, 0, buffer.Length);
             if (count == 0)
             {
                 break;
             }
             target.Write(buffer, 0, (int)count);
             total  += count;
             length -= count;
         }
         activity("return CopyStream 2");
         result.Return(total);
     }
     else
     {
         // use new task environment so we don't copy the task state over and over again
         TaskEnv.ExecuteNew(delegate() {
             activity("pre CopyStream_Handler");
             Coroutine.Invoke(CopyStream_Handler, activity, source, target, length, result);
             activity("post CopyStream_Handler");
         });
     }
     return(result);
 }
Example #25
0
 void ITaskTimerOwner.AddToQueue(TaskTimer timer, TaskEnv env, TaskTimerStatus next)
 {
     env.Acquire();
     if(timer.Env != null) {
         timer.Env.Release();
     }
     if(_running) {
         lock(_queue) {
             timer.Env = env;
             timer.SetStatus(next);
             _queue.Enqueue(timer);
         }
     } else {
         env.Release();
         timer.Env = null;
         timer.SetStatus(TaskTimerStatus.Done);
     }
 }
Example #26
0
File: timer.cs Project: bjorg/DReAM
        /// <summary>
        /// Change when the timer will execute.
        /// </summary>
        /// <param name="when">The absolute time.</param>
        /// <param name="env">The environment to use for invocation.</param>
        public void Change(DateTime when, TaskEnv env) {
            DateTime now = GlobalClock.UtcNow;

            // determine new status
            int next;
            if(when <= now.AddSeconds(QUEUE_CUTOFF)) {
                next = (int)TaskTimerStatus.Queued;
            } else if(when < DateTime.MaxValue) {
                next = (int)TaskTimerStatus.Pending;
            } else {
                next = (int)TaskTimerStatus.Done;
            }

            // ensure we have a behavior if we need one and we don't if we do not
            if(next != (int)TaskTimerStatus.Done) {
                if(env == null) {
                    throw new ArgumentNullException("env");
                }
            } else {
                env = null;
            }

            // attempt to change current status
        retry:
            int current;
            switch(_status) {
            case (int)TaskTimerStatus.Done:

                // nothing to do
                break;
            case (int)TaskTimerStatus.Pending:

                // attempt to remove timer from pending list
                current = Interlocked.CompareExchange(ref _status, (int)TaskTimerStatus.Done, (int)TaskTimerStatus.Pending);
                switch(current) {
                case (int)TaskTimerStatus.Done:

                    // nothing to do
                    break;
                case (int)TaskTimerStatus.Pending:

                    // remove timer from pending list
                    _owner.RemoveFromPending(this);
                    break;
                case (int)TaskTimerStatus.Queued:

                    // we changed states; retry
                    Interlocked.Increment(ref _retries);
                    goto retry;
                case (int)TaskTimerStatus.Locked:

                    // somebody else is already changing the timer; no need to compete
                    return;
                }
                break;
            case (int)TaskTimerStatus.Queued:

                // attempto remove timer from queue
                current = Interlocked.CompareExchange(ref _status, (int)TaskTimerStatus.Done, (int)TaskTimerStatus.Queued);
                switch(current) {
                case (int)TaskTimerStatus.Done:

                    // nothing to do
                    break;
                case (int)TaskTimerStatus.Pending:

                    // we changed states; retry
                    Interlocked.Increment(ref _retries);
                    goto retry;
                case (int)TaskTimerStatus.Queued:

                    // remove timer from queue
                    _owner.RemoveFromQueue(this);
                    break;
                case (int)TaskTimerStatus.Locked:

                    // somebody else is already changing the timer; no need to compete
                    return;
                }
                break;
            case (int)TaskTimerStatus.Locked:

                // somebody else is already changing the timer; no need to compete
                return;
            }

            // register timer according to new status
            if(Interlocked.CompareExchange(ref _status, (int)TaskTimerStatus.Locked, (int)TaskTimerStatus.Done) == (int)TaskTimerStatus.Done) {
                _when = when;
                switch(next) {
                case (int)TaskTimerStatus.Done:

                    // release Task Environment
                    if(Env != null) {
                        Env.Release();
                    }
                    Env = null;
                    Interlocked.Exchange(ref _status, next);
                    return;
                case (int)TaskTimerStatus.Pending:

                    // add timer to pending list
                    _owner.AddToPending(this, env, (TaskTimerStatus)next);
                    break;
                case (int)TaskTimerStatus.Queued:

                    // add timer to active queue
                    _owner.AddToQueue(this, env, (TaskTimerStatus)next);
                    break;
                case (int)TaskTimerStatus.Locked:
                    Interlocked.Exchange(ref _status, (int)TaskTimerStatus.Done);
                    throw new InvalidOperationException("should never happen");
                }
            }
        }
Example #27
0
File: timer.cs Project: bjorg/DReAM
        //--- Methods ---

        /// <summary>
        /// Change when the timer will execute.
        /// </summary>
        /// <param name="timespan">The relative time.</param>
        /// <param name="env">The environment to use for invocation.</param>
        public void Change(TimeSpan timespan, TaskEnv env) {
            if(timespan != TimeSpan.MaxValue) {
                Change(GlobalClock.UtcNow.Add(timespan), env);
            } else {
                Change(DateTime.MaxValue, env);
            }
        }
Example #28
0
 /// <summary>
 /// Create a new timer and set its fire time.
 /// </summary>
 /// <param name="when">Relateive time from now until when the timer should fire.</param>
 /// <param name="handler">The action to invoke when the timer fires.</param>
 /// <param name="state">A state object to associate with the timer.</param>
 /// <param name="env">The environment in which the timer should fire.</param>
 /// <returns>New timer instance.</returns>
 public TaskTimer New(TimeSpan when, Action<TaskTimer> handler, object state, TaskEnv env)
 {
     var result = new TaskTimer(this, handler, state);
     result.Change(when, env);
     return result;
 }
Example #29
0
 /// <summary>
 /// Enqueue a callback as a work item to be invoked with a clone of 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 QueueWorkItemWithClonedEnv(this IDispatchQueue dispatchQueue, Action callback, Result result)
 {
     return(dispatchQueue.QueueWorkItemWithEnv(callback, TaskEnv.Clone(), result));
 }
        //--- Methods ---
        protected override Yield Start(XDoc config, Result result)
        {
            yield return(Coroutine.Invoke(base.Start, config, new Result()));

            // set up defaults
            _insertTextLimit = config["max-size"].AsLong ?? DEFAULT_TEXT_LIMIT;
            _memoryCacheTime = config["memory-cache-time"].AsDouble ?? DEFAULT_MEMORY_CACHE_TIME;
            _log.DebugFormat("max-size: {0}, memory-cache-time: {1}", _insertTextLimit, _memoryCacheTime);

            // load current cache state
            Async.Fork(() => Coroutine.Invoke(RefreshCache, new Result(TimeSpan.MaxValue)), TaskEnv.Clone(), null);
            result.Return();
        }
Example #31
0
 /// <summary>
 /// Enqueue a callback as a work item to be invoked with a clone of the current <see cref="TaskEnv"/>.
 /// </summary>
 /// <param name="dispatchQueue">DispatchQueue to enqueue work into.</param>
 /// <param name="callback">Work item callback.</param>
 public static void QueueWorkItemWithClonedEnv(this IDispatchQueue dispatchQueue, Action callback)
 {
     dispatchQueue.QueueWorkItemWithEnv(callback, TaskEnv.Clone(), null);
 }
Example #32
0
 /// <summary>
 /// Enqueue a callback as a work item to be invoked with a provided <see cref="TaskEnv"/>.
 /// </summary>
 /// <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>
 public static void QueueWorkItemWithEnv(this IDispatchQueue dispatchQueue, Action callback, TaskEnv env)
 {
     dispatchQueue.QueueWorkItemWithEnv(callback, env, null);
 }
Example #33
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);
 }
Example #34
0
 /// <summary>
 /// Enqueue a callback as a work item to be invoked with a clone of 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> QueueWorkItemWithClonedEnv <T>(this IDispatchQueue dispatchQueue, Func <T> callback, Result <T> result)
 {
     return(dispatchQueue.QueueWorkItemWithEnv(callback, TaskEnv.Clone(), result));
 }
Example #35
0
File: timer.cs Project: bjorg/DReAM
 public static TaskTimer New(DateTime when, Action<TaskTimer> handler, object state, TaskEnv env) {
     return TaskTimerFactory.Current.New(when, handler, state, env);
 }
Example #36
0
File: timer.cs Project: bjorg/DReAM
 internal void ExecuteNow(TaskEnv env) {
     env.InvokeNow(() => _handler(this));
 }
Example #37
0
        //--- Class Methods ---

        /// <summary>
        /// Set an interval at which Garbage collection should be forced.
        /// </summary>
        /// <param name="t">Interval length.</param>
        public static void SetCollectionInterval(TimeSpan t)
        {
            _collectInterval = t;
            _collectTimer.Change(t, TaskEnv.New());
            _log.DebugFormat("set collection interval to {0:0} seconds", t.TotalSeconds);
        }
Example #38
0
 void ITaskTimerOwner.AddToPending(TaskTimer timer, TaskEnv env, TaskTimerStatus next)
 {
     env.Acquire();
     if(timer.Env != null) {
         timer.Env.Release();
     }
     if(_running) {
         lock(_pending) {
             timer.Env = env;
             timer.SetStatus(next);
             _pending[timer] = null;
         }
     } else {
         env.Release();
         timer.Env = null;
         timer.SetStatus(TaskTimerStatus.Done);
     }
 }
Example #39
0
File: timer.cs Project: bjorg/DReAM
 internal void Execute(TaskEnv env) {
     env.Invoke(_handler, this);
 }