Skip to content

Commit

Permalink
Added draft for command queue utility.
Browse files Browse the repository at this point in the history
  • Loading branch information
xabre committed Apr 9, 2017
1 parent 3f2271b commit 7914486
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
Expand Down Expand Up @@ -73,6 +73,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceBase.cs" />
<Compile Include="Trace.cs" />
<Compile Include="Utils\BleCommandQueue.cs" />
<Compile Include="Utils\FakeAdapter.cs" />
<Compile Include="Utils\TaskBuilder.cs" />
</ItemGroup>
Expand Down
130 changes: 130 additions & 0 deletions Source/Plugin.BLE.Abstractions/Utils/BleCommandQueue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Plugin.BLE.Abstractions.Utils
{
public class BleCommandQueue
{
public Queue<IBleCommand> CommandQueue { get; set; }

private object _lock = new object();
private IBleCommand _currentCommand;

public BleCommandQueue()
{

}

public Task<T> EnqueueAsync<T>(Func<Task<T>> bleCommand, int timeOutInSeconds = 10)
{
var command = new BleCommand<T>(bleCommand, timeOutInSeconds);
lock (_lock)
{
CommandQueue.Enqueue(command);
}

TryExecuteNext();
return command.ExecutingTask;
}

public void CancelPending()
{
lock (_lock)
{
foreach (var command in CommandQueue)
{
command.Cancel();
}
CommandQueue.Clear();
}
}

private async void TryExecuteNext()
{
lock (_lock)
{
if (_currentCommand != null || !CommandQueue.Any())
{
return;
}

_currentCommand = CommandQueue.Dequeue();
}

await _currentCommand.ExecuteAsync();

lock (_lock)
{
_currentCommand = null;
}

TryExecuteNext();

}
}


public interface IBleCommand
{
Task ExecuteAsync();
void Cancel();
bool IsExecuting { get; }
int TimeoutInMiliSeconds { get; }
}

public class BleCommand<T> : IBleCommand
{
private Func<Task<T>> _taskSource;
private TaskCompletionSource<T> _taskCompletionSource;

public int TimeoutInMiliSeconds { get; }

public BleCommand(Func<Task<T>> taskSource, int timeoutInSeconds)
{
_taskSource = taskSource;
TimeoutInMiliSeconds = timeoutInSeconds;
_taskCompletionSource = new TaskCompletionSource<T>();
}

public Task<T> ExecutingTask => _taskCompletionSource.Task;

public bool IsExecuting { get; private set; }

public async Task ExecuteAsync()
{
try
{
IsExecuting = true;
var source = _taskSource();
if (source != await Task.WhenAny(source, Task.Delay(TimeoutInMiliSeconds)))
{
throw new TimeoutException("Timed out while executing ble task.");
}

_taskCompletionSource.TrySetResult(await source);
}
catch (TaskCanceledException)
{
_taskCompletionSource.TrySetCanceled();
}
catch (Exception ex)
{
_taskCompletionSource.TrySetException(ex);
}
finally
{
IsExecuting = false;
}

}

public void Cancel()
{
_taskCompletionSource.TrySetCanceled();
}
}
}

0 comments on commit 7914486

Please sign in to comment.