Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,30 @@ public virtual IScheduledTask Schedule(Action<object, object> action, object con
throw new NotSupportedException();
}

/// <inheritdoc cref="IScheduledExecutorService"/>
public virtual IScheduledTask ScheduleAtFixedRate(Action action, TimeSpan initialDelay, TimeSpan period)
{
throw new NotSupportedException();
}

/// <inheritdoc cref="IScheduledExecutorService"/>
public virtual IScheduledTask ScheduleAtFixedRate(IRunnable action, TimeSpan initialDelay, TimeSpan period)
{
throw new NotSupportedException();
}

/// <inheritdoc cref="IScheduledExecutorService"/>
public virtual IScheduledTask ScheduleWithFixedDelay(Action action, TimeSpan initialDelay, TimeSpan delay)
{
throw new NotSupportedException();
}

/// <inheritdoc cref="IScheduledExecutorService"/>
public virtual IScheduledTask ScheduleWithFixedDelay(IRunnable action, TimeSpan initialDelay, TimeSpan delay)
{
throw new NotSupportedException();
}

/// <inheritdoc cref="IScheduledExecutorService"/>
public virtual Task ScheduleAsync(Action action, TimeSpan delay) =>
this.ScheduleAsync(action, delay, CancellationToken.None);
Expand Down
8 changes: 8 additions & 0 deletions src/DotNetty.Common/Concurrency/AbstractEventExecutorGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ public abstract class AbstractEventExecutorGroup : IEventExecutorGroup

public IScheduledTask Schedule(Action<object, object> action, object context, object state, TimeSpan delay) => this.GetNext().Schedule(action, context, state, delay);

public IScheduledTask ScheduleAtFixedRate(Action action, TimeSpan initialDelay, TimeSpan period) => this.GetNext().ScheduleAtFixedRate(action, initialDelay, period);

public IScheduledTask ScheduleAtFixedRate(IRunnable action, TimeSpan initialDelay, TimeSpan period) => this.GetNext().ScheduleAtFixedRate(action, initialDelay, period);

public IScheduledTask ScheduleWithFixedDelay(Action action, TimeSpan initialDelay, TimeSpan delay) => this.GetNext().ScheduleWithFixedDelay(action, initialDelay, delay);

public IScheduledTask ScheduleWithFixedDelay(IRunnable action, TimeSpan initialDelay, TimeSpan delay) => this.GetNext().ScheduleWithFixedDelay(action, initialDelay, delay);

public Task ScheduleAsync(Action<object> action, object state, TimeSpan delay, CancellationToken cancellationToken) => this.GetNext().ScheduleAsync(action, state, delay, cancellationToken);

public Task ScheduleAsync(Action<object> action, object state, TimeSpan delay) => this.GetNext().ScheduleAsync(action, state, delay);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,35 @@ public override IScheduledTask Schedule(Action<object, object> action, object co
return this.Schedule(new StateActionWithContextScheduledTask(this, action, context, state, PreciseTimeSpan.Deadline(delay)));
}

public override IScheduledTask ScheduleAtFixedRate(Action action, TimeSpan initialDelay, TimeSpan period)
{
Contract.Requires(action != null);

return this.Schedule(new FixedRateScheduledTask(this, action, PreciseTimeSpan.Deadline(initialDelay), PreciseTimeSpan.FromTimeSpan(period)));
}

public override IScheduledTask ScheduleAtFixedRate(IRunnable action, TimeSpan initialDelay, TimeSpan period)
{
Contract.Requires(action != null);

return this.Schedule(new FixedRateScheduledTask(this, action, PreciseTimeSpan.Deadline(initialDelay), PreciseTimeSpan.FromTimeSpan(period)));

}

public override IScheduledTask ScheduleWithFixedDelay(Action action, TimeSpan initialDelay, TimeSpan delay)
{
Contract.Requires(action != null);

return this.Schedule(new FixedDelayScheduledTask(this, action, PreciseTimeSpan.Deadline(initialDelay), PreciseTimeSpan.FromTimeSpan(delay)));
}

public override IScheduledTask ScheduleWithFixedDelay(IRunnable action, TimeSpan initialDelay, TimeSpan delay)
{
Contract.Requires(action != null);

return this.Schedule(new FixedDelayScheduledTask(this, action, PreciseTimeSpan.Deadline(initialDelay), PreciseTimeSpan.FromTimeSpan(delay)));
}

public override Task ScheduleAsync(Action action, TimeSpan delay, CancellationToken cancellationToken)
{
Contract.Requires(action != null);
Expand Down Expand Up @@ -169,7 +198,7 @@ public override Task ScheduleAsync(Action<object, object> action, object context
return this.Schedule(new StateActionWithContextScheduledAsyncTask(this, action, context, state, PreciseTimeSpan.Deadline(delay), cancellationToken)).Completion;
}

protected IScheduledRunnable Schedule(IScheduledRunnable task)
internal IScheduledRunnable Schedule(IScheduledRunnable task)
{
if (this.InEventLoop)
{
Expand Down
53 changes: 53 additions & 0 deletions src/DotNetty.Common/Concurrency/FixedDelayScheduledTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

namespace DotNetty.Common.Concurrency
{

sealed class FixedDelayScheduledTask : ScheduledTask
{
readonly Action action;
public FixedDelayScheduledTask(AbstractScheduledEventExecutor executor, IRunnable action, PreciseTimeSpan deadline, PreciseTimeSpan period)
: this(executor, action.Run, deadline, period)
{
}

public FixedDelayScheduledTask(AbstractScheduledEventExecutor executor, Action action, PreciseTimeSpan deadline, PreciseTimeSpan period)
: base(executor, deadline, new TaskCompletionSource())
{
if (period.Ticks <= 0)
throw new ArgumentException("period: 0 (expected: != 0)");

this.Period = period;
this.action = action;
}

public PreciseTimeSpan Period { get; }

protected override void Execute() => this.action();

public override void Run()
{
try
{
this.Execute();
if (!Executor.IsShutdown)
{
this.Deadline = PreciseTimeSpan.Deadline(this.Period);
this.Executor.Schedule(this);
}
else
{
this.Promise.TryComplete();
}
}
catch (Exception ex)
{
// todo: check for fatal
this.Promise.TrySetException(ex);
}
}
}
}
52 changes: 52 additions & 0 deletions src/DotNetty.Common/Concurrency/FixedRateScheduledTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;

namespace DotNetty.Common.Concurrency
{
sealed class FixedRateScheduledTask : ScheduledTask
{
readonly Action action;
public FixedRateScheduledTask(AbstractScheduledEventExecutor executor, IRunnable action, PreciseTimeSpan deadline, PreciseTimeSpan period)
: this(executor, action.Run, deadline, period)
{
}

public FixedRateScheduledTask(AbstractScheduledEventExecutor executor, Action action, PreciseTimeSpan deadline, PreciseTimeSpan period)
: base(executor, deadline, new TaskCompletionSource())
{
if (period.Ticks <= 0)
throw new ArgumentException("period: 0 (expected: != 0)");

this.Period = period;
this.action = action;
}

public PreciseTimeSpan Period { get; }

protected override void Execute() => this.action();

public override void Run()
{
try
{
this.Execute();
if (!Executor.IsShutdown)
{
this.Deadline = PreciseTimeSpan.FromTicks(Deadline.Ticks + Period.Ticks);
this.Executor.Schedule(this);
}
else
{
this.Promise.TryComplete();
}
}
catch (Exception ex)
{
// todo: check for fatal
this.Promise.TrySetException(ex);
}
}
}
}
36 changes: 36 additions & 0 deletions src/DotNetty.Common/Concurrency/IScheduledExecutorService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,42 @@ public interface IScheduledExecutorService : IExecutorService
/// </remarks>
IScheduledTask Schedule(Action<object, object> action, object context, object state, TimeSpan delay);

/// <summary>
/// Schedules the given action for execution at a fixed frequency after the specified delay would pass.
/// </summary>
/// <param name="action"></param>
/// <param name="initialDelay"></param>
/// <param name="period"></param>
/// <returns></returns>
IScheduledTask ScheduleAtFixedRate(Action action, TimeSpan initialDelay, TimeSpan period);

/// <summary>
/// Schedules the given action for execution at a fixed frequency after the specified delay would pass.
/// </summary>
/// <param name="action"></param>
/// <param name="initialDelay"></param>
/// <param name="period"></param>
/// <returns></returns>
IScheduledTask ScheduleAtFixedRate(IRunnable action, TimeSpan initialDelay, TimeSpan period);

/// <summary>
/// Schedules the given action for execution at a fixed delay after the specified delay would pass.
/// </summary>
/// <param name="action"></param>
/// <param name="initialDelay"></param>
/// <param name="delay"></param>
/// <returns></returns>
IScheduledTask ScheduleWithFixedDelay(Action action, TimeSpan initialDelay, TimeSpan delay);

/// <summary>
/// Schedules the given action for execution at a fixed delay after the specified delay would pass.
/// </summary>
/// <param name="action"></param>
/// <param name="initialDelay"></param>
/// <param name="delay"></param>
/// <returns></returns>
IScheduledTask ScheduleWithFixedDelay(IRunnable action, TimeSpan initialDelay, TimeSpan delay);

/// <summary>
/// Schedules the given action for execution after the specified delay would pass.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/DotNetty.Common/Concurrency/ScheduledTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ protected ScheduledTask(AbstractScheduledEventExecutor executor, PreciseTimeSpan
this.Deadline = deadline;
}

public PreciseTimeSpan Deadline { get; }
public PreciseTimeSpan Deadline { get; protected set; }

public bool Cancel()
{
Expand Down