forked from louthy/language-ext
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAsync.Module.cs
More file actions
91 lines (87 loc) · 4.2 KB
/
Copy pathAsync.Module.cs
File metadata and controls
91 lines (87 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using System;
using System.Threading;
using System.Threading.Tasks;
using LanguageExt.Common;
namespace LanguageExt.Async;
/// <summary>
/// The `Async` module helps transition away from the `Task` / `async` / `await` world and into one
/// where awaiting is the default setting for concurrent programming and branching/forking is the
/// thing we do the least.
///
/// The `Async.await` function will convert a `Task<A>` into an `A` by waiting for the `Task` to
/// complete; it will yield the thread whilst it's waiting (to play nice with other tasks in the
/// task-pool). This is just like the regular `await` keyword without all the ceremony and
/// colouring of methods.
///
/// `Async.fork` lifts a function into an IO monad, forks it, and then runs the IO monad returning
/// a `ForkIO` object. The forked operation continues to run in parallel. The `ForkIO` object
/// contains two properties: `Await` and `Cancel` that be used to either await the result or
/// cancel the operation.
///
/// These two functions remove the need for methods that are 'tainted' with `Task` or `async` /
/// `await` mechanics and assume that the thing we will do the most with asynchronous code is to
/// await it.
///
/// This module shouldn't be needed too much, as the IO monad is where most of the asynchrony
/// should be. But, when converting from existing async/await code, or if you're coming from
/// language-ext v4, or earlier, where there was lots of `*Async` methods in the key types, then
/// this module will help ease the transition.
/// </summary>
public static class Async
{
/// <summary>
/// Simple awaiter that yields the thread whilst waiting. Allows for the `Task` to
/// be used with synchronous code without blocking any threads for concurrent
/// processing.
/// </summary>
/// <param name="operation">Task to await</param>
/// <typeparam name="A">Bound value type</typeparam>
/// <returns>Result of the task, `TaskCanceledException`, or any exception raised by the task</returns>
/// <exception cref="TaskCanceledException"></exception>
public static A await<A>(Task<A> operation)
{
SpinWait sw = default;
while (true)
{
if (operation.IsCanceled)
{
throw new TaskCanceledException();
}
else if (operation.IsFaulted)
{
operation.Exception.Rethrow();
}
else if (operation.IsCompleted)
{
return operation.Result;
}
sw.SpinOnce();
}
}
/// <summary>
/// `Async.fork` lifts a function into an IO monad, forks it, and then runs the IO monad returning
/// the `ForkIO` object. The forked operation continues to run in parallel. The `ForkIO` object
/// contains two properties: `Await` and `Cancel` that be used to either await the result or
/// cancel the operation.
/// </summary>
/// <param name="operation">Operation to fork</param>
/// <param name="timeout">Optional timeout</param>
/// <typeparam name="A">Bound value type</typeparam>
/// <returns>The `ForkIO` object contains two properties: `Await` and `Cancel` that be used to either
/// await the result or cancel the operation.</returns>
public static ForkIO<A> fork<A>(Func<A> operation, TimeSpan timeout = default) =>
IO.lift(operation).ForkIO(timeout).Run();
/// <summary>
/// `Async.fork` lifts a function into an IO monad, forks it, and then runs the IO monad returning
/// the `ForkIO` object. The forked operation continues to run in parallel. The `ForkIO` object
/// contains two properties: `Await` and `Cancel` that be used to either await the result or
/// cancel the operation.
/// </summary>
/// <param name="operation">Operation to fork</param>
/// <param name="timeout">Optional timeout</param>
/// <typeparam name="A">Bound value type</typeparam>
/// <returns>The `ForkIO` object contains two properties: `Await` and `Cancel` that be used to either
/// await the result or cancel the operation.</returns>
public static ForkIO<A> fork<A>(Func<Task<A>> operation, TimeSpan timeout = default) =>
IO.liftAsync(operation).ForkIO(timeout).Run();
}