forked from luteberget/simcpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample-resource.cpp
150 lines (115 loc) · 3.58 KB
/
example-resource.cpp
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
// Copyright © 2021 Felix Schütz
// Licensed under the MIT license. See the LICENSE file for details.
#include <cmath>
#include <cstdio>
#include <queue>
#include "simcpp.h"
double expovariate(double lambda) {
double u = rand() / (RAND_MAX + 1.0);
return -log(1 - u) / lambda;
}
class Resource {
public:
Resource(simcpp::SimulationPtr sim, int capacity)
: sim(sim), capacity(capacity) {}
simcpp::EventPtr request() {
auto request = sim.lock()->event();
request_queue.push(request);
trigger_requests();
return request;
}
void release() {
++capacity;
trigger_requests();
}
int get_queue_length() { return request_queue.size(); }
private:
std::queue<simcpp::EventPtr> request_queue = {};
simcpp::SimulationWeakPtr sim;
int capacity;
void trigger_requests() {
while (capacity > 0 && request_queue.size() > 0) {
auto request = request_queue.front();
request_queue.pop();
if (!request->is_pending()) {
continue;
}
--capacity;
request->trigger();
}
}
};
using ResourcePtr = std::shared_ptr<Resource>;
class Customer : public simcpp::Process {
public:
Customer(simcpp::SimulationPtr sim, double mean_time_in_bank,
double max_wait_time, ResourcePtr counters, int id)
: Process(sim), mean_time_in_bank(mean_time_in_bank),
max_wait_time(max_wait_time), counters(counters), id(id) {}
bool Run() override {
auto sim = this->sim.lock();
PT_BEGIN();
printf("[%5.2f] Customer %d arrives\n", sim->get_now(), id);
request = counters->request();
PROC_WAIT_FOR(sim->any_of({request, sim->timeout(max_wait_time)}));
if (!request->is_triggered()) {
request->abort();
printf("[%5.2f] Customer %d leaves unhappy\n", sim->get_now(), id);
PT_EXIT();
}
printf("[%5.2f] Customer %d gets to the counter\n", sim->get_now(), id);
PROC_WAIT_FOR(sim->timeout(expovariate(1 / mean_time_in_bank)));
printf("[%5.2f] Customer %d leaves\n", sim->get_now(), id);
counters->release();
PT_END();
}
private:
simcpp::EventPtr request = nullptr;
double mean_time_in_bank;
double max_wait_time;
ResourcePtr counters;
int id;
};
class CustomerSource : public simcpp::Process {
public:
CustomerSource(simcpp::SimulationPtr sim, int n_customers,
double mean_arrival_interval, double mean_time_in_bank,
double max_wait_time, ResourcePtr counters)
: Process(sim), n_customers(n_customers),
mean_arrival_interval(mean_arrival_interval),
mean_time_in_bank(mean_time_in_bank), max_wait_time(max_wait_time),
counters(counters) {}
bool Run() override {
auto sim = this->sim.lock();
PT_BEGIN();
while (next_id <= n_customers) {
sim->start_process<Customer>(mean_time_in_bank, max_wait_time, counters,
next_id);
++next_id;
PROC_WAIT_FOR(sim->timeout(expovariate(1 / mean_arrival_interval)));
}
PT_END();
}
private:
int next_id = 1;
int n_customers;
double mean_arrival_interval;
double mean_time_in_bank;
double max_wait_time;
ResourcePtr counters;
};
int main() {
int n_customers = 10;
double mean_arrival_interval = 10.0;
double mean_time_in_bank = 12.0;
double max_wait_time = 16.0;
int n_counters = 1;
srand(0);
auto sim = simcpp::Simulation::create();
auto counters = std::make_shared<Resource>(sim, n_counters);
auto customer_source = sim->start_process<CustomerSource>(
n_customers, mean_arrival_interval, mean_time_in_bank, max_wait_time,
counters);
sim->run();
return 0;
}