blob: 7a61d035efe23741091f3f26b1b970193e1bc339 [file] [log] [blame]
//
// state_machine.cpp
//
// Author: Lutz Bichler <Lutz.Bichler@bmwgroup.com>
//
// This file is part of the BMW Some/IP implementation.
//
// Copyright © 2013, 2014 Bayerische Motoren Werke AG (BMW).
// All rights reserved.
//
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <vsomeip/service_discovery/internal/events.hpp>
#include <vsomeip/service_discovery/internal/service_registration.hpp>
namespace vsomeip {
namespace service_discovery {
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace boost::msm::front;
////////////////////////////////////////////////////////
/////////// Implementation of statechart /////////
////////////////////////////////////////////////////////
// Top-level state machine
struct service_registration_state_machine_def
: public msm::front::state_machine_def<service_registration_state_machine_def> {
// States
struct initial: public msm::front::entry_pseudo_state<0> {
template <class Event, class Fsm>
void on_entry(Event const &, Fsm &fsm)
{ std::cout << "Entering Initial" << std::endl; }
template <class Event, class Fsm>
void on_exit(Event const &, Fsm &fsm)
{ std::cout << "Exiting Initial" << std::endl; }
};
struct not_ready: public msm::front::state<> {
template <class Event, class Fsm>
void on_entry(Event const &, Fsm &fsm)
{ std::cout << "Entering NotReady" << std::endl; }
template <class Event, class Fsm>
void on_exit(Event const &, Fsm &fsm)
{ std::cout << "Exiting NotReady" << std::endl; }
};
struct ready: public msm::front::state_machine_def<ready> {
template <class Event, class Fsm>
void on_entry(Event const &, Fsm &fsm)
{ std::cout << "Entering Ready" << std::endl; }
template <class Event, class Fsm>
void on_exit(Event const &, Fsm &fsm)
{ std::cout << "Exiting Ready" << std::endl; }
// States
struct initial: public msm::front::entry_pseudo_state<0> {
};
struct waiting: public msm::front::state<> {
};
struct repeating: public msm::front::state<> {
};
struct announcing: public msm::front::state<> {
};
// Determine initial state
typedef initial initial_state;
// Members
uint32_t repetitions_max_;
// Guards
bool is_repeating(ev_timer_expired const &_event) {
return repetitions_max_ > 0;
}
bool is_not_repeating(ev_timer_expired const &_event) {
return repetitions_max_ == 0;
}
// Actions
void send_offer_service(ev_timer_expired const &_event) {
// TODO: send message
}
void send_delayed_offer_service(ev_find_service const &_event) {
// TODO: check timing and schedule sending of message
}
// Transitions
struct transition_table: mpl::vector<
row<waiting, ev_timer_expired, announcing,
&ready::send_offer_service, &ready::is_not_repeating>,
row<waiting, ev_timer_expired, repeating,
&ready::send_offer_service, &ready::is_repeating>,
a_row<repeating, ev_find_service, repeating,
&ready::send_delayed_offer_service>,
row<repeating, ev_timer_expired, repeating,
&ready::send_offer_service, &ready::is_repeating>,
g_row<repeating, ev_timer_expired, announcing,
&ready::is_not_repeating>,
a_row<announcing, ev_timer_expired, announcing,
&ready::send_offer_service>,
a_row<announcing, ev_find_service, announcing,
&ready::send_delayed_offer_service> > {
};
};
// Determine initial state
typedef initial initial_state;
// Members
bool is_daemon_up_;
bool is_service_up_;
bool is_requested_;
// Guards
bool is_not_ready(none const &_no_event) {
return (!is_daemon_up_ || !is_service_up_);
}
bool is_ready(none const &_no_event) {
return !(is_not_ready(_no_event));
}
bool is_not_ready(ev_service_status_change const &_event) {
is_service_up_ = _event.is_up_;
return (!is_daemon_up_ || !is_service_up_);
}
bool is_ready(ev_service_status_change const &_event) {
return !(is_not_ready(_event));
}
bool is_not_ready(ev_daemon_status_change const &_event) {
is_daemon_up_ = _event.is_up_;
return (!is_daemon_up_ || !is_service_up_);
}
bool is_ready(ev_daemon_status_change const &_event) {
return !(is_not_ready(_event));
}
// Actions
void handle_service_down(ev_daemon_status_change const &_event) {
// TODO: clear_all_timers();
}
;
void handle_service_down(ev_service_status_change const &_event) {
if (!is_service_up_) {
// TODO: send "StopOfferService" message!
}
// TODO: clear_all_timers();
};
// Transitions
struct transition_table: mpl::vector<
g_row<initial, none, ready,
&service_registration_state_machine_def::is_ready>,
g_row<initial, none, not_ready,
&service_registration_state_machine_def::is_not_ready>,
g_row<not_ready, ev_daemon_status_change, ready,
&service_registration_state_machine_def::is_ready>,
g_row<not_ready, ev_service_status_change, ready,
&service_registration_state_machine_def::is_ready>,
row<ready, ev_daemon_status_change, not_ready,
&service_registration_state_machine_def::handle_service_down,
&service_registration_state_machine_def::is_not_ready>,
row<ready, ev_service_status_change, not_ready,
&service_registration_state_machine_def::handle_service_down,
&service_registration_state_machine_def::is_not_ready> > {
};
template <class Fsm, class Event>
void no_transition(Event const &_event, Fsm &_machine, int state) {
std::cout << "No transition from state " << state << " on event " << typeid(_event).name() << std::endl;
}
};
struct service_registration::state_machine
: msm::back::state_machine< service_registration_state_machine_def > {
};
////////////////////////////////////////////////////////
/////////// Implementation of member functions /////////
////////////////////////////////////////////////////////
service_registration::service_registration()
: state_machine_(new state_machine) {
state_machine_->is_daemon_up_ = false;
state_machine_->is_service_up_ = false;
}
void service_registration::start() {
state_machine_->start();
}
void service_registration::stop() {
state_machine_->stop();
}
void service_registration::process() {
state_machine_->process_event(none());
}
} // namespace service_discovery
} // namespace vsomeip