My favorites | Sign in
Project Home Downloads Wiki Issues Source
Checkout   Browse   Changes    
 
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
using System;
using System.Collections.Generic;
using System.Linq;

namespace Retlang.Fibers
{
/// <summary>
/// StubFiber does not use a backing thread or a thread pool for execution. Actions are added to pending
/// lists for execution. These actions can be executed synchronously by the calling thread. This class
/// is not thread safe and should not be used in production code.
///
/// The class is typically used for testing asynchronous code to make it completely synchronous and
/// deterministic.
/// </summary>
public class StubFiber : IFiber
{
private readonly List<IDisposable> _subscriptions = new List<IDisposable>();
private readonly List<Action> _pending = new List<Action>();
private readonly List<StubScheduledAction> _scheduled = new List<StubScheduledAction>();

private bool _root = true;

/// <summary>
/// No Op
/// </summary>
public void Start()
{}

/// <summary>
/// Clears all subscriptions, scheduled, and pending actions.
/// </summary>
public void Dispose()
{
_scheduled.ToList().ForEach(x => x.Dispose());
_subscriptions.ToList().ForEach(x => x.Dispose());
_pending.Clear();
}

/// <summary>
/// Enqueue a single action.
/// </summary>
/// <param name="action"></param>
public void Enqueue(Action action)
{
if (_root && ExecutePendingImmediately)
{
try
{
_root = false;
action();
ExecuteAllPendingUntilEmpty();
}
finally
{
_root = true;
}
}
else
{
_pending.Add(action);
}
}

///<summary>
/// Register subscription to be unsubcribed from when the fiber is disposed.
///</summary>
///<param name="toAdd"></param>
public void RegisterSubscription(IDisposable toAdd)
{
_subscriptions.Add(toAdd);
}

///<summary>
/// Deregister a subscription.
///</summary>
///<param name="toRemove"></param>
///<returns></returns>
public bool DeregisterSubscription(IDisposable toRemove)
{
return _subscriptions.Remove(toRemove);
}

///<summary>
/// Number of subscriptions.
///</summary>
public int NumSubscriptions
{
get { return _subscriptions.Count; }
}

/// <summary>
/// Adds a scheduled action to the list.
/// </summary>
/// <param name="action"></param>
/// <param name="firstInMs"></param>
/// <returns></returns>
public IDisposable Schedule(Action action, long firstInMs)
{
var toAdd = new StubScheduledAction(action, firstInMs, _scheduled);
_scheduled.Add(toAdd);
return toAdd;
}

/// <summary>
/// Adds scheduled action to list.
/// </summary>
/// <param name="action"></param>
/// <param name="firstInMs"></param>
/// <param name="regularInMs"></param>
/// <returns></returns>
public IDisposable ScheduleOnInterval(Action action, long firstInMs, long regularInMs)
{
var toAdd = new StubScheduledAction(action, firstInMs, regularInMs, _scheduled);
_scheduled.Add(toAdd);
return toAdd;
}

/// <summary>
/// All subscriptions.
/// </summary>
public List<IDisposable> Subscriptions
{
get { return _subscriptions; }
}

/// <summary>
/// All pending actions.
/// </summary>
public List<Action> Pending
{
get { return _pending; }
}

/// <summary>
/// All scheduled actions.
/// </summary>
public List<StubScheduledAction> Scheduled
{
get { return _scheduled; }
}

/// <summary>
/// If true events will be executed immediately rather than added to the pending list.
/// </summary>
public bool ExecutePendingImmediately { get; set; }

/// <summary>
/// Execute all actions in the pending list. If any of the executed actions enqueue more actions, execute those as well.
/// </summary>
public void ExecuteAllPendingUntilEmpty()
{
while (_pending.Count > 0)
{
var toExecute = _pending[0];
_pending.RemoveAt(0);
toExecute();
}
}

/// <summary>
/// Execute all actions in the pending list.
/// </summary>
public void ExecuteAllPending()
{
var copy = _pending.ToArray();
_pending.Clear();
foreach (var pending in copy)
{
pending();
}
}

/// <summary>
/// Execute all actions in the scheduled list.
/// </summary>
public void ExecuteAllScheduled()
{
foreach (var scheduled in _scheduled.ToArray())
{
scheduled.Execute();
}
}
}
}

Change log

r418 by graham.m.nash on Sep 29, 2010   Diff
Added test for StubFiber.Dispose
Go to: 
Project members, sign in to write a code review

Older revisions

r417 by graham.m.nash on Sep 29, 2010   Diff
Added yield to BusyWaitQueue to fix
performance problem
Added test to confirm BusyWaitQueue
low latency
Clear all data on StubFiber::Dispose
...
r408 by graham.m.nash on Sep 7, 2010   Diff
Documentation fixes
r401 by graham.m.nash on Sep 3, 2010   Diff
Added BusyWaitQueue
Extracted DefaultQueue from
BoundedQueue and made DefaultQueue
default in ThreadFiber
Various renames/removals of redundant
...
All revisions of this file

File info

Size: 5642 bytes, 184 lines
Powered by Google Project Hosting