-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLock.cs
More file actions
97 lines (81 loc) · 3.22 KB
/
Copy pathLock.cs
File metadata and controls
97 lines (81 loc) · 3.22 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
92
93
94
95
96
97
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
namespace Screenplay
{
public class Lock
{
private readonly IPreconditionCollector _parentTracker;
// Need to split into two as a close might signal an open and vice versa
private readonly CancelableAutoResetEvent<int> _openEvent = new(), _closeEvent = new();
private readonly object _lock = new();
private int _counter;
public bool Open => _counter != 0;
public async UniTask WaitOpen(Cancellation cancellation)
{
if (Open)
return;
await _openEvent.NextSignal(cancellation);
}
public async UniTask WaitClosed(Cancellation cancellation)
{
if (Open == false)
return;
await _closeEvent.NextSignal(cancellation);
}
public Lock(IPreconditionCollector parentTracker, IList<Precondition> targets, out IPreconditionCollector[] preconditions)
{
_parentTracker = parentTracker;
preconditions = new IPreconditionCollector[targets.Count];
for (int i = 0; i < preconditions.Length; i++)
preconditions[i] = new Key(this, targets[i]);
}
private class Key : IPreconditionCollector
{
private readonly List<GlobalId> _lastAppliedLocals = new();
private readonly Lock _lock;
public bool IsUnlocked { get; private set; }
public ScreenplayGraph.Introspection Introspection => _lock._parentTracker.Introspection;
public Locals SharedLocals => _lock._parentTracker.SharedLocals;
public void SetUnlockedState(bool state, params GlobalId[] locals)
{
if (IsUnlocked == state)
return;
IsUnlocked = state;
lock (_lock._lock)
{
if (IsUnlocked)
{
foreach (var v in locals)
{
if (SharedLocals.TryAdd(v))
_lastAppliedLocals.Add(v);
}
}
else
{
foreach (var v in _lastAppliedLocals)
SharedLocals.Remove(v);
_lastAppliedLocals.Clear();
}
int previousCounter = _lock._counter;
_lock._counter += IsUnlocked ? 1 : -1;
if (previousCounter == 0 && _lock._counter == 1
|| previousCounter == 1 && _lock._counter == 0)
{
if (_lock.Open)
_lock._openEvent.Signal(0);
else
_lock._closeEvent.Signal(0);
}
}
}
public Key(Lock l, Precondition target)
{
_lock = l;
if (Introspection.Preconditions.TryGetValue(target, out var list) == false)
Introspection.Preconditions[target] = list = new();
list.Add(this);
}
}
}
}