Using Y_BEHAVIOR_METHOD2 with classes with inheritence

A forum for discussions about the C++ state machine framework yasmine.
In this forum you can ask questions about how something works, post your programming problems, file bug reports, request features, get information about licensing, ...
Ein Forum für Diskussionen über das C++ State Machine-Framework yasmine.
In diesem Forum kannst Du Fragen stellen, wenn Du wissen willst, wie etwas funktioniert, Du kannst Deine Programmierprobleme posten, Bugs melden, Features anfrangen, Fragen zur Lizenzierung stellen, ...
Milad
Posts: 4
Joined: 29 Aug 2018, 18:36

Using Y_BEHAVIOR_METHOD2 with classes with inheritence

Postby Milad » 23 Oct 2018, 08:18

Hi,
I have a question about using Y_BEHAVIOR_METHOD2 with a class that has inheritance.
First of all, I have to ask if it is possible to use Y_BEHAVIOR_METHOD2 macro with classes with several layers of inheritance and call functions from the parent and any of the children?
If yes then how should the address of the method be provided to the macro?
If no is there any other way to solve the problem?

Thanks a lot in advance for your time and answer.

Wolfgang Petroschka
Posts: 5
Joined: 13 Jul 2016, 08:38

Re: Using Y_BEHAVIOR_METHOD2 with classes with inheritence

Postby Wolfgang Petroschka » 07 Dec 2018, 13:42

Hi Milad,

sorry, that it took actually ages to answer your questions. But we have been super busy...

First of all, I have to ask if it is possible to use Y_BEHAVIOR_METHOD2 macro with classes with several layers of inheritance and call functions from the parent and any of the children?
Yes, it is. But it is not very pretty syntactically.

If yes then how should the address of the method be provided to the macro?
The name of the method is not the problem. You can pass it as &base::method or as &derived::method no difference. The problem is the object pointer (the first parameter). You have to cast your pointer outside the macro to the according class.

Code: Select all

Base* bp = static_cast<Base*>(this);
and then you can use the casted pointer within the macro.
It's ugly, but it works.

Code: Select all

Layer1* l1 = static_cast<Layer1*>(this); sxy::simple_state& simple_state_replying = main_region.add_simple_state( "replying", Y_BEHAVIOR_METHOD2( l1, &Layer1::reply ) )

I created a quick and dirty example based on "Hello, yasmine!" for you:

Code: Select all

////////////////////////////////////////////////////////////////////////////////////////////////////// // // // This file is part of the Seadex yasmine ecosystem (http://yasmine.seadex.de). // // Copyright (C) 2016-2018 Seadex GmbH // // // // Licensing information is available in the folder "license" which is part of this distribution. // // The same information is available on the www @ http://yasmine.seadex.de/Licenses.html. // // // ////////////////////////////////////////////////////////////////////////////////////////////////////// #include <iostream> #include "libyasmine/include/yasmine.hpp" const sxy::event_id HELLO_EVENT = 1; class Layer1 { public: void reply() { std::cout << "Hello, yasmine!" << std::endl; } }; class Layer2 : public Layer1 { public: void wait() { std::cout << "waiting" << std::endl; } }; class Layer3 : public Layer2 { public: Layer3(): error_code_(0), hello_yasmine_state_machine_() { hello_yasmine_state_machine_ = setup_state_machine( "hello yasmine state machine" ); if( check_state_machine_for_defects( *hello_yasmine_state_machine_ ) ) { hello_yasmine_state_machine_->run(); try { hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) ); hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) ); hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) ); hello_yasmine_state_machine_->halt(); } catch( const std::exception& exception ) { SX_LOG( hermes::log_level::LL_FATAL, "Unhandled exception: '%'.", exception.what() ); error_code_ = 1; } catch( ... ) { SX_LOG( hermes::log_level::LL_FATAL, "Unknown exception!" ); error_code_ = 2; } } else { error_code_ = 3; } } int get_error_code() const { return error_code_; } private: typedef sxe::SX_UNIQUE_PTR< sxy::sync_state_machine > state_machine_uptr; state_machine_uptr setup_state_machine( const std::string& _name ) { Layer1* l1 = static_cast<Layer1*>(this); Layer2* l2 = static_cast<Layer2*>(this); state_machine_uptr state_machine = SX_MAKE_UNIQUE< sxy::sync_state_machine >( _name ); sxy::composite_state& root_state = state_machine->get_root_state(); sxy::region& main_region = root_state.add_region( "main region" ); sxy::initial_pseudostate& initial_pseudostate = main_region.add_initial_pseudostate( "initial" ); sxy::simple_state& simple_state_waiting = main_region.add_simple_state( "waiting", Y_BEHAVIOR_METHOD2( l2, &Layer2::wait ) ); sxy::simple_state& simple_state_replying = main_region.add_simple_state( "replying", Y_BEHAVIOR_METHOD2( l1, &Layer1::reply ) ); state_machine->add_transition( HELLO_EVENT, simple_state_waiting, simple_state_replying ); state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, initial_pseudostate, simple_state_waiting ); state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, simple_state_replying, simple_state_waiting ); return( state_machine ); } bool check_state_machine_for_defects( const sxy::sync_state_machine& _state_machine ) { sxy::state_machine_defects defects; const bool state_machine_has_no_defects = _state_machine.check( defects ); if( !state_machine_has_no_defects ) { sxy::write_defects_to_log( defects ); } return( state_machine_has_no_defects ); } int error_code_; state_machine_uptr hello_yasmine_state_machine_; }; int main() { #ifndef SX_NO_LOGGING hermes::log_manager_template<hermes::std_timestamp_policy>& log_manager = hermes::log_manager::get_instance(); log_manager.set_log_level( hermes::log_level::LL_FATAL ); log_manager.add_logger( SX_MAKE_UNIQUE< hermes::cout_logger >() ); log_manager.run(); sxy::version::log_version(); #endif Layer3 layer3; #ifndef SX_NO_LOGGING log_manager.halt_and_join(); #endif return( layer3.get_error_code() ); }

Wolfgang Petroschka
Posts: 5
Joined: 13 Jul 2016, 08:38

Re: Using Y_BEHAVIOR_METHOD2 with classes with inheritence

Postby Wolfgang Petroschka » 07 Dec 2018, 13:43

The board software removed the line breaks in the code, so here for now without code tags:

//////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// This file is part of the Seadex yasmine ecosystem (http://yasmine.seadex.de). //
// Copyright (C) 2016-2018 Seadex GmbH //
// //
// Licensing information is available in the folder "license" which is part of this distribution. //
// The same information is available on the www @ http://yasmine.seadex.de/Licenses.html. //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////


#include <iostream>

#include "libyasmine/include/yasmine.hpp"


const sxy::event_id HELLO_EVENT = 1;

class Layer1 {
public:
void reply()
{
std::cout << "Hello, yasmine!" << std::endl;
}

};

class Layer2 : public Layer1 {
public:
void wait()
{
std::cout << "waiting" << std::endl;
}
};

class Layer3 : public Layer2 {
public:

Layer3():
error_code_(0),
hello_yasmine_state_machine_()
{
hello_yasmine_state_machine_ = setup_state_machine( "hello yasmine state machine" );

if( check_state_machine_for_defects( *hello_yasmine_state_machine_ ) )
{
hello_yasmine_state_machine_->run();
try
{
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->fire_event( sxy::event_impl::create( HELLO_EVENT ) );
hello_yasmine_state_machine_->halt();
}
catch( const std::exception& exception )
{
SX_LOG( hermes::log_level::LL_FATAL, "Unhandled exception: '%'.", exception.what() );
error_code_ = 1;
}
catch( ... )
{
SX_LOG( hermes::log_level::LL_FATAL, "Unknown exception!" );
error_code_ = 2;
}
}
else
{
error_code_ = 3;
}
}

int get_error_code() const
{
return error_code_;
}

private:
typedef sxe::SX_UNIQUE_PTR< sxy::sync_state_machine > state_machine_uptr;

state_machine_uptr setup_state_machine( const std::string& _name )
{
Layer1* l1 = static_cast<Layer1*>(this);
Layer2* l2 = static_cast<Layer2*>(this);
state_machine_uptr state_machine = SX_MAKE_UNIQUE< sxy::sync_state_machine >( _name );
sxy::composite_state& root_state = state_machine->get_root_state();
sxy::region& main_region = root_state.add_region( "main region" );
sxy::initial_pseudostate& initial_pseudostate = main_region.add_initial_pseudostate( "initial" );
sxy::simple_state& simple_state_waiting = main_region.add_simple_state( "waiting", Y_BEHAVIOR_METHOD2( l2, &Layer2::wait ) );
sxy::simple_state& simple_state_replying = main_region.add_simple_state( "replying", Y_BEHAVIOR_METHOD2( l1, &Layer1::reply ) );
state_machine->add_transition( HELLO_EVENT, simple_state_waiting, simple_state_replying );
state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, initial_pseudostate, simple_state_waiting );
state_machine->add_transition( sxy::Y_COMPLETION_EVENT_ID, simple_state_replying, simple_state_waiting );

return( state_machine );
}

bool check_state_machine_for_defects( const sxy::sync_state_machine& _state_machine )
{
sxy::state_machine_defects defects;
const bool state_machine_has_no_defects = _state_machine.check( defects );
if( !state_machine_has_no_defects )
{
sxy::write_defects_to_log( defects );
}

return( state_machine_has_no_defects );
}

int error_code_;
state_machine_uptr hello_yasmine_state_machine_;
};

int main()
{
#ifndef SX_NO_LOGGING
hermes::log_manager_template<hermes::std_timestamp_policy>& log_manager = hermes::log_manager::get_instance();
log_manager.set_log_level( hermes::log_level::LL_FATAL );
log_manager.add_logger( SX_MAKE_UNIQUE< hermes::cout_logger >() );
log_manager.run();
sxy::version::log_version();
#endif

Layer3 layer3;

#ifndef SX_NO_LOGGING
log_manager.halt_and_join();
#endif

return( layer3.get_error_code() );
}

Milad
Posts: 4
Joined: 29 Aug 2018, 18:36

Re: Using Y_BEHAVIOR_METHOD2 with classes with inheritence

Postby Milad » 04 Feb 2019, 10:32

Great, Thank you very much for your answer.


Return to “yasmine”

Who is online

Users browsing this forum: No registered users and 1 guest