-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLongDataOperation.cs
106 lines (87 loc) · 2.8 KB
/
LongDataOperation.cs
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Agni.MDB
{
/// <summary>
/// Gets called by various routines that report long-running data operation progress and allow to cancel further processing.
/// </summary>
public delegate void LongDataOperationCallback<TResult>(LongDataOperation<TResult> operation);
/// <summary>
/// Provides a context for long data operation, such as fetching data from many shards.
/// Callers may cancel operation and track overall progress via a LongDataOperationCallback.
/// This is conceptually similar to CancelationToken
/// </summary>
public sealed class LongDataOperation<TResult>
{
public LongDataOperation()
{
m_StartTimeUTC = NFX.App.TimeSource.UTCNow;
}
private DateTime m_StartTimeUTC;
private volatile int m_Total;
private int m_Current;
private volatile bool m_Canceled;
private volatile bool m_HasResult;
private TResult m_Result;
/// <summary>
/// Allows to attach arbitrary object context
/// </summary>
public object Context;
/// <summary>
/// Returns the UTC timestamp of this operation
/// </summary>
public DateTime StartTimeUTC{ get{ return m_StartTimeUTC;} }
/// <summary>
/// The total amount of work
/// </summary>
public int Total{ get{return m_Total;}}
/// <summary>
/// The current progress of work out of Total
/// </summary>
public int Current{ get{ return Thread.VolatileRead(ref m_Current);} }
/// <summary>
/// True if operation was canceled via Cancel()
/// </summary>
public bool Canceled { get{ return m_Canceled;}}
/// <summary>
/// True if operation was completed via a call to SetResult()
/// </summary>
public bool HasResult { get{ return m_HasResult;}}
/// <summary>
/// The final result of operation which is available after completion or cancel
/// </summary>
public TResult Result{ get{ return m_Result;}}
/// <summary>
/// Sets total amount of work
/// </summary>
public void SetTotal(int total){ m_Total = total;}
/// <summary>
/// Sets current progress out of total
/// </summary>
public void SetCurrent(int current){ m_Current = current;}
/// <summary>
/// Sets current progress by +1 via interlocked
/// </summary>
public int AdvanceCurrent()
{
return Interlocked.Increment(ref m_Current);
}
/// <summary>
/// Call to cancel the further processing
/// </summary>
public void Cancel() { m_Canceled = true; }
/// <summary>
/// Call to set result
/// </summary>
public void SetResult(TResult result)
{
m_HasResult = true;
m_Result = result;
Thread.MemoryBarrier();
}
}
}