Skip to content

Commit 721ce01

Browse files
authored
Allow access to the list of created resources.
1 parent 1382e3b commit 721ce01

File tree

7 files changed

+134
-106
lines changed

7 files changed

+134
-106
lines changed

CHANGELOG.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.0
2+
3+
* Access the list of created resources.
4+
15
## 0.2.0
26

37
* Setting to determine how often `Future.delayed` is used instead of `Future.microtask` during event execution to allow GUI refresh.
@@ -8,8 +12,8 @@
812
## 0.1.0
913

1014
* Initial release
11-
* Discrete event processing
12-
* Event scheduling, execution, waiting, and repetition
13-
* Intervals management
15+
* Discrete event processing.
16+
* Event scheduling, execution, waiting, and repetition.
17+
* Intervals management.
1418
* Resources
1519
* Capacity limit

lib/simdart.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export 'src/event.dart';
22
export 'src/interval.dart';
33
export 'src/observable.dart';
4-
export 'src/resources.dart' hide ResourcesFactory;
4+
export 'src/resources.dart' hide ResourcesFactory, ResourceStore;
55
export 'src/simdart.dart' hide SimDartHelper;
66
export 'src/simulation_track.dart';
77
export 'src/start_time_handling.dart';

lib/src/internal/resource.dart

Lines changed: 0 additions & 50 deletions
This file was deleted.

lib/src/resources.dart

Lines changed: 114 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,126 @@
1+
import 'dart:collection';
2+
13
import 'package:meta/meta.dart';
24
import 'package:simdart/src/internal/completer_action.dart';
35
import 'package:simdart/src/internal/event_action.dart';
4-
import 'package:simdart/src/internal/resource.dart';
56
import 'package:simdart/src/simdart.dart';
67
import 'package:simdart/src/simulation_track.dart';
78

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+
887
class Resources {
9-
Resources._(SimDart sim) : _sim = sim;
88+
Resources._(SimDart sim)
89+
: _sim = sim,
90+
_store = SimDartHelper.resourceStore(sim: sim);
1091

1192
final SimDart _sim;
93+
final ResourceStore _store;
94+
95+
List<Resource> get all => _store._unmodifiableList;
96+
97+
int get length => _store._map.length;
1298

1399
/// Creates a resource with limited capacity.
14100
///
15101
/// This method adds a resource with the specified capacity.
16102
/// The resource will be configured as limited, meaning it will have a maximum
17103
/// capacity defined by the [capacity] parameter.
18104
///
19-
/// - [id]: The unique identifier of the resource (required).
105+
/// - [name]: The unique name of the resource (required).
20106
/// - [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;
26116
}
27117

28118
/// Checks if a resource is available.
29119
///
30-
/// - [id]: The id of the resource to check.
120+
/// - [name]: The name of the resource to check.
31121
/// - 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];
34124
if (resource != null) {
35125
return resource.isAvailable();
36126
}
@@ -47,10 +137,10 @@ class ResourcesContext extends Resources {
47137

48138
/// Tries to acquire a resource immediately.
49139
///
50-
/// - [id]: The id of the resource to acquire.
140+
/// - [name]: The name of the resource to acquire.
51141
/// - 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];
54144
if (resource != null) {
55145
return resource.acquire(_event);
56146
}
@@ -59,17 +149,17 @@ class ResourcesContext extends Resources {
59149

60150
/// Acquires a resource, waiting if necessary until it becomes available.
61151
///
62-
/// - [id]: The id of the resource to acquire.
152+
/// - [name]: The name of the resource to acquire.
63153
/// - Returns: A [Future] that completes when the resource is acquired.
64-
Future<void> acquire(String id) async {
154+
Future<void> acquire(String name) async {
65155
if (_event.eventCompleter != null) {
66156
SimDartHelper.error(
67157
sim: _sim,
68158
msg:
69159
"This event should be waiting for the resource to be released. Did you forget to use 'await'?");
70160
return;
71161
}
72-
Resource? resource = SimDartHelper.getResource(sim: _sim, resourceId: id);
162+
_ResourceImpl? resource = _store._map[name];
73163
if (resource != null) {
74164
bool acquired = resource.acquire(_event);
75165
if (!acquired) {
@@ -78,23 +168,23 @@ class ResourcesContext extends Resources {
78168
sim: _sim, eventName: _event.eventName, status: Status.yielded);
79169
}
80170
_event.buildCompleter();
81-
resource.waiting.add(_event);
171+
resource._waiting.add(_event);
82172
SimDartHelper.scheduleNextAction(sim: _sim);
83173
await _event.eventCompleter!.future;
84-
return await acquire(id);
174+
return await acquire(name);
85175
}
86176
}
87177
}
88178

89179
/// Releases a previously acquired resource.
90180
///
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];
94184
if (resource != null) {
95185
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);
98188
// Schedule a complete to resume this event in the future.
99189
SimDartHelper.addAction(
100190
sim: _sim,

lib/src/simdart.dart

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import 'package:meta/meta.dart';
66
import 'package:simdart/src/event.dart';
77
import 'package:simdart/src/internal/event_action.dart';
88
import 'package:simdart/src/internal/repeat_event_action.dart';
9-
import 'package:simdart/src/internal/resource.dart';
109
import 'package:simdart/src/internal/simdart_interface.dart';
1110
import 'package:simdart/src/internal/time_action.dart';
1211
import 'package:simdart/src/interval.dart';
@@ -51,9 +50,7 @@ class SimDart implements SimDartInterface {
5150
final Map<String, SimNum> _numProperties = {};
5251
final Map<String, SimCounter> _counterProperties = {};
5352

54-
/// Holds the resources in the simulator.
55-
final Map<String, Resource> _resources = {};
56-
53+
final ResourceStore _resourceStore = ResourceStore();
5754
late final Resources resources = ResourcesFactory.sim(this);
5855

5956
/// The instance of the random number generator used across the simulation.
@@ -242,16 +239,12 @@ class SimDart implements SimDartInterface {
242239
}
243240

244241
void _addTrack({required String eventName, required Status status}) {
245-
Map<String, int> resourceUsage = {};
246-
for (Resource resource in _resources.values) {
247-
resourceUsage[resource.id] = resource.queue.length;
248-
}
249242
_tracks ??= [];
250243
_tracks!.add(SimulationTrack(
251244
status: status,
252245
name: eventName,
253246
time: now,
254-
resourceUsage: resourceUsage));
247+
resourceUsage: _resourceStore.usage()));
255248
}
256249

257250
Future<void> _consumeNextAction() async {
@@ -296,17 +289,8 @@ class SimDartHelper {
296289
sim._addAction(action);
297290
}
298291

299-
static Resource? getResource(
300-
{required SimDart sim, required String? resourceId}) {
301-
return sim._resources[resourceId];
302-
}
303-
304-
static void addResource(
305-
{required SimDart sim,
306-
required String resourceId,
307-
required Resource Function() create}) {
308-
sim._resources.putIfAbsent(resourceId, create);
309-
}
292+
static ResourceStore resourceStore({required SimDart sim}) =>
293+
sim._resourceStore;
310294

311295
static void addSimulationTrack(
312296
{required SimDart sim,

test/repeat_process_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void main() {
4747
test('Resource - acquire and wait', () async {
4848
SimDart sim = SimDart(includeTracks: true);
4949

50-
sim.resources.limited(id: 'r');
50+
sim.resources.limited(name: 'r');
5151

5252
sim.process(
5353
event: (context) async {
@@ -79,7 +79,7 @@ void main() {
7979
test('Resource', () async {
8080
SimDart sim = SimDart(includeTracks: true);
8181

82-
sim.resources.limited(id: 'r');
82+
sim.resources.limited(name: 'r');
8383

8484
sim.repeatProcess(
8585
event: (context) async {
@@ -113,7 +113,7 @@ void main() {
113113
test('Resource - stop', () async {
114114
SimDart sim = SimDart(includeTracks: true);
115115

116-
sim.resources.limited(id: 'r');
116+
sim.resources.limited(name: 'r');
117117

118118
sim.repeatProcess(
119119
event: (context) async {

0 commit comments

Comments
 (0)