Skip to content

Commit

Permalink
Updated version.
Browse files Browse the repository at this point in the history
Added v3.2.0 changelog.
Added channels documentation.
Updated documentation for ConfigureAwait.
  • Loading branch information
timcassell committed Nov 3, 2024
1 parent 95db72c commit f5cb851
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 14 deletions.
30 changes: 30 additions & 0 deletions Docs/Changelog/v3.2.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Change Log

## v3.2.0 - November 3, 2024

Enhancements:

- Added `Channel<T>` and related types in `Proto.Promises.Channels` namespace.
- Added `Promise(<T>).{ConfigureAwait, ConfigureContinuation}` APIs and accompanying `ContinuationOptions` type.
- Added `SynchronizationOption.CapturedContext` option.
- Added `(Ordered, Configured)AsyncEnumerable.ConfigureAwait(ContinuationOptions)` new overloads.
- Exposed `ConfiguredAsyncEnumerable<T>.{ContinuationOptions, CancelationToken}` and `ConfiguredAsyncEnumerable<T>.Enumerator.ContinuationOptions`.
- Added `ManualSynchronizationContextCore` type.
- Added `PromiseSynchronizationContext.Execute(bool exhaustive)` API.
- Added `Promise(<T>).FromException` API.
- Added option to disable context capture for async synchronization primitives.

Fixes:

- Fixed some bugs surrounding `AsyncEnumerable.Merge` enumerator disposal.
- Fixed a potential race condition with `Promise.New` API.
- Fixed some async Linq implementations that weren't configuring the awaits properly.

Deprecated:

- Deprecated `Promise(<T>).WaitAsync` APIs accepting `SynchronizationContext` and `SynchronizationOption`.

Misc:

- Changed default `Progress` invokeOption to `CapturedContext`.
- Added net8.0 build target.
7 changes: 7 additions & 0 deletions Docs/Guides/channels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Channels

A channel is an async producer/consumer data structure, similar to a blocking collection. You can use it to move data from 1 or more producers to 1 or more consumers asynchronously. Both bounded and unbounded channels are supported.

`Proto.Promises.Channels.Channel<T>` was designed very similar to `System.Threading.Channels.Channel<T>`. See the [BCL documentation](https://learn.microsoft.com/en-us/dotnet/core/extensions/channels) to see how channels may be typically used. Channels in this library work very similarly, but were also designed to not allocate. When you no longer need the channel, you can `Dispose` it to return the backing object to the pool for future re-use.

Another difference from the BCL design is, if the channeled objects need to be cleaned up, and you are working with a bounded channel, you can retrieve the dropped item and clean it up, or try to write it to the channel again. `if (channelWriteResult.TryGetDroppedItem(out var droppedItem)) { ... }`
2 changes: 1 addition & 1 deletion Docs/Guides/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ If you are in DEBUG mode, you can configure when additional stacktraces will be

`Promise.Config.UncaughtRejectionHandler` allows you to route unhandled rejections through a delegate instead of being thrown.

`Promise.Config.ForegroundContext` is the context to which foreground operations are posted, typically used to marshal work to the UI thread. This is automatically set in Unity, but in other UI frameworks it should be set at application startup (usually `Promise.Config.ForegroundContext = SynchronizationContext.Current` is enough). Note: if your application uses multiple `SynchronizationContext`s, you should instead pass the context directly to the `WaitAsync` and other APIs instead of using `SynchronizationOption.Foreground`. See [Switching Execution Context](context-switching.md).
`Promise.Config.ForegroundContext` is the context to which foreground operations are posted, typically used to marshal work to the UI thread. This is automatically set in Unity, but in other UI frameworks it should be set at application startup (usually `Promise.Config.ForegroundContext = SynchronizationContext.Current` is enough). Note: if your application uses multiple `SynchronizationContext`s, you may want to pass `ContinuationOptions.CapturedContext` to the `ConfigureAwait` and other APIs instead of `Foreground`. See [Switching Execution Context](context-switching.md).

`Promise.Config.BackgroundContext` can be set to override how background operations are executed. If this is null, `ThreadPool.QueueUserWorkItem(callback, state)` is used.

Expand Down
14 changes: 7 additions & 7 deletions Docs/Guides/context-switching.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

Context switching in this case refers to switching execution between the main/UI thread and background threads. Executing code on a background thread frees up the UI thread to draw the application at a higher frame-rate and not freeze the application when executing an expensive computation.

Promise continuations (`.Then` or `await`) normally execute synchronously, not caring what thread they are executing on. However, you can force continuations to execute either on the foreground context for UI code, or background context for expensive non-UI code. You can use the `promise.WaitAsync(SynchronizationOption)` to force the next continuation to execute on the given context (`Synchronous` (default), `Foreground`, or `Background`).
Promise continuations (`.Then` or `await`) execute synchronously by default, not caring what thread they are executing on. However, you can force continuations to execute either on the foreground context for UI code, or background context for expensive non-UI code. You can use the `promise.ConfigureAwait(ContinuationOptions)` or `promise.ConfigureContinuation(ContinuationOptions)` APIs to force the continuation behavior.

```cs
async void Func()
{
// Not sure what thread we're on here...
await DoSomethingAsync()
.WaitAsync(SynchronizationOption.Background);
.ConfigureAwait(ContinuationOptions.Background);
// Now we're executing in the background.
Console.Log("Thread is background: " + Thread.CurrentThread.IsBackground); // true
await DoSomethingElseAsync()
.WaitAsync(SynchronizationOption.Foreground);
.ConfigureAwait(ContinuationOptions.Foreground);
// Now we're executing in the foreground (UI thread).
Console.Log("Thread is background: " + Thread.CurrentThread.IsBackground); // false
}
Expand All @@ -24,14 +24,14 @@ void Func()
{
// Not sure what thread we're on here...
DoSomethingAsync()
.WaitAsync(SynchronizationOption.Background)
.ConfigureContinuation(ContinuationOptions.Background)
.Then(() =>
{
// Now we're executing in the background.
Console.Log("Thread is background: " + Thread.CurrentThread.IsBackground); // true
return DoSomethingElseAsync();
}
.WaitAsync(SynchronizationOption.Foreground)
.ConfigureContinuation(ContinuationOptions.Foreground)
.Then(() =>
{
// Now we're executing in the foreground (UI thread).
Expand All @@ -45,8 +45,8 @@ To make things a little easier, there are shortcut functions to simply hop to th

The `Foreground` option posts the continuation to `Promise.Config.ForegroundContext`. This property is set automatically in Unity, but in other UI frameworks it should be set at application startup (usually `Promise.Config.ForegroundContext = SynchronizationContext.Current` is enough).

If your application uses multiple `SynchronizationContext`s, instead of using `SynchronizationOption.Foreground`, you should pass the proper `SynchronizationContext` directly to `WaitAsync` or `Promise.SwitchToContext`.
If your application uses multiple `SynchronizationContext`s, instead of using `SynchronizationOption.Foreground`, you may want to pass the proper `SynchronizationContext` directly to `Promise.SwitchToContext`, or `ContinuationOptions.CapturedContext` to `Promise.ConfigureAwait`.

For context switching optimized for async/await, use `Promise.SwitchToForegroundAwait`, `Promise.SwitchToBackgroundAwait`, and `Promise.SwitchToContextAwait`. These functions return custom awaiters that avoid the overhead of `Promise`.

Other APIs that allow you to pass `SynchronizationOption` or `SynchronizationContext` to configure the context that the callback executes on are `Progress.New` (default `Foreground`), `Promise.New` (default `Synchronous`), and `Promise.Run` (default `Background`).
Other APIs that allow you to pass `SynchronizationOption` or `SynchronizationContext` to configure the context that the callback executes on are `Progress.New` (default `CapturedContext`), `Promise.New` (default `Synchronous`), and `Promise.Run` (default `Background`).
6 changes: 4 additions & 2 deletions Package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ See the [C# Asynchronous Benchmarks Repo](https://github.com/timcassell/CSharpAs

## Latest Updates

### v3.1.1 - August 16, 2024
### v3.2.0 - November 3, 2024

- Fixed a race condition with `Promise.AsValueTask()`.
- Added Channels.
- Added `Promise(<T>).{ConfigureAwait, ConfigureContinuation}` APIs.
- Added `SynchronizationOption.CapturedContext` option.

See [ChangeLog](https://github.com/timcassell/ProtoPromise/tree/master/Docs/Changelog) for the full changelog.

Expand Down
2 changes: 1 addition & 1 deletion Package/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "com.timcassell.protopromise",
"version": "3.1.1",
"version": "3.2.0",
"unity": "2018.3",
"displayName": "ProtoPromise",
"description": "Robust and efficient library for management of asynchronous operations.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<!--We target .Net Standard 2.0 to support old Unity versions, and we also target .Net Standard 2.1 to use function pointers.-->
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<Version>3.1.1</Version>
<Version>3.2.0</Version>
<!--In case any IL2CPP issues need to be resolved like in the core library.-->
<DefineConstants>$(DefineConstants);ENABLE_IL2CPP</DefineConstants>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>netstandard2.1</TargetFrameworks>
<Version>3.1.1</Version>
<Version>3.2.0</Version>
<!-- The language version Unity supports in 2023.1. -->
<LangVersion>9</LangVersion>
<!--In case any IL2CPP issues need to be resolved like in the core library.-->
Expand Down
2 changes: 1 addition & 1 deletion ProtoPromise/ProtoPromise.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<Version>3.1.1</Version>
<Version>3.2.0</Version>
<!--Set true to help debug internal promise code (allows the debugger to step into the code and includes internal stacktraces).-->
<DeveloperMode>false</DeveloperMode>
</PropertyGroup>
Expand Down

0 comments on commit f5cb851

Please sign in to comment.