Skip to content

Commit

Permalink
Merge branch 'release/0.9.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
Arvtesh committed May 25, 2018
2 parents 7edb5bf + c8d7b23 commit dd9a903
Show file tree
Hide file tree
Showing 60 changed files with 1,315 additions and 802 deletions.
63 changes: 0 additions & 63 deletions .gitattributes

This file was deleted.

File renamed without changes.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md → .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Introduction
# Contributing guide

First off, thank you for considering contributing to UnityFx. It's people like you that make UnityFx such a great tool. Feel welcome and read the following sections in order to know what and how to work on something. If you get stuck at any point you can create a [ticket on GitHub](https://github.com/Arvtesh/UnityFx.Async/issues).

Expand Down
8 changes: 8 additions & 0 deletions .github/SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Support guide

First of all thank you for using *UnityFx.Async*.

For **help**, **support**, **questions** and **ideas** please use **[Unity forums thread](https://forum.unity.com/threads/asynchronous-operations-for-unity-free.522989/)**.
Please **_do not_** raise an issue on GitHub.

You can get general information on the library and answers to frequently asked questions in [README](../README.md).
12 changes: 0 additions & 12 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Pp]rojectSettings/
[Pp]ackages/
[Bb]in/
[Bb]uild/
[Bb]uilds/
Expand All @@ -14,11 +12,6 @@
.vscode/
_site/

# UnityApps
/AssetStore/UnityPackage35/*.*
/AssetStore/UnityPackage46/*.*
/Tests/UnityTests/*.*

# Autogenerated VS/MD/Consulo solution and project files
.consulo/
*.unityproj
Expand All @@ -36,8 +29,3 @@ _site/

# Unity3D Generated File On Crash Reports
sysinfo.txt

# Builds
*.ipa
*.apk
*.unitypackage
1 change: 1 addition & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[submodule "src/CodingConventions"]
path = src/CodingConventions
url = https://github.com/Arvtesh/CodingConventions

3 changes: 2 additions & 1 deletion BuildDocs.bat
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
powershell .\BuildDocs.ps1
powershell .\src\Build.ps1 Release
powershell .\src\BuildDocs.ps1
2 changes: 0 additions & 2 deletions BuildDocs.ps1

This file was deleted.

19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/); this project adheres to [Semantic Versioning](http://semver.org/).

-----------------------
## [0.9.2] - Unreleased
## [0.9.3] - unreleased

-----------------------
## [0.9.2] - 2018.05.25

### Added
- Added pull-based progress support (`IAsyncOperation.Progress`).
- Added new methods to `IAsyncUpdateSource`.
- Added `AsyncUpdateSource` class as default `IAsyncUpdateSource` implementation.
- `IAsyncOperation<T>` now inherits `IObservable<T>`.

### Changed
- Renamed `(Try)AddCompletionCallback`/`RemoveCompletionCallback` methods to `(Try)AddContinuation`/`RemoveContinuation`.
- Changed `IAsyncOperation.Exception` type to `Exception`.
- Changed `IAsyncOperationEvents.Completed` type to `AsyncCompletedEventHandler`.

### Removed
- Removed `ToObservable` extension of `IAsyncOperation`.

-----------------------
## [0.9.1] - 2018.05.07
Expand Down
52 changes: 34 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Channel | UnityFx.Async |
AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/hfmq9vow53al7tpd/branch/master?svg=true)](https://ci.appveyor.com/project/Arvtesh/unityfx-async/branch/master) [![AppVeyor tests](https://img.shields.io/appveyor/tests/Arvtesh/unityFx-async.svg)](https://ci.appveyor.com/project/Arvtesh/unityfx-async/build/tests)
NuGet | [![NuGet](https://img.shields.io/nuget/v/UnityFx.Async.svg)](https://www.nuget.org/packages/UnityFx.Async)
Github | [![GitHub release](https://img.shields.io/github/release/Arvtesh/UnityFx.Async.svg?logo=github)](https://github.com/Arvtesh/UnityFx.Async/releases)
Unity Asset Store | [![Asynchronous operations for Unity](https://img.shields.io/badge/tools-v0.9.1-green.svg)](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696)
Unity Asset Store | [![Asynchronous operations for Unity](https://img.shields.io/badge/tools-v0.9.2-green.svg)](https://assetstore.unity.com/packages/tools/asynchronous-operations-for-unity-96696)

## Synopsis

Expand All @@ -30,6 +30,7 @@ The table below summarizes differences berween *UnityFx.Async* and other popular
| Supports `async` / `await` | ✔️ | - | ✔️ |
| Supports `promise`-like continuations | ✔️ | ✔️ | - |
| Supports cancellation | ✔️ | -️ | ✔️ |
| Supports progress reporting | ✔️ | ✔️ | ✔️ |
| Supports child operations | - | - | ✔️ |
| Minimum operation data size for 32-bit systems (in bytes) | 28+ | 36+ | 40+ |
| Minimum number of allocations per continuation | 1+ | 5+ | 2+ |
Expand Down Expand Up @@ -167,6 +168,11 @@ var op = new AsyncCompletionSource<string>();
```
The type of the operation should reflect its result type. In this case we have created a special kind of operation - a completion source that incapsulated both producer and consumer interfaces (consumer side is represented via `IAsyncOperation` / `IAsyncOperation<TResult>` interfaces and producer side is `IAsyncCompletionSource` / `IAsyncCompletionSource<TResult>`, `AsyncCompletionSource` implements both of the interfaces).

While operation is running its progress can be set as:
```csharp
op.SetProgress(progressValue);
```

Upon completion of an asynchronous operation transition it to one of the final states (`RanToCompletion`, `Faulted` or `Canceled`):
```csharp
op.SetResult(resultValue);
Expand Down Expand Up @@ -272,24 +278,24 @@ DownloadTextAsync("http://www.google.com")
.Catch(e => Debug.LogException(e))
.Finally(() => Debug.Log("Done"));
```
The chain of processing ends as soon as an exception occurs. In this case when an error occurs the `Catch` handler would be called.
The chain of processing ends as soon as an exception occurs. In this case when an error occurs the `Catch()` handler would be called.

`Then` continuations get executed only if previous operation in the chain completed successfully. Otherwise, they are skipped. Note that `Then` expects the handler return value to be another operation.
`Then()` continuations get executed only if previous operation in the chain completed successfully. Otherwise, they are skipped. Note that `Then()` expects the handler return value to be another operation.

`Rebind` is a special kind of continuation for transforming operation result to a different type:
`Rebind()` is a special kind of continuation for transforming operation result to a different type:
```csharp
DownloadTextAsync("http://www.google.com")
.Then(text => ExtractFirstUrl(text))
.Rebind(url => new Url(url));
```
`ContinueWith` and `Finally` delegates get called independently of the antecedent operation result. `ContinueWith` also define overloads accepting `AsyncContinuationOptions` argument that allows to customize its behaviour. Note that `ContinueWith` is analog to the corresponding [Task method](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.continuewith) and not a part of the JS promise pattern:
`ContinueWith()` and `Finally()` delegates get called independently of the antecedent operation result. `ContinueWith()` also define overloads accepting `AsyncContinuationOptions` argument that allows to customize its behaviour. Note that `ContinueWith()` is analog to the corresponding [Task method](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.continuewith) and not a part of the JS promise pattern:
```csharp
DownloadTextAsync("http://www.google.com")
.ContinueWith(op => Debug.Log("1"))
.ContinueWith(op => Debug.Log("2"), AsyncContinuationOptions.NotOnCanceled)
.ContinueWith(op => Debug.Log("3"), AsyncContinuationOptions.OnlyOnFaulted);
```
`Done` acts like a combination of `Catch` and `Finally`. It should always be the last element of the chain:
`Done()` acts like a combination of `Catch()` and `Finally()`. It should always be the last element of the chain:
```csharp
DownloadTextAsync("http://www.google.com")
.Then(text => ExtractFirstUrl(text))
Expand All @@ -315,20 +321,27 @@ finally
```

### Cancellation
All library operations can be cancelled using `Cancel` method:
All library operations can be cancelled using `Cancel()` method:
```csharp
op.Cancel();
op.Cancel(); // attempts to cancel an operation
```
Or with `WithCancellation` extension:
Or with `WithCancellation()` extension:
```csharp
DownloadTextAsync("http://www.google.com")
.Then(text => ExtractFirstParagraph(text))
.WithCancellation(cancellationToken);
```
If the [token](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken) passed to `WithCancellation` is cancelled the target operation is cancelled as well (and that means cancelling all chained operations) as soon as possible. Cancellation might not be instant (depends on specific operation implementation). Also, please note that not all operations might support cancellation; in this case `Cancel` will throw `NotSupportedException`.
If the [token](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken) passed to `WithCancellation()` is cancelled the target operation is cancelled as well (and that means cancelling all chained operations) as soon as possible. Cancellation might not be instant (depends on specific operation implementation). Also, please note that not all operations might support cancellation; in this case `Cancel()` will throw `NotSupportedException`.

### Progress reporting
Library operations support progress reporting via exposing `IAsyncOperation.Progress` property:
```csharp
var progress = op.Progess; // gets an operation progress as a float value in range [0, 1]
```
There is `AsyncResult.GetProgress()` virtual method that is called when a progress values is requested. Finally there are producer-side methods like `AsyncCompletionSource.TrySetProgress()` that can set the progress value.

### Synchronization context capturing
The default behaviour of all library methods is to capture current [SynchronizationContext](https://docs.microsoft.com/en-us/dotnet/api/system.threading.synchronizationcontext) and try to schedule continuations on it. If there is no synchronization context attached to current thread, continuations are executed on a thread that initiated an operation completion. The same behaviour applies to `async` / `await` implementation unless explicitly overriden with `ConfigureAwait`:
The default behaviour of all library methods is to capture current [SynchronizationContext](https://docs.microsoft.com/en-us/dotnet/api/system.threading.synchronizationcontext) and try to schedule continuations on it. If there is no synchronization context attached to current thread, continuations are executed on a thread that initiated an operation completion. The same behaviour applies to `async` / `await` implementation unless explicitly overriden with `ConfigureAwait()`:
```csharp
// thread1
await DownloadTextAsync("http://www.google.com");
Expand All @@ -342,9 +355,9 @@ Completion callbacks are basicly low-level continuations. Just like continuation
```csharp
var op = DownloadTextAsync("http://www.google.com");
op.Completed += o => Debug.Log("1");
op.AddCompletionCallback(o => Debug.Log("2"));
op.AddContinuation(o => Debug.Log("2"));
```
That said, unlike `ContinueWith`-like stuff completion callbacks cannot be chained and do not handle exceptions automatically. Throwing an exception from a completion callback results in unspecified behavior.
That said, unlike `ContinueWith()`-like stuff completion callbacks cannot be chained and do not handle exceptions automatically. Throwing an exception from a completion callback results in unspecified behavior.

There are also non-delegate completion callbacks (`IAsyncContinuation`):
```csharp
Expand All @@ -360,9 +373,9 @@ op.AddContinuation(new MyContinuation());
```

### Disposing of operations
All operations implement [IDisposable](https://docs.microsoft.com/en-us/dotnet/api/system.idisposable) interface. So strictly speaking users should call `Dispose` when an operation is not in use. That said library implementation only requires this if `AsyncWaitHandle` was accessed (just like [tasks](https://blogs.msdn.microsoft.com/pfxteam/2012/03/25/do-i-need-to-dispose-of-tasks/)).
All operations implement [IDisposable](https://docs.microsoft.com/en-us/dotnet/api/system.idisposable) interface. So strictly speaking users should call `Dispose()` when an operation is not in use. That said library implementation only requires this if `AsyncWaitHandle` was accessed (just like [tasks](https://blogs.msdn.microsoft.com/pfxteam/2012/03/25/do-i-need-to-dispose-of-tasks/)).

Please note that `Dispose` implementation is NOT thread-safe and can only be called after an operation has completed (the same restrictions apply to [Task](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task)).
Please note that `Dispose()` implementation is NOT thread-safe and can only be called after an operation has completed (the same restrictions apply to [Task](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task)).

### Completed asynchronous operations
There are a number of helper methods for creating completed operations:
Expand All @@ -374,11 +387,13 @@ var op4 = AsyncResult.FromException(new Exception());
var op5 = AsyncResult.FromCanceled();
```

### Reactive programming support
`IAsyncOperation<T>` inherits `IObservable<T>` which makes it usable just like any other data stream.

### Convertions
Library defines convertion methods between `IAsyncOperation` and `Task`, `IObservable`, `UnityWebRequest`, `AsyncOperation`, `WWW` with corresponding extension methods:
```csharp
var task = op.ToTask();
var observable = op.ToObservable();

var op1 = task.ToAsync();
var op2 = observable.ToAsync();
Expand All @@ -388,7 +403,7 @@ var op5 = unityWWW.ToAsync();
```

### Creating own asynchronous operations
Most common way of creating own asynchronous operation is instantiating `AsyncCompletionSource` instance and call `SetResult` / `SetException` / `SetCanceled` when done. Still there are cases when more control is required. For this purpose the library provides two public extendable implementations for asynchronous operations:
Most common way of creating own asynchronous operation is instantiating `AsyncCompletionSource` instance and call `SetResult()` / `SetException()` / `SetCanceled()` when done. Still there are cases when more control is required. For this purpose the library provides two public extendable implementations for asynchronous operations:
* `AsyncResult`: a generic asynchronous operation without a result value.
* `AsyncResult<TResult>`: an asynchronous operation with a result value.

Expand Down Expand Up @@ -464,6 +479,7 @@ Please see the links below for extended information on the product:
- [Documentation](https://arvtesh.github.io/UnityFx.Async/articles/intro.html).
- [API Reference](https://arvtesh.github.io/UnityFx.Async/api/index.html).
- [CHANGELOG](CHANGELOG.md).
- [SUPPORT](.github/SUPPORT.md).

## Useful links
- [Task-based Asynchronous Pattern (TAP)](https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap).
Expand All @@ -477,7 +493,7 @@ Please see the links below for extended information on the product:

## Contributing

Please see [contributing guide](CONTRIBUTING.md) for details.
Please see [contributing guide](.github/CONTRIBUTING.md) for details.

## Versioning

Expand Down
Loading

0 comments on commit dd9a903

Please sign in to comment.