1
+ import 'dart:collection' ;
2
+
1
3
import 'package:meta/meta.dart' ;
2
4
import 'package:simdart/src/internal/completer_action.dart' ;
3
5
import 'package:simdart/src/internal/event_action.dart' ;
4
- import 'package:simdart/src/internal/resource.dart' ;
5
6
import 'package:simdart/src/simdart.dart' ;
6
7
import 'package:simdart/src/simulation_track.dart' ;
7
8
9
+ @internal
10
+ class ResourceStore {
11
+ /// Holds the resources in the simulator.
12
+ final Map <String , _ResourceImpl > _map = {};
13
+ final List <_ResourceImpl > _list = [];
14
+ late final UnmodifiableListView <_ResourceImpl > _unmodifiableList =
15
+ UnmodifiableListView (_list);
16
+
17
+ Map <String , int > usage () {
18
+ Map <String , int > result = {};
19
+ for (_ResourceImpl resource in _map.values) {
20
+ result[resource.name] = resource._queue.length;
21
+ }
22
+ return result;
23
+ }
24
+ }
25
+
26
+ abstract interface class Resource {
27
+ String get name;
28
+ int get capacity;
29
+ bool isAvailable ();
30
+ }
31
+
32
+ abstract interface class LimitedResource extends Resource {}
33
+
34
+ abstract class _ResourceImpl implements Resource {
35
+ _ResourceImpl (
36
+ {required this .name,
37
+ required this .capacity,
38
+ required this .acquisitionRule});
39
+
40
+ @override
41
+ final String name;
42
+
43
+ @override
44
+ final int capacity;
45
+
46
+ final List <EventAction > _queue = [];
47
+ final bool Function (EventAction event)? acquisitionRule;
48
+
49
+ /// A queue that holds completer to resume events waiting for a resource to become available.
50
+ final List <EventAction > _waiting = [];
51
+
52
+ bool acquire (EventAction event);
53
+
54
+ bool release (SimDart sim, EventAction event);
55
+ }
56
+
57
+ class _LimitedResourceImpl extends _ResourceImpl implements LimitedResource {
58
+ _LimitedResourceImpl (
59
+ {required super .name,
60
+ required super .capacity,
61
+ required super .acquisitionRule});
62
+
63
+ @override
64
+ bool acquire (EventAction event) {
65
+ if (acquisitionRule != null && ! acquisitionRule !(event)) {
66
+ return false ;
67
+ }
68
+ if (isAvailable ()) {
69
+ _queue.add (event);
70
+ return true ;
71
+ }
72
+
73
+ return false ;
74
+ }
75
+
76
+ @override
77
+ bool release (SimDart sim, EventAction event) {
78
+ return _queue.remove (event);
79
+ }
80
+
81
+ @override
82
+ bool isAvailable () {
83
+ return _queue.length < capacity;
84
+ }
85
+ }
86
+
8
87
class Resources {
9
- Resources ._(SimDart sim) : _sim = sim;
88
+ Resources ._(SimDart sim)
89
+ : _sim = sim,
90
+ _store = SimDartHelper .resourceStore (sim: sim);
10
91
11
92
final SimDart _sim;
93
+ final ResourceStore _store;
94
+
95
+ List <Resource > get all => _store._unmodifiableList;
96
+
97
+ int get length => _store._map.length;
12
98
13
99
/// Creates a resource with limited capacity.
14
100
///
15
101
/// This method adds a resource with the specified capacity.
16
102
/// The resource will be configured as limited, meaning it will have a maximum
17
103
/// capacity defined by the [capacity] parameter.
18
104
///
19
- /// - [id ] : The unique identifier of the resource (required).
105
+ /// - [name ] : The unique name of the resource (required).
20
106
/// - [capacity] : The maximum capacity of the resource. The default value is 1.
21
- void limited ({required String id, int capacity = 1 }) {
22
- SimDartHelper .addResource (
23
- sim: _sim,
24
- resourceId: id,
25
- create: () => LimitedResource (id: id, capacity: capacity));
107
+ Resource limited ({required String name, int capacity = 1 }) {
108
+ _ResourceImpl ? resource = _store._map[name];
109
+ if (resource == null ) {
110
+ resource = _LimitedResourceImpl (
111
+ name: name, capacity: capacity, acquisitionRule: null );
112
+ _store._map[name] = resource;
113
+ _store._list.add (resource);
114
+ }
115
+ return resource;
26
116
}
27
117
28
118
/// Checks if a resource is available.
29
119
///
30
- /// - [id ] : The id of the resource to check.
120
+ /// - [name ] : The name of the resource to check.
31
121
/// - Returns: `true` if the resource is available, `false` otherwise.
32
- bool isAvailable (String id ) {
33
- Resource ? resource = SimDartHelper . getResource (sim : _sim, resourceId : id) ;
122
+ bool isAvailable (String name ) {
123
+ _ResourceImpl ? resource = _store._map[name] ;
34
124
if (resource != null ) {
35
125
return resource.isAvailable ();
36
126
}
@@ -47,10 +137,10 @@ class ResourcesContext extends Resources {
47
137
48
138
/// Tries to acquire a resource immediately.
49
139
///
50
- /// - [id ] : The id of the resource to acquire.
140
+ /// - [name ] : The name of the resource to acquire.
51
141
/// - Returns: `true` if the resource was acquired, `false` otherwise.
52
- bool tryAcquire (String id ) {
53
- Resource ? resource = SimDartHelper . getResource (sim : _sim, resourceId : id) ;
142
+ bool tryAcquire (String name ) {
143
+ _ResourceImpl ? resource = _store._map[name] ;
54
144
if (resource != null ) {
55
145
return resource.acquire (_event);
56
146
}
@@ -59,17 +149,17 @@ class ResourcesContext extends Resources {
59
149
60
150
/// Acquires a resource, waiting if necessary until it becomes available.
61
151
///
62
- /// - [id ] : The id of the resource to acquire.
152
+ /// - [name ] : The name of the resource to acquire.
63
153
/// - Returns: A [Future] that completes when the resource is acquired.
64
- Future <void > acquire (String id ) async {
154
+ Future <void > acquire (String name ) async {
65
155
if (_event.eventCompleter != null ) {
66
156
SimDartHelper .error (
67
157
sim: _sim,
68
158
msg:
69
159
"This event should be waiting for the resource to be released. Did you forget to use 'await'?" );
70
160
return ;
71
161
}
72
- Resource ? resource = SimDartHelper . getResource (sim : _sim, resourceId : id) ;
162
+ _ResourceImpl ? resource = _store._map[name] ;
73
163
if (resource != null ) {
74
164
bool acquired = resource.acquire (_event);
75
165
if (! acquired) {
@@ -78,23 +168,23 @@ class ResourcesContext extends Resources {
78
168
sim: _sim, eventName: _event.eventName, status: Status .yielded);
79
169
}
80
170
_event.buildCompleter ();
81
- resource.waiting .add (_event);
171
+ resource._waiting .add (_event);
82
172
SimDartHelper .scheduleNextAction (sim: _sim);
83
173
await _event.eventCompleter! .future;
84
- return await acquire (id );
174
+ return await acquire (name );
85
175
}
86
176
}
87
177
}
88
178
89
179
/// Releases a previously acquired resource.
90
180
///
91
- /// - [id ] : The id of the resource to release.
92
- void release (String id ) {
93
- Resource ? resource = SimDartHelper . getResource (sim : _sim, resourceId : id) ;
181
+ /// - [name ] : The name of the resource to release.
182
+ void release (String name ) {
183
+ _ResourceImpl ? resource = _store._map[name] ;
94
184
if (resource != null ) {
95
185
if (resource.release (_sim, _event)) {
96
- if (resource.waiting .isNotEmpty) {
97
- EventAction other = resource.waiting .removeAt (0 );
186
+ if (resource._waiting .isNotEmpty) {
187
+ EventAction other = resource._waiting .removeAt (0 );
98
188
// Schedule a complete to resume this event in the future.
99
189
SimDartHelper .addAction (
100
190
sim: _sim,
0 commit comments