|
@@ -34,115 +34,97 @@
|
|
|
#include <mutex>
|
|
|
#include <thread>
|
|
|
|
|
|
-namespace artis {
|
|
|
-namespace pdevs {
|
|
|
-namespace multithreading {
|
|
|
+namespace artis::pdevs::multithreading {
|
|
|
|
|
|
-template<class Time>
|
|
|
-struct start_message : common::Message
|
|
|
-{
|
|
|
+template<typename Time>
|
|
|
+struct start_message : common::Message {
|
|
|
explicit start_message(typename Time::type t)
|
|
|
- : _t(t)
|
|
|
- {}
|
|
|
+ : _t(t) {}
|
|
|
|
|
|
typename Time::type _t;
|
|
|
};
|
|
|
|
|
|
-template<class Time>
|
|
|
-struct transition_message : common::Message
|
|
|
-{
|
|
|
+template<typename Time>
|
|
|
+struct transition_message : common::Message {
|
|
|
explicit transition_message(typename Time::type t)
|
|
|
- : _t(t)
|
|
|
- {}
|
|
|
+ : _t(t) {}
|
|
|
|
|
|
typename Time::type _t;
|
|
|
};
|
|
|
|
|
|
-template<class Time>
|
|
|
-struct done_start_message : common::Message
|
|
|
-{
|
|
|
+template<typename Time>
|
|
|
+struct done_start_message : common::Message {
|
|
|
explicit done_start_message(typename Time::type tn,
|
|
|
- common::Model <Time> *child)
|
|
|
- :
|
|
|
- _tn(tn), _child(child)
|
|
|
- {}
|
|
|
+ common::Model<Time> *child)
|
|
|
+ :
|
|
|
+ _tn(tn), _child(child) {}
|
|
|
|
|
|
typename Time::type _tn;
|
|
|
- common::Model <Time> *_child;
|
|
|
+ common::Model<Time> *_child;
|
|
|
};
|
|
|
|
|
|
-template<class Time>
|
|
|
-struct done_transition_message : common::Message
|
|
|
-{
|
|
|
+template<typename Time>
|
|
|
+struct done_transition_message : common::Message {
|
|
|
explicit done_transition_message(typename Time::type tn,
|
|
|
- common::Model <Time> *child)
|
|
|
- :
|
|
|
- _tn(tn), _child(child)
|
|
|
- {}
|
|
|
+ common::Model<Time> *child)
|
|
|
+ :
|
|
|
+ _tn(tn), _child(child) {}
|
|
|
|
|
|
typename Time::type _tn;
|
|
|
- common::Model <Time> *_child;
|
|
|
+ common::Model<Time> *_child;
|
|
|
};
|
|
|
|
|
|
-struct Queues
|
|
|
-{
|
|
|
- std::shared_ptr <common::MessageQueue> child_queue;
|
|
|
- std::shared_ptr <common::MessageQueue> parent_queue;
|
|
|
+struct Queues {
|
|
|
+ std::shared_ptr<common::MessageQueue> child_queue;
|
|
|
+ std::shared_ptr<common::MessageQueue> parent_queue;
|
|
|
std::mutex mutex;
|
|
|
std::condition_variable condition;
|
|
|
|
|
|
- Queues() : child_queue(new common::MessageQueue), parent_queue(new common::MessageQueue)
|
|
|
- {}
|
|
|
+ Queues() : child_queue(new common::MessageQueue), parent_queue(new common::MessageQueue) {}
|
|
|
|
|
|
- bool empty() const
|
|
|
- { return child_queue->empty() and parent_queue->empty(); }
|
|
|
+ bool empty() const { return child_queue->empty() and parent_queue->empty(); }
|
|
|
|
|
|
- std::shared_ptr <common::Message> pop_child_queue()
|
|
|
- {
|
|
|
- std::unique_lock <std::mutex> lock(mutex);
|
|
|
- std::shared_ptr <common::Message> message = child_queue->front();
|
|
|
+ std::shared_ptr<common::Message> pop_child_queue() {
|
|
|
+ std::unique_lock<std::mutex> lock(mutex);
|
|
|
+ std::shared_ptr<common::Message> message = child_queue->front();
|
|
|
|
|
|
child_queue->pop();
|
|
|
return message;
|
|
|
}
|
|
|
|
|
|
- std::shared_ptr <common::Message> pop_parent_queue()
|
|
|
- {
|
|
|
- std::unique_lock <std::mutex> lock(mutex);
|
|
|
- std::shared_ptr <common::Message> message = parent_queue->front();
|
|
|
+ std::shared_ptr<common::Message> pop_parent_queue() {
|
|
|
+ std::unique_lock<std::mutex> lock(mutex);
|
|
|
+ std::shared_ptr<common::Message> message = parent_queue->front();
|
|
|
|
|
|
parent_queue->pop();
|
|
|
return message;
|
|
|
}
|
|
|
|
|
|
- void push_child_queue(const std::shared_ptr <common::Message> &message)
|
|
|
- {
|
|
|
- std::unique_lock <std::mutex> lock(mutex);
|
|
|
+ void push_child_queue(const std::shared_ptr<common::Message> &message) {
|
|
|
+ std::unique_lock<std::mutex> lock(mutex);
|
|
|
|
|
|
child_queue->push(message);
|
|
|
condition.notify_one();
|
|
|
}
|
|
|
|
|
|
- void push_parent_queue(const std::shared_ptr <common::Message> &message)
|
|
|
- {
|
|
|
- std::unique_lock <std::mutex> lock(mutex);
|
|
|
+ void push_parent_queue(const std::shared_ptr<common::Message> &message) {
|
|
|
+ std::unique_lock<std::mutex> lock(mutex);
|
|
|
|
|
|
parent_queue->push(message);
|
|
|
condition.notify_one();
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-template<class Time,
|
|
|
- class GraphManager,
|
|
|
- class Parameters = common::NoParameters,
|
|
|
- class GraphParameters = common::NoParameters>
|
|
|
+template<typename Time,
|
|
|
+ typename GraphManager,
|
|
|
+ typename Parameters = common::NoParameters,
|
|
|
+ typename GraphParameters = common::NoParameters>
|
|
|
class Coordinator
|
|
|
- : public pdevs::Coordinator<Time, GraphManager, Parameters, GraphParameters>
|
|
|
-{
|
|
|
+ : public pdevs::Coordinator<Time, GraphManager, Parameters, GraphParameters> {
|
|
|
typedef pdevs::Coordinator<Time, GraphManager,
|
|
|
- Parameters, GraphParameters> parent_type;
|
|
|
+ Parameters, GraphParameters> parent_type;
|
|
|
typedef Coordinator<Time, GraphManager,
|
|
|
- Parameters, GraphParameters> type;
|
|
|
+ Parameters, GraphParameters> type;
|
|
|
typedef done_start_message<Time> done_start_message_type;
|
|
|
typedef start_message<Time> start_message_type;
|
|
|
typedef done_transition_message<Time> done_transition_message_type;
|
|
@@ -152,73 +134,66 @@ public:
|
|
|
Coordinator(const std::string &name,
|
|
|
const Parameters ¶meters,
|
|
|
const GraphParameters &graph_parameters)
|
|
|
- :
|
|
|
- common::Model<Time>(name),
|
|
|
- pdevs::Coordinator<Time, GraphManager, Parameters, GraphParameters>(
|
|
|
- name, parameters, graph_parameters),
|
|
|
- _queues(new Queues)
|
|
|
- {
|
|
|
+ :
|
|
|
+ common::Model<Time>(name),
|
|
|
+ pdevs::Coordinator<Time, GraphManager, Parameters, GraphParameters>(
|
|
|
+ name, parameters, graph_parameters),
|
|
|
+ _queues(new Queues) {
|
|
|
type::_graph_manager.init();
|
|
|
_thread = std::make_shared<std::thread>([&] { loop(); });
|
|
|
}
|
|
|
|
|
|
- virtual ~Coordinator()
|
|
|
- {
|
|
|
+ virtual ~Coordinator() {
|
|
|
done();
|
|
|
_thread->join();
|
|
|
}
|
|
|
|
|
|
- void attach_child(common::Model <Time> *model,
|
|
|
- const std::shared_ptr <Queues> &child_queue)
|
|
|
- {
|
|
|
+ void attach_child(common::Model<Time> *model,
|
|
|
+ const std::shared_ptr<Queues> &child_queue) {
|
|
|
_child_queues[model] = child_queue;
|
|
|
}
|
|
|
|
|
|
- void attach_parent(const std::shared_ptr <Queues> &parent_queue)
|
|
|
- {
|
|
|
+ void attach_parent(const std::shared_ptr<Queues> &parent_queue) {
|
|
|
_parent_queue = parent_queue;
|
|
|
}
|
|
|
|
|
|
- void done()
|
|
|
- {
|
|
|
+ void done() {
|
|
|
_queues->push_parent_queue(std::shared_ptr<artis::common::Message>(new artis::common::Close));
|
|
|
}
|
|
|
|
|
|
- const std::shared_ptr <Queues> &get_queue() const
|
|
|
- {
|
|
|
+ const std::shared_ptr<Queues> &get_queue() const {
|
|
|
return _queues;
|
|
|
}
|
|
|
|
|
|
- bool process(const common::Message *message)
|
|
|
- {
|
|
|
+ bool process(const common::Message *message) {
|
|
|
if (const done_transition_message<Time>
|
|
|
- *m = dynamic_cast< const done_transition_message<Time> *>(message)) {
|
|
|
+ *m = dynamic_cast< const done_transition_message<Time> *>(message)) {
|
|
|
type::_event_table.put(m->_tn, m->_child);
|
|
|
--_received;
|
|
|
if (_received == 0) {
|
|
|
- std::unique_lock <std::mutex> lock(_received_mutex);
|
|
|
+ std::unique_lock<std::mutex> lock(_received_mutex);
|
|
|
|
|
|
_received_condition.notify_one();
|
|
|
}
|
|
|
} else if (const transition_message<Time>
|
|
|
- *m = dynamic_cast< const transition_message<Time> *>(message)) {
|
|
|
+ *m = dynamic_cast< const transition_message<Time> *>(message)) {
|
|
|
typename Time::type tn = transition(m->_t);
|
|
|
|
|
|
_parent_queue
|
|
|
- ->push_parent_queue(
|
|
|
- std::shared_ptr<common::Message>(new done_transition_message_type(tn, this)));
|
|
|
+ ->push_parent_queue(
|
|
|
+ std::shared_ptr<common::Message>(new done_transition_message_type(tn, this)));
|
|
|
} else if (const start_message<Time> *m = dynamic_cast< const start_message<Time> *>(message)) {
|
|
|
typename Time::type tn = start(m->_t);
|
|
|
|
|
|
_parent_queue
|
|
|
- ->push_parent_queue(
|
|
|
- std::shared_ptr<common::Message>(new done_start_message_type(tn, this)));
|
|
|
+ ->push_parent_queue(
|
|
|
+ std::shared_ptr<common::Message>(new done_start_message_type(tn, this)));
|
|
|
} else if (const done_start_message<Time>
|
|
|
- *m = dynamic_cast< const done_start_message<Time> *>(message)) {
|
|
|
+ *m = dynamic_cast< const done_start_message<Time> *>(message)) {
|
|
|
type::_event_table.init(m->_tn, m->_child);
|
|
|
--_received;
|
|
|
if (_received == 0) {
|
|
|
- std::unique_lock <std::mutex> lock(_received_mutex);
|
|
|
+ std::unique_lock<std::mutex> lock(_received_mutex);
|
|
|
|
|
|
_received_condition.notify_one();
|
|
|
}
|
|
@@ -228,23 +203,22 @@ public:
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- void loop()
|
|
|
- {
|
|
|
+ void loop() {
|
|
|
while (true) {
|
|
|
{
|
|
|
- std::unique_lock <std::mutex> lock(_queues->mutex);
|
|
|
+ std::unique_lock<std::mutex> lock(_queues->mutex);
|
|
|
|
|
|
while (_queues->empty()) {
|
|
|
_queues->condition.wait(lock);
|
|
|
}
|
|
|
}
|
|
|
if (not _queues->child_queue->empty()) {
|
|
|
- std::shared_ptr <common::Message> message = _queues->pop_child_queue();
|
|
|
+ std::shared_ptr<common::Message> message = _queues->pop_child_queue();
|
|
|
|
|
|
process(message.get());
|
|
|
}
|
|
|
if (not _queues->parent_queue->empty()) {
|
|
|
- std::shared_ptr <common::Message> message = _queues->pop_parent_queue();
|
|
|
+ std::shared_ptr<common::Message> message = _queues->pop_parent_queue();
|
|
|
|
|
|
if (not process(message.get())) {
|
|
|
break;
|
|
@@ -253,11 +227,9 @@ public:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- typename Time::type
|
|
|
- start(const typename Time::type &t)
|
|
|
- {
|
|
|
+ typename Time::type start(const typename Time::type &t) {
|
|
|
_received = 0;
|
|
|
- for (auto &child : parent_type::_graph_manager.children()) {
|
|
|
+ for (auto &child: parent_type::_graph_manager.children()) {
|
|
|
if (child->is_atomic()) {
|
|
|
type::_event_table.init(child->start(type::_tn), child);
|
|
|
} else {
|
|
@@ -266,11 +238,11 @@ public:
|
|
|
}
|
|
|
|
|
|
if (_received > 0) {
|
|
|
- std::unique_lock <std::mutex> lock(_received_mutex);
|
|
|
+ std::unique_lock<std::mutex> lock(_received_mutex);
|
|
|
|
|
|
- for (const auto &q:_child_queues) {
|
|
|
+ for (const auto &q: _child_queues) {
|
|
|
q.second
|
|
|
- ->push_child_queue(std::shared_ptr<artis::common::Message>(new start_message<Time>(t)));
|
|
|
+ ->push_child_queue(std::shared_ptr<artis::common::Message>(new start_message<Time>(t)));
|
|
|
}
|
|
|
_received_condition.wait(lock);
|
|
|
}
|
|
@@ -280,36 +252,34 @@ public:
|
|
|
return type::_tn;
|
|
|
}
|
|
|
|
|
|
- void output(const typename Time::type &t)
|
|
|
- {
|
|
|
+ void output(const typename Time::type &t) {
|
|
|
|
|
|
assert(t == type::_tn);
|
|
|
|
|
|
- common::Models <Time> IMM = type::_event_table.get_current_models(t);
|
|
|
+ common::Models<Time> IMM = type::_event_table.get_current_models(t);
|
|
|
|
|
|
- for (auto &model : IMM) {
|
|
|
+ for (auto &model: IMM) {
|
|
|
model->output(t);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- typename Time::type transition(const typename Time::type &t)
|
|
|
- {
|
|
|
+ typename Time::type transition(const typename Time::type &t) {
|
|
|
assert(t >= type::_tl and t <= type::_tn);
|
|
|
|
|
|
- common::Models <Time> receivers = type::get_receivers();
|
|
|
- common::Models <Time> IMM = type::_event_table.get_current_models(t);
|
|
|
+ common::Models<Time> receivers = type::get_receivers();
|
|
|
+ common::Models<Time> IMM = type::_event_table.get_current_models(t);
|
|
|
// common::Models <Time>
|
|
|
// IMM = type::_event_table.get_current_models(t, type::_graph_manager.lookahead(t));
|
|
|
|
|
|
_received = 0;
|
|
|
- for (auto &model : receivers) {
|
|
|
+ for (auto &model: receivers) {
|
|
|
if (model->is_atomic()) {
|
|
|
type::_event_table.put(model->transition(t), model);
|
|
|
} else {
|
|
|
++_received;
|
|
|
}
|
|
|
}
|
|
|
- for (auto &model : IMM) {
|
|
|
+ for (auto &model: IMM) {
|
|
|
if (std::find(receivers.begin(), receivers.end(), model) == receivers.end()) {
|
|
|
if (model->is_atomic()) {
|
|
|
type::_event_table.put(model->transition(model->get_tn()), model);
|
|
@@ -320,29 +290,29 @@ public:
|
|
|
}
|
|
|
|
|
|
if (_received > 0) {
|
|
|
- std::unique_lock <std::mutex> lock(_received_mutex);
|
|
|
+ std::unique_lock<std::mutex> lock(_received_mutex);
|
|
|
|
|
|
if (not receivers.empty()) {
|
|
|
std::for_each(receivers.begin(), receivers.end(),
|
|
|
- [this, t](common::Model <Time> *model) {
|
|
|
+ [this, t](common::Model<Time> *model) {
|
|
|
auto it = _child_queues.find(model);
|
|
|
|
|
|
if (it != _child_queues.end()) {
|
|
|
it->second->push_child_queue(
|
|
|
- std::shared_ptr<artis::common::Message>(
|
|
|
- new transition_message<Time>(t)));
|
|
|
+ std::shared_ptr<artis::common::Message>(
|
|
|
+ new transition_message<Time>(t)));
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
if (not IMM.empty()) {
|
|
|
std::for_each(IMM.begin(), IMM.end(),
|
|
|
- [this, t](common::Model <Time> *model) {
|
|
|
+ [this, t](common::Model<Time> *model) {
|
|
|
auto it = _child_queues.find(model);
|
|
|
|
|
|
if (it != _child_queues.end()) {
|
|
|
it->second->push_child_queue(
|
|
|
- std::shared_ptr<artis::common::Message>(
|
|
|
- new transition_message<Time>(model->get_tn())));
|
|
|
+ std::shared_ptr<artis::common::Message>(
|
|
|
+ new transition_message<Time>(model->get_tn())));
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -356,17 +326,15 @@ public:
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- std::shared_ptr <std::thread> _thread;
|
|
|
- std::shared_ptr <Queues> _queues;
|
|
|
+ std::shared_ptr<std::thread> _thread;
|
|
|
+ std::shared_ptr<Queues> _queues;
|
|
|
unsigned int _received;
|
|
|
std::mutex _received_mutex;
|
|
|
std::condition_variable _received_condition;
|
|
|
- std::shared_ptr <Queues> _parent_queue;
|
|
|
- std::map<common::Model < Time> *, std::shared_ptr <Queues >> _child_queues;
|
|
|
+ std::shared_ptr<Queues> _parent_queue;
|
|
|
+ std::map<common::Model<Time> *, std::shared_ptr<Queues >> _child_queues;
|
|
|
};
|
|
|
|
|
|
-}
|
|
|
-}
|
|
|
} // namespace artis pdevs multithreading
|
|
|
|
|
|
#endif
|