void DestroyDown(XThread currentThread, FABHandlerContext ctx, bool inEventLoop) { // We have reached at tail; now traverse backwards. FABHandlerContext headContext = this.head; while (true) { if (ctx == headContext) { break; } IEventExecutor executor = ctx.Executor; if (inEventLoop || executor.IsInEventLoop(currentThread)) { lock (this) { Remove0(ctx); this.CallHandlerRemoved0(ctx); } } else { executor.Execute((self, c) => ((FABChannelPipeline)self).DestroyDown(XThread.CurrentThread, (FABHandlerContext)c, true), this, ctx); break; } ctx = ctx.Prev; inEventLoop = false; } }
/// <summary> /// Creates a new timer. /// </summary> /// <param name="tickInterval">the interval between two consecutive ticks</param> /// <param name="ticksPerWheel">the size of the wheel</param> /// <param name="maxPendingTimeouts">The maximum number of pending timeouts after which call to /// <c>newTimeout</c> will result in <see cref="RejectedExecutionException"/> being thrown. /// No maximum pending timeouts limit is assumed if this value is 0 or negative.</param> /// <exception cref="ArgumentException">if either of <c>tickInterval</c> and <c>ticksPerWheel</c> is <= 0</exception> public HashedWheelTimer( TimeSpan tickInterval, int ticksPerWheel, long maxPendingTimeouts) { if (tickInterval <= TimeSpan.Zero) { throw new ArgumentException($"{nameof(tickInterval)} must be greater than 0: {tickInterval}"); } if (Math.Ceiling(tickInterval.TotalMilliseconds) > int.MaxValue) { throw new ArgumentException($"{nameof(tickInterval)} must be less than or equal to ${int.MaxValue} ms."); } if (ticksPerWheel <= 0) { throw new ArgumentException($"{nameof(ticksPerWheel)} must be greater than 0: {ticksPerWheel}"); } if (ticksPerWheel > int.MaxValue / 2 + 1) { throw new ArgumentOutOfRangeException( $"{nameof(ticksPerWheel)} may not be greater than 2^30: {ticksPerWheel}"); } // Normalize ticksPerWheel to power of two and initialize the wheel. this.wheel = CreateWheel(ticksPerWheel); this.worker = new Worker(this); this.mask = this.wheel.Length - 1; this.tickDuration = tickInterval.Ticks; // Prevent overflow if (this.tickDuration >= long.MaxValue / this.wheel.Length) { throw new ArgumentException( string.Format( "tickInterval: {0} (expected: 0 < tickInterval in nanos < {1}", tickInterval, long.MaxValue / this.wheel.Length)); } this.workerThread = new XThread(st => this.worker.Run()); this.maxPendingTimeouts = maxPendingTimeouts; if (Interlocked.Increment(ref instanceCounter) > InstanceCountLimit && Interlocked.CompareExchange(ref warnedTooManyInstances, 1, 0) == 0) { ReportTooManyInstances(); } }
/// <summary>Creates a new timer.</summary> /// <param name="tickInterval">the interval between two consecutive ticks</param> /// <param name="ticksPerWheel">the size of the wheel</param> /// <param name="maxPendingTimeouts">The maximum number of pending timeouts after which call to /// <c>newTimeout</c> will result in <see cref="RejectedExecutionException"/> being thrown. /// No maximum pending timeouts limit is assumed if this value is 0 or negative.</param> /// <exception cref="ArgumentException">if either of <c>tickInterval</c> and <c>ticksPerWheel</c> is <= 0</exception> public HashedWheelTimer(TimeSpan tickInterval, int ticksPerWheel, long maxPendingTimeouts) { if (tickInterval <= TimeSpan.Zero) { ThrowHelper.ThrowArgumentException_MustBeGreaterThanZero(tickInterval); } if (Math.Ceiling(tickInterval.TotalMilliseconds) > int.MaxValue) { ThrowHelper.ThrowArgumentException_MustBeLessThanOrEqualTo(); } if (ticksPerWheel <= 0) { ThrowHelper.ThrowArgumentException_MustBeGreaterThanZero(ticksPerWheel); } if (ticksPerWheel > int.MaxValue / 2 + 1) { ThrowHelper.ThrowArgumentOutOfRangeException_MustBeGreaterThan(ticksPerWheel); } // Normalize ticksPerWheel to power of two and initialize the wheel. _wheel = CreateWheel(ticksPerWheel); _worker = new Worker(this); _mask = _wheel.Length - 1; _tickDuration = tickInterval.Ticks; // Prevent overflow if (_tickDuration >= long.MaxValue / _wheel.Length) { throw new ArgumentException( string.Format( "tickInterval: {0} (expected: 0 < tickInterval in nanos < {1}", tickInterval, long.MaxValue / _wheel.Length)); } _workerThread = new XThread(st => _worker.Run()); _maxPendingTimeouts = maxPendingTimeouts; if (Interlocked.Increment(ref v_instanceCounter) > InstanceCountLimit && 0u >= (uint)Interlocked.CompareExchange(ref v_warnedTooManyInstances, 1, 0)) { ReportTooManyInstances(); } }
void CreateLongRunningTask(XParameterizedThreadStart threadStartFunc) { this.task = Task.Factory.StartNew(() => { // We start the task running, then unleash it by signaling the readyToStart event. // This is needed to avoid thread reuse for tasks (see below) this.readyToStart.WaitOne(); // This is the first time we're using this thread, therefore the TLS slot must be empty if (tls_this_thread != null) { Debug.WriteLine("warning: tls_this_thread already created; OS thread reused"); Debug.Assert(false); } tls_this_thread = this; threadStartFunc(this.startupParameter); this.completed.Set(); }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); }
public LoopExecutor(IEventLoopGroup parent, string threadName, TimeSpan breakoutInterval) : base(parent) { this.preciseBreakoutInterval = (long)breakoutInterval.TotalMilliseconds; this.terminationCompletionSource = new TaskCompletionSource(); this.taskQueue = PlatformDependent.NewMpscQueue <IRunnable>(); this.scheduler = new ExecutorTaskScheduler(this); this.loop = new Loop(); this.asyncHandle = new Async(this.loop, OnCallback, this); this.timerHandle = new Timer(this.loop, OnCallback, this); string name = $"{this.GetType().Name}:{this.loop.Handle}"; if (!string.IsNullOrEmpty(threadName)) { name = $"{name}({threadName})"; } this.thread = new XThread(Run) { Name = name }; this.loopRunStart = new ManualResetEventSlim(false, 1); }
public LoopExecutor(IEventLoopGroup parent, string threadName, TimeSpan breakoutInterval) : base(parent) { this.preciseBreakoutInterval = PreciseTimeSpan.FromTimeSpan(breakoutInterval); this.preciseTimerInterval = PreciseTimeSpan.FromTimeSpan(TimeSpan.FromTicks(breakoutInterval.Ticks * 2)); this.terminationCompletionSource = new TaskCompletionSource(); this.taskQueue = PlatformDependent.NewMpscQueue <IRunnable>(); this.scheduler = new ExecutorTaskScheduler(this); this.loop = new Loop(); this.asyncHandle = new Async(this.loop, RunAllTasksCallback, this); this.timerHandle = new Timer(this.loop, RunAllTasksCallback, this); string name = string.Format(DefaultWorkerThreadName, this.loop.Handle); if (!string.IsNullOrEmpty(threadName)) { name = $"{name} ({threadName})"; } this.thread = new XThread(RunLoop) { Name = name }; }
public static long Run() { long ran = 0; const int Iterations = 100 * 1000 * 1000; Thread thread = null; thread = new Thread(() => { CodeTimer.Time(true, "Thread", Iterations, () => { if (Thread.CurrentThread == thread) { ran++; } }); }); thread.Start(); thread.Join(100000); XThread xthread = null; xthread = new XThread(() => { CodeTimer.Time(true, "XThread", Iterations, () => { if (XThread.CurrentThread == xthread) { ran++; } }); }); xthread.Start(); xthread.Join(100000); return(ran); }
void DestroyUp(FABHandlerContext ctx, bool inEventLoop) { XThread currentThread = XThread.CurrentThread; FABHandlerContext tailContext = this.tail; while (true) { if (ctx == tailContext) { this.DestroyDown(currentThread, tailContext.Prev, inEventLoop); break; } IEventExecutor executor = ctx.Executor; if (!inEventLoop && !executor.IsInEventLoop(currentThread)) { executor.Execute((self, c) => ((FABChannelPipeline)self).DestroyUp((FABHandlerContext)c, true), this, ctx); break; } ctx = ctx.Next; inEventLoop = false; } }
public static void LoopRunDefaultError(this IInternalLogger logger, XThread thread, IntPtr handle, Exception ex) { logger.Error("Loop {}:{} run default error.", thread.Name, handle, ex); }
public static void LoopThreadFinished(this IInternalLogger logger, XThread thread, IntPtr handle) { logger.Info("Loop {}:{} thread finished.", thread.Name, handle); }
public static void LoopReleaseError(this IInternalLogger logger, XThread thread, IntPtr handle, Exception ex) { logger.Warn("{}:{} release error {}", thread.Name, handle, ex); }
public static void LoopDisposed(this IInternalLogger logger, XThread thread, IntPtr handle) { logger.Info("{}:{} disposed.", thread.Name, handle); }
public static void FreedThreadLocalBufferFromThread(this IInternalLogger logger, int numFreed, XThread deathWatchThread) { logger.Debug("Freed {} thread-local buffer(s) from thread: {}", numFreed, deathWatchThread.Name); }
public static void ExecutionLoopFailed(this IInternalLogger logger, XThread thread, Exception ex) { logger.Error("{}: execution loop failed", thread.Name, ex); }
public override bool IsInEventLoop(XThread thread) { return(true); }
public override bool IsInEventLoop(XThread t) => this.thread == t;