Skip to content

Commit

Permalink
Add allows ref struct
Browse files Browse the repository at this point in the history
  • Loading branch information
wherewhere committed Aug 31, 2024
1 parent 45d19e6 commit d81a8ab
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 13 deletions.
18 changes: 15 additions & 3 deletions AdvancedSharpAdbClient/DeviceMonitor.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ public partial class DeviceMonitor
/// is used to block the <see cref="StartAsync(CancellationToken)"/> method until the <see cref="DeviceMonitorLoopAsync"/>
/// has processed the first list of devices.
/// </summary>
#if NET5_0_OR_GREATER
protected TaskCompletionSource? FirstDeviceListParsed;
#else
protected TaskCompletionSource<object?>? FirstDeviceListParsed;
#endif

/// <summary>
/// A <see cref="CancellationToken"/> that can be used to cancel the <see cref="MonitorTask"/>.
Expand All @@ -39,11 +43,11 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
{
try
{
FirstDeviceListParsed = new TaskCompletionSource<object?>();
FirstDeviceListParsed = new();
using CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.Register(() => FirstDeviceListParsed.SetCanceled());
MonitorTask = DeviceMonitorLoopAsync(MonitorTaskCancellationTokenSource.Token);
// Wait for the worker thread to have read the first list of devices.
_ = await FirstDeviceListParsed.Task.ConfigureAwait(false);
await FirstDeviceListParsed.Task.ConfigureAwait(false);
}
finally
{
Expand Down Expand Up @@ -133,7 +137,15 @@ protected virtual async Task DeviceMonitorLoopAsync(CancellationToken cancellati
if (FirstDeviceListParsed != null)
{
// Switch to the background thread to avoid blocking the caller.
_ = Task.Factory.StartNew(() => FirstDeviceListParsed?.TrySetResult(null), default, TaskCreationOptions.None, TaskScheduler.Default);
_ = Task.Factory.StartNew(
#if NET5_0_OR_GREATER
() => FirstDeviceListParsed?.TrySetResult(),
#else
() => FirstDeviceListParsed?.TrySetResult(null),
#endif
default,
TaskCreationOptions.None,
TaskScheduler.Default);
}
}
catch (TaskCanceledException ex)
Expand Down
4 changes: 2 additions & 2 deletions AdvancedSharpAdbClient/DeviceMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ public void Start()
{
try
{
FirstDeviceListParsed = new TaskCompletionSource<object?>();
FirstDeviceListParsed = new();
MonitorTask = DeviceMonitorLoopAsync(MonitorTaskCancellationTokenSource.Token);
// Wait for the worker thread to have read the first list of devices.
_ = FirstDeviceListParsed.Task.AwaitByTaskCompleteSource();
FirstDeviceListParsed.Task.AwaitByTaskCompleteSource();
}
finally
{
Expand Down
4 changes: 2 additions & 2 deletions AdvancedSharpAdbClient/Extensions/EnumerableBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,13 @@ static void ReadLogEntry(BinaryReader reader, params ICollection<object> parent)
ushort? ReadUInt16(in ReadOnlySpan<byte> bytes)
{
ReadOnlySpan<byte> data = ReadBytesSafe(bytes, 2);
return data == null ? null : (ushort)(data[0] | (data[1] << 8));
return data.IsEmpty ? null : (ushort)(data[0] | (data[1] << 8));
}

uint? ReadUInt32(in ReadOnlySpan<byte> bytes)
{
ReadOnlySpan<byte> data = ReadBytesSafe(bytes, 4);
return data == null ? null : (uint)(data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24));
return data.IsEmpty ? null : (uint)(data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24));
}

int? ReadInt32(in ReadOnlySpan<byte> bytes)
Expand Down
6 changes: 5 additions & 1 deletion AdvancedSharpAdbClient/Logs/Interfaces/ILogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ public interface ILogger
/// Generally used to enable activation of a named <see cref="ILogger"/> from dependency injection.
/// </summary>
/// <typeparam name="TCategoryName">The type whose name is used for the logger category name.</typeparam>
public interface ILogger<out TCategoryName> : ILogger;
public interface ILogger<out TCategoryName> : ILogger
#if NET9_0_OR_GREATER
where TCategoryName : allows ref struct
#endif
;
}
6 changes: 5 additions & 1 deletion AdvancedSharpAdbClient/Logs/Interfaces/ILoggerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public interface ILoggerFactory
/// </summary>
/// <typeparam name="T">The category name for messages produced by the logger.</typeparam>
/// <returns>The <see cref="ILogger"/>.</returns>
ILogger<T> CreateLogger<T>();
ILogger<T> CreateLogger<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
;
}
}
6 changes: 5 additions & 1 deletion AdvancedSharpAdbClient/Logs/LoggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public static class LoggerProvider
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <returns>The <see cref="ILogger"/> that was created</returns>
public static ILogger<T> CreateLogger<T>() => _loggerFactory == null ? NullLogger<T>.Instance : _loggerFactory.CreateLogger<T>();
public static ILogger<T> CreateLogger<T>()
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
=> _loggerFactory == null ? NullLogger<T>.Instance : _loggerFactory.CreateLogger<T>();
}
}
3 changes: 3 additions & 0 deletions AdvancedSharpAdbClient/Logs/NullLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public void Log(LogLevel logLevel, Exception? exception, string? message, params
/// Minimalistic logger that does nothing.
/// </summary>
public class NullLogger<T> : NullLogger, ILogger<T>
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
{
/// <summary>
/// Returns an instance of <see cref="NullLogger{T}"/>.
Expand Down
2 changes: 1 addition & 1 deletion AdvancedSharpAdbClient/Models/AdbCommandLineStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public readonly IEnumerator<string> GetEnumerator()
}

/// <inheritdoc/>
public override string ToString() => string.Join(Environment.NewLine, [.. this]);
public override string ToString() => string.Join(Environment.NewLine, (string[])[.. this]);

#if NET7_0_OR_GREATER
[GeneratedRegex(VersionPattern)]
Expand Down
15 changes: 13 additions & 2 deletions AdvancedSharpAdbClient/Polyfills/Extensions/TaskExExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

#if NET40
using Microsoft.Runtime.CompilerServices;
Expand Down Expand Up @@ -137,21 +138,31 @@ public static TResult AwaitByTaskCompleteSource<TResult>(this IAsyncOperation<TR
/// <param name="cancellationToken">A cancellation token that can be used to cancel the work if it has not yet started.</param>
public static void AwaitByTaskCompleteSource(this Task function, CancellationToken cancellationToken = default)
{
#if NET5_0_OR_GREATER
TaskCompletionSource taskCompletionSource = new();
#else
TaskCompletionSource<object?> taskCompletionSource = new();
Task<object?> task = taskCompletionSource.Task;
#endif
#pragma warning disable IDE0008
var task = taskCompletionSource.Task;
#pragma warning restore IDE0008
_ = Task.Factory.StartNew(async () =>
{
try
{
await function.ConfigureAwait(false);
#if NET5_0_OR_GREATER
_ = taskCompletionSource.TrySetResult();
#else
_ = taskCompletionSource.TrySetResult(null);
#endif
}
catch (Exception e)
{
_ = taskCompletionSource.TrySetException(e);
}
}, cancellationToken);
_ = task.Result;
task.Wait(cancellationToken);
}

/// <summary>
Expand Down
3 changes: 3 additions & 0 deletions AdvancedSharpAdbClient/Polyfills/Interfaces/ICloneable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ namespace AdvancedSharpAdbClient.Polyfills
/// </summary>
/// <typeparam name="T">The type of the class.</typeparam>
public interface ICloneable<out T> : ICloneable
#if NET9_0_OR_GREATER
where T : allows ref struct
#endif
{
/// <summary>
/// Creates a new <typeparamref name="T"/> object that is a copy of the current instance.
Expand Down

0 comments on commit d81a8ab

Please sign in to comment.