Parcourir la source

Add policy to dtss

Eric Ramat il y a 11 ans
Parent
commit
ba0067716d

+ 1 - 1
src/common/ExternalEvent.cpp

@@ -66,7 +66,7 @@ std::string ExternalEvent::to_string() const
     std::ostringstream ss;
     std::ostringstream ss;
 
 
     ss << "( " << _port_name << " , " << (_model?_model->get_name():"<>")
     ss << "( " << _port_name << " , " << (_model?_model->get_name():"<>")
-       << ")";
+       << " , " << _content << ")";
     return ss.str();
     return ss.str();
 }
 }
 
 

+ 0 - 115
src/dtss/Coordinator.cpp

@@ -24,123 +24,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
  */
 
 
-#include <common/Trace.hpp>
-
 #include <dtss/Coordinator.hpp>
 #include <dtss/Coordinator.hpp>
-#include <dtss/Simulator.hpp>
-
-#include <algorithm>
-#include <cassert>
 
 
 namespace paradevs { namespace dtss {
 namespace paradevs { namespace dtss {
 
 
-Coordinator::Coordinator(const std::string& name, common::Time time_step) :
-    common::Coordinator(name), _time_step(time_step)
-{ }
-
-Coordinator::~Coordinator()
-{
-    for (unsigned int i = 0; i < _child_list.size(); i++)
-    { delete _child_list[i]; }
-}
-
-common::Time Coordinator::start(common::Time t)
-{
-    assert(_child_list.size() > 0);
-
-    for (auto & child : _child_list) {
-        child->start(_tn);
-    }
-    _tn = t;
-    return _tn;
-}
-
-common::Time Coordinator::dispatch_events(common::Bag bag, common::Time t)
-{
-    for (auto & ymsg : bag) {
-        std::pair < common::Links::iterator ,
-                    common::Links::iterator > result_model =
-            _link_list.equal_range(common::Node(ymsg.get_port_name(),
-                                                ymsg.get_model()));
-
-        for (common::Links::iterator it = result_model.first;
-             it != result_model.second; ++it) {
-            // event on output port of coupled model
-            if (it->second.get_model() == this) {
-                common::Bag ymessages;
-
-                ymessages.push_back(
-                    common::ExternalEvent(it->second.get_port_name(),
-                                          it->second.get_model(),
-                                          ymsg.get_content()));
-                dynamic_cast < Coordinator* >(get_parent())->dispatch_events(
-                    ymessages, t);
-            } else { // event on input port of internal model
-                Model* model = dynamic_cast < Model* >(
-                    it->second.get_model());
-                common::ExternalEvent message(it->second.get_port_name(),
-                                              model, ymsg.get_content());
-
-                model->post_message(t, message);
-            }
-        }
-    }
-    return _tn;
-}
-
-void Coordinator::observation(std::ostream& file) const
-{
-    for (unsigned i = 0; i < _child_list.size(); i++) {
-        _child_list[i]->observation(file);
-    }
-}
-
-void Coordinator::output(common::Time t)
-{
-    assert(t == _tn);
-
-    for (auto & model : _child_list) {
-        model->output(t);
-    }
-}
-
-void Coordinator::post_message(common::Time t,
-                               const common::ExternalEvent& message)
-{
-    std::pair < common::Links::iterator, common::Links::iterator > result =
-        _link_list.equal_range(common::Node(message.get_port_name(), this));
-
-    for (common::Links::iterator it_r = result.first;
-         it_r != result.second; ++it_r) {
-        Model* model = dynamic_cast < Model* >((*it_r).second.get_model());
-
-        model->post_message(t,
-                            common::ExternalEvent(it_r->second.get_port_name(),
-                                                  model,
-                                                  message.get_content()));
-    }
-}
-
-common::Time Coordinator::transition(common::Time t)
-{
-    assert(t >= _tl and t <= _tn);
-
-    for (auto & model : _child_list) {
-        model->transition(t);
-    }
-    _tn = t + _time_step;
-    return _tn;
-}
-
-void Coordinator::add_child(Model* child)
-{
-    _child_list.push_back(child);
-    child->set_parent(this);
-}
-
-void Coordinator::add_link(const common::Node& source,
-                           const common::Node& destination)
-{ _link_list.insert(std::pair < common::Node, common::Node >(source,
-                                                             destination)); }
-
 } } // namespace paradevs dtss
 } } // namespace paradevs dtss

+ 127 - 15
src/dtss/Coordinator.hpp

@@ -29,40 +29,152 @@
 
 
 #include <common/Bag.hpp>
 #include <common/Bag.hpp>
 #include <common/Coordinator.hpp>
 #include <common/Coordinator.hpp>
-#include <common/EventTable.hpp>
-#include <common/Links.hpp>
 #include <common/ExternalEvent.hpp>
 #include <common/ExternalEvent.hpp>
+#include <common/Links.hpp>
 #include <common/Node.hpp>
 #include <common/Node.hpp>
+#include <common/Trace.hpp>
 
 
+#include <dtss/Simulator.hpp>
+
+#include <algorithm>
+#include <cassert>
 #include <iostream>
 #include <iostream>
 
 
 namespace paradevs { namespace dtss {
 namespace paradevs { namespace dtss {
 
 
+template < class Policy >
 class Coordinator : public common::Coordinator
 class Coordinator : public common::Coordinator
 {
 {
 public:
 public:
-    Coordinator(const std::string& name, common::Time time_step);
-    virtual ~Coordinator();
+    Coordinator(const std::string& name, common::Time time_step) :
+        common::Coordinator(name), _time_step(time_step)
+    { }
+    virtual ~Coordinator()
+    {
+        for (unsigned int i = 0; i < _child_list.size(); i++)
+        { delete _child_list[i]; }
+    }
 
 
 // DEVS methods
 // DEVS methods
-    virtual void output(common::Time /* t */);
-    virtual void post_message(common::Time /* t */,
-                              const common::ExternalEvent& /* message */);
-    virtual common::Time dispatch_events(common::Bag /* bag */,
-                                         common::Time /* t */);
-    virtual common::Time start(common::Time /* t */);
-    virtual common::Time transition(common::Time /* t */);
-    virtual void observation(std::ostream& file) const;
+    common::Time start(common::Time t)
+    {
+        assert(_child_list.size() > 0);
+
+        for (auto & child : _child_list) {
+            child->start(_tn);
+        }
+        _tl = t;
+        _tn = t;
+        return _tn;
+    }
+
+    common::Time dispatch_events(common::Bag bag, common::Time t)
+    {
+        for (auto & ymsg : bag) {
+            std::pair < common::Links::iterator ,
+                        common::Links::iterator > result_model =
+                _link_list.equal_range(common::Node(ymsg.get_port_name(),
+                                                    ymsg.get_model()));
+
+            for (common::Links::iterator it = result_model.first;
+                 it != result_model.second; ++it) {
+                // event on output port of coupled model
+                if (it->second.get_model() == this) {
+                    common::Bag ymessages;
+
+                    ymessages.push_back(
+                        common::ExternalEvent(it->second.get_port_name(),
+                                              it->second.get_model(),
+                                              ymsg.get_content()));
+                    dynamic_cast < Coordinator* >(get_parent())->dispatch_events(
+                        ymessages, t);
+                } else { // event on input port of internal model
+                    Model* model = dynamic_cast < Model* >(
+                        it->second.get_model());
+                    common::ExternalEvent message(it->second.get_port_name(),
+                                                  model, ymsg.get_content());
+
+                    model->post_message(t, message);
+                }
+            }
+        }
+        return _tn;
+    }
+
+    void observation(std::ostream& file) const
+    {
+        for (unsigned i = 0; i < _child_list.size(); i++) {
+            _child_list[i]->observation(file);
+        }
+    }
+
+    void output(common::Time t)
+    {
+        if (t == _tn) {
+            for (auto & model : _child_list) {
+                model->output(t);
+            }
+        }
+    }
+
+    void post_message(common::Time t,
+                      const common::ExternalEvent& event)
+    {
+        if (t == _tn) {
+            std::pair < common::Links::iterator, common::Links::iterator > result =
+                _link_list.equal_range(common::Node(event.get_port_name(), this));
+
+            for (common::Links::iterator it_r = result.first;
+                 it_r != result.second; ++it_r) {
+                Model* model = dynamic_cast < Model* >((*it_r).second.get_model());
+
+                model->post_message(t,
+                                    common::ExternalEvent(it_r->second.get_port_name(),
+                                                          model, event.get_content()));
+            }
+        } else {
+            _policy(t, event, _tl, _tn);
+        }
+    }
+
+    common::Time transition(common::Time t)
+    {
+        if (t == _tn) {
+            if (not _policy.bag().empty()) {
+                for (common::Bag::const_iterator it = _policy.bag().begin();
+                     it != _policy.bag().end(); ++it) {
+                    post_message(t, *it);
+                }
+            }
+            for (auto & model : _child_list) {
+                model->transition(t);
+            }
+            _tl = t;
+            _tn = t + _time_step;
+        }
+        clear_bag();
+        return _tn;
+    }
 
 
 // graph methods
 // graph methods
-    virtual void add_child(Model* child);
-    virtual void add_link(const common::Node& source,
-                          const common::Node& destination);
+    void add_child(Model* child)
+    {
+        _child_list.push_back(child);
+        child->set_parent(this);
+    }
+
+    void add_link(const common::Node& source,
+                  const common::Node& destination)
+    {
+        _link_list.insert(std::pair < common::Node, common::Node >(source,
+                                                                   destination));
+    }
 
 
 private:
 private:
     common::Links  _link_list;
     common::Links  _link_list;
     common::Models _child_list;
     common::Models _child_list;
     common::Time   _time_step;
     common::Time   _time_step;
+    Policy         _policy;
 };
 };
 
 
 } } // namespace paradevs dtss
 } } // namespace paradevs dtss

+ 5 - 2
src/dtss/Simulator.cpp

@@ -45,6 +45,7 @@ Simulator::~Simulator()
 common::Time Simulator::start(common::Time t)
 common::Time Simulator::start(common::Time t)
 {
 {
     _dynamics->start(t);
     _dynamics->start(t);
+    _tl = t;
     _tn = t;
     _tn = t;
     return _tn;
     return _tn;
 }
 }
@@ -62,8 +63,8 @@ void Simulator::output(common::Time t)
                  ++it) {
                  ++it) {
                 it->set_model(this);
                 it->set_model(this);
             }
             }
-            dynamic_cast < Coordinator* >(get_parent())->dispatch_events(bag,
-                                                                         t);
+            dynamic_cast < common::Coordinator* >(get_parent())->dispatch_events(bag,
+                                                                                 t);
         }
         }
     }
     }
 }
 }
@@ -74,9 +75,11 @@ void Simulator::post_message(common::Time /* t */,
 
 
 common::Time Simulator::transition(common::Time t)
 common::Time Simulator::transition(common::Time t)
 {
 {
+
     assert(t == _tn);
     assert(t == _tn);
 
 
     _dynamics->transition(get_bag(), t);
     _dynamics->transition(get_bag(), t);
+    _tl = t;
     _tn = t + _time_step;
     _tn = t + _time_step;
     clear_bag();
     clear_bag();
     return _tn;
     return _tn;

+ 11 - 2
src/pdevs/Coordinator.cpp

@@ -83,20 +83,29 @@ void Coordinator::output(common::Time t)
 
 
     common::Trace::trace() << common::TraceElement(get_name(), t,
     common::Trace::trace() << common::TraceElement(get_name(), t,
                                                    common::OUTPUT)
                                                    common::OUTPUT)
-                           << ": BEFORE";
+                           << ": BEFORE => "
+                           << "tl = " << _tl << " ; tn = " << _tn
+                           << " ; scheduler = " << _event_table.to_string();
     common::Trace::trace().flush();
     common::Trace::trace().flush();
 
 
     assert(t == _tn);
     assert(t == _tn);
 
 
     common::Models IMM = _event_table.get_current_models(t);
     common::Models IMM = _event_table.get_current_models(t);
 
 
+    common::Trace::trace() << common::TraceElement(get_name(), t,
+                                                   common::OUTPUT)
+                           << ": IMM = " << IMM.to_string();
+    common::Trace::trace().flush();
+
     for (auto & model : IMM) {
     for (auto & model : IMM) {
         model->output(t);
         model->output(t);
     }
     }
 
 
     common::Trace::trace() << common::TraceElement(get_name(), t,
     common::Trace::trace() << common::TraceElement(get_name(), t,
                                                    common::OUTPUT)
                                                    common::OUTPUT)
-                           << ": AFTER";
+                           << ": AFTER => "
+                           << "tl = " << _tl << " ; tn = " << _tn
+                           << " ; scheduler = " << _event_table.to_string();
     common::Trace::trace().flush();
     common::Trace::trace().flush();
 
 
 }
 }

+ 20 - 4
src/tests/dtss_tests.cpp

@@ -56,7 +56,7 @@ common::Bag A::lambda(common::Time t) const
 {
 {
     common::Bag msgs;
     common::Bag msgs;
 
 
-    msgs.push_back(common::ExternalEvent("out", 0, true));
+    msgs.push_back(common::ExternalEvent("out", 0.));
 
 
     common::Trace::trace() << common::TraceElement(get_name(), t,
     common::Trace::trace() << common::TraceElement(get_name(), t,
                                                    common::LAMBDA)
                                                    common::LAMBDA)
@@ -88,7 +88,7 @@ common::Bag B::lambda(common::Time t) const
 {
 {
     common::Bag msgs;
     common::Bag msgs;
 
 
-    msgs.push_back(common::ExternalEvent("out", 0, true));
+    msgs.push_back(common::ExternalEvent("out", 0.));
 
 
     common::Trace::trace() << common::TraceElement(get_name(), t,
     common::Trace::trace() << common::TraceElement(get_name(), t,
                                                    common::LAMBDA)
                                                    common::LAMBDA)
@@ -98,9 +98,25 @@ common::Bag B::lambda(common::Time t) const
     return msgs;
     return msgs;
 }
 }
 
 
+struct Policy
+{
+    const common::Bag& bag() const
+    { return _bag; }
+
+    virtual void operator()(common::Time /* t */, const common::ExternalEvent& event,
+                            common::Time /* tl */, common::Time /* tn */)
+    {
+        _bag.clear();
+        _bag.push_back(event);
+    }
+
+private:
+    common::Bag _bag;
+};
+
 common::Model* OnlyOneBuilder::build() const
 common::Model* OnlyOneBuilder::build() const
 {
 {
-    dtss::Coordinator* root = new dtss::Coordinator("root", 1);
+    dtss::Coordinator < Policy >* root = new dtss::Coordinator < Policy >("root", 1);
     dtss::Simulator* a = new dtss::Simulator(new A("a"), 1);
     dtss::Simulator* a = new dtss::Simulator(new A("a"), 1);
 
 
     root->add_child(a);
     root->add_child(a);
@@ -109,7 +125,7 @@ common::Model* OnlyOneBuilder::build() const
 
 
 common::Model* TwoBuilder::build() const
 common::Model* TwoBuilder::build() const
 {
 {
-    dtss::Coordinator* root = new dtss::Coordinator("root", 1);
+    dtss::Coordinator < Policy >* root = new dtss::Coordinator < Policy >("root", 1);
     dtss::Simulator* a = new dtss::Simulator(new A("a"), 1);
     dtss::Simulator* a = new dtss::Simulator(new A("a"), 1);
     dtss::Simulator* b = new dtss::Simulator(new B("b"), 1);
     dtss::Simulator* b = new dtss::Simulator(new B("b"), 1);
 
 

+ 41 - 10
src/tests/mixed_tests.cpp

@@ -98,7 +98,7 @@ common::Bag A1::lambda(common::Time t) const
 {
 {
     common::Bag msgs;
     common::Bag msgs;
 
 
-    msgs.push_back(common::ExternalEvent("out", 0, true));
+    msgs.push_back(common::ExternalEvent("out", 0.));
 
 
     common::Trace::trace() << common::TraceElement(get_name(), t,
     common::Trace::trace() << common::TraceElement(get_name(), t,
                                                    common::LAMBDA)
                                                    common::LAMBDA)
@@ -170,7 +170,7 @@ common::Bag B1::lambda(common::Time t) const
 {
 {
     common::Bag msgs;
     common::Bag msgs;
 
 
-    msgs.push_back(common::ExternalEvent("out", 0, true));
+    msgs.push_back(common::ExternalEvent("out", t));
 
 
     common::Trace::trace() << common::TraceElement(get_name(), t,
     common::Trace::trace() << common::TraceElement(get_name(), t,
                                                    common::LAMBDA)
                                                    common::LAMBDA)
@@ -243,6 +243,36 @@ common::Bag B2::lambda(common::Time t) const
     return msgs;
     return msgs;
 }
 }
 
 
+struct LastBagPolicy
+{
+    const common::Bag& bag() const
+    { return _bag; }
+
+    virtual void operator()(common::Time /* t */, const common::ExternalEvent& event,
+                            common::Time /* tl */, common::Time /* tn */)
+    {
+        _bag.clear();
+        _bag.push_back(event);
+    }
+
+private:
+    common::Bag _bag;
+};
+
+struct IgnorePolicy
+{
+    const common::Bag& bag() const
+    { return _bag; }
+
+    virtual void operator()(common::Time /* t */,
+                            const common::ExternalEvent& /* event */,
+                            common::Time /* tl */, common::Time /* tn */)
+    { }
+
+private:
+    common::Bag _bag;
+};
+
 common::Model* HierachicalBuilder::build() const
 common::Model* HierachicalBuilder::build() const
 {
 {
     pdevs::Coordinator* root = new pdevs::Coordinator("root");
     pdevs::Coordinator* root = new pdevs::Coordinator("root");
@@ -258,10 +288,11 @@ common::Model* HierachicalBuilder::build() const
         S1->add_link(common::Node("out", b), common::Node("out", S1));
         S1->add_link(common::Node("out", b), common::Node("out", S1));
     }
     }
 
 
-    dtss::Coordinator* S2 = new dtss::Coordinator("S2", 1);
+    dtss::Coordinator < LastBagPolicy >* S2 =
+        new dtss::Coordinator < LastBagPolicy >("S2", 20);
     {
     {
-        dtss::Simulator* a = new dtss::Simulator(new A2("a2"), 1);
-        dtss::Simulator* b = new dtss::Simulator(new B2("b2"), 1);
+        dtss::Simulator* a = new dtss::Simulator(new A2("a2"), 20);
+        dtss::Simulator* b = new dtss::Simulator(new B2("b2"), 20);
 
 
         S2->add_child(a);
         S2->add_child(a);
         S2->add_child(b);
         S2->add_child(b);
@@ -279,7 +310,7 @@ common::Model* HierachicalBuilder::build() const
 TEST_CASE("mixed/hierachical", "run")
 TEST_CASE("mixed/hierachical", "run")
 {
 {
     paradevs::HierachicalBuilder builder;
     paradevs::HierachicalBuilder builder;
-    paradevs::common::RootCoordinator rc(0, 10, builder);
+    paradevs::common::RootCoordinator rc(0, 100, builder);
 
 
     paradevs::common::Trace::trace().clear();
     paradevs::common::Trace::trace().clear();
     rc.run();
     rc.run();
@@ -300,7 +331,7 @@ TEST_CASE("mixed/hierachical", "run")
     REQUIRE(paradevs::common::Trace::trace().elements().
     REQUIRE(paradevs::common::Trace::trace().elements().
             filter_model_name("a1").
             filter_model_name("a1").
             filter_type(paradevs::common::DELTA_EXT).size() == 0);
             filter_type(paradevs::common::DELTA_EXT).size() == 0);
-    for (unsigned int t = 0; t <= 10; ++t) {
+    for (double t = 0; t <= 100; ++t) {
         REQUIRE(paradevs::common::Trace::trace().elements().
         REQUIRE(paradevs::common::Trace::trace().elements().
                 filter_model_name("a1").filter_time(t).
                 filter_model_name("a1").filter_time(t).
                 filter_type(paradevs::common::LAMBDA).size() == 1);
                 filter_type(paradevs::common::LAMBDA).size() == 1);
@@ -312,7 +343,7 @@ TEST_CASE("mixed/hierachical", "run")
                 filter_type(paradevs::common::TA).size() == 1);
                 filter_type(paradevs::common::TA).size() == 1);
     }
     }
 
 
-    for (unsigned int t = 0; t <= 10; ++t) {
+    for (double t = 0; t <= 100; ++t) {
         REQUIRE(paradevs::common::Trace::trace().elements().
         REQUIRE(paradevs::common::Trace::trace().elements().
                 filter_model_name("b1").filter_time(t).
                 filter_model_name("b1").filter_time(t).
                 filter_type(paradevs::common::LAMBDA).size() == 1);
                 filter_type(paradevs::common::LAMBDA).size() == 1);
@@ -327,7 +358,7 @@ TEST_CASE("mixed/hierachical", "run")
                 filter_type(paradevs::common::DELTA_EXT).size() == 1);
                 filter_type(paradevs::common::DELTA_EXT).size() == 1);
     }
     }
 
 
-    for (unsigned int t = 0; t <= 10; ++t) {
+    for (unsigned int t = 0; t <= 100; t += 20) {
         REQUIRE(paradevs::common::Trace::trace().elements().
         REQUIRE(paradevs::common::Trace::trace().elements().
                 filter_model_name("a2").filter_time(t).
                 filter_model_name("a2").filter_time(t).
                 filter_type(paradevs::common::LAMBDA).size() == 1);
                 filter_type(paradevs::common::LAMBDA).size() == 1);
@@ -336,7 +367,7 @@ TEST_CASE("mixed/hierachical", "run")
                 filter_type(paradevs::common::DELTA_INT).size() == 1);
                 filter_type(paradevs::common::DELTA_INT).size() == 1);
     }
     }
 
 
-    for (unsigned int t = 0; t <= 10; ++t) {
+    for (unsigned int t = 0; t <= 100; t += 20) {
         REQUIRE(paradevs::common::Trace::trace().elements().
         REQUIRE(paradevs::common::Trace::trace().elements().
                 filter_model_name("b2").filter_time(t).
                 filter_model_name("b2").filter_time(t).
                 filter_type(paradevs::common::LAMBDA).size() == 1);
                 filter_type(paradevs::common::LAMBDA).size() == 1);