diff --git a/wire/CMakeLists.txt b/wire/CMakeLists.txt index cb3ddc3..468759d 100644 --- a/wire/CMakeLists.txt +++ b/wire/CMakeLists.txt @@ -19,6 +19,7 @@ set( SOURCES ${SOURCES} "slot/output_slot.h" "slot/output_slot.cpp" "slot/sheet.hpp" + "slot/other_slot.hpp" ) motor_vs_src_dir( SOURCES ) diff --git a/wire/node/node.cpp b/wire/node/node.cpp index 605d3c8..b0819bb 100644 --- a/wire/node/node.cpp +++ b/wire/node/node.cpp @@ -172,10 +172,10 @@ motor::concurrent::task_t::task_funk_t inode::make_task_funk( void_t ) noexcept return [=] ( motor::concurrent::task_t::task_funk_param_in_t ) { // exchange all inputs... (pull) - this->inputs().exchange() ; + //this->inputs().exchange() ; this->execute() ; // or exchange all outputs (push) - //this->outputs().exchange() ; + this->outputs().exchange() ; } ; } diff --git a/wire/slot/input_slot.h b/wire/slot/input_slot.h index 75f7384..bf14a6a 100644 --- a/wire/slot/input_slot.h +++ b/wire/slot/input_slot.h @@ -34,6 +34,7 @@ namespace motor private: + bool_t _has_changed = false ; T _value ; this_output_slot_mtr_t _output_slot = nullptr ; @@ -99,19 +100,39 @@ namespace motor this_ref_t operator = ( T const & v ) noexcept { _value = v ; + _has_changed = true ; return *this ; } public: + // Returns the value of the slot + // Does not reset the changed flag. + // @see get_value_and_reset T const & get_value( void_t ) const noexcept { return _value ; } + // get the value in v if the value has changed + // returns the "changed flag" and also resets it + bool_t get_value_and_reset( T & v ) noexcept + { + if( _has_changed ) + { + v = _value ; + _has_changed = false ; + return true ; + } + + return false ; + } + + // void_t set_value( T const v ) noexcept { _value = v ; + _has_changed = true ; } }; } diff --git a/wire/slot/other_slot.hpp b/wire/slot/other_slot.hpp new file mode 100644 index 0000000..10dca49 --- /dev/null +++ b/wire/slot/other_slot.hpp @@ -0,0 +1,34 @@ + + +#pragma once + +#include "input_slot.h" +#include "output_slot.h" + +namespace motor +{ + namespace wire + { + template< typename T > + class other_slot + { + using type_t = void_t ; + }; + + template<> + struct other_slot< motor::wire::iinput_slot_t > + { + using type_t = motor::wire::ioutput_slot_t ; + using type_ptr_t = type_t * ; + using type_safe_mtr_t = motor::core::mtr_safe< type_t > ; + }; + + template<> + struct other_slot< motor::wire::ioutput_slot_t > + { + using type_t = motor::wire::iinput_slot_t ; + using type_ptr_t = type_t * ; + using type_safe_mtr_t = motor::core::mtr_safe< type_t > ; + }; + } +} \ No newline at end of file diff --git a/wire/slot/output_slot.h b/wire/slot/output_slot.h index 7d3c85f..f32867b 100644 --- a/wire/slot/output_slot.h +++ b/wire/slot/output_slot.h @@ -34,6 +34,7 @@ namespace motor private: + bool_t _has_changed = false ; T _value ; motor::vector< this_input_slot_mtr_t > _inputs ; @@ -52,9 +53,14 @@ namespace motor virtual void_t exchange( void_t ) noexcept { - for ( auto * slot : _inputs ) + // only push data if a changed happened. + if( _has_changed ) { - slot->set_value( _value ) ; + for ( auto * slot : _inputs ) + { + slot->set_value( _value ) ; + } + _has_changed = false ; } } @@ -99,6 +105,7 @@ namespace motor this_ref_t operator = ( T const & v ) noexcept { _value = v ; + _has_changed = true ; return *this ; } @@ -112,6 +119,16 @@ namespace motor void_t set_value( T const v ) noexcept { _value = v ; + _has_changed = true ; + } + + // set the value and immediately exchange with + // connected input slots. + void_t set_and_exchange( T const v ) noexcept + { + _value = v ; + _has_changed = true ; + this->exchange() ; } }; } diff --git a/wire/slot/sheet.hpp b/wire/slot/sheet.hpp index e22f901..34bc97c 100644 --- a/wire/slot/sheet.hpp +++ b/wire/slot/sheet.hpp @@ -4,6 +4,7 @@ #include "input_slot.h" #include "output_slot.h" +#include "other_slot.hpp" #include #include @@ -108,6 +109,13 @@ namespace motor return motor::share( iter->second ) ; } + + bool_t connect( motor::string_in_t name, typename motor::wire::other_slot< T >::type_safe_mtr_t slot ) noexcept + { + auto * this_slot = this_t::borrow( name ) ; + if( this_slot == nullptr ) return false ; + return this_slot->connect( slot ) ; + } }; motor_typedefs( sheet< motor::wire::ioutput_slot >, outputs ) ; motor_typedefs( sheet< motor::wire::iinput_slot >, inputs ) ; diff --git a/wire/variable.hpp b/wire/variable.hpp index 5ad0f49..80989a4 100644 --- a/wire/variable.hpp +++ b/wire/variable.hpp @@ -18,6 +18,9 @@ namespace motor private: char const * _name ; + + motor::wire::iinput_slot_ptr_t _in = nullptr ; + motor::wire::ioutput_slot_ptr_t _out = nullptr ; public: @@ -32,31 +35,86 @@ namespace motor public: any( char const * name ) noexcept : _name( name ) {} + any( char const * name, motor::wire::iinput_slot_ptr_t in_, motor::wire::ioutput_slot_ptr_t out_ ) noexcept : + _name( name ), _in( in_ ), _out( out_ ) {} + any( this_cref_t ) = delete ; - any( this_rref_t rhv ) noexcept : _name( motor::move( rhv._name ) ){ } - virtual ~any( void_t ) noexcept {} + any( this_rref_t rhv ) noexcept : _name( motor::move( rhv._name ) ), + _in( motor::move( rhv._in ) ), _out( motor::move( rhv._out ) ){ } + + virtual ~any( void_t ) noexcept + { + motor::release( motor::move( _in ) ) ; + motor::release( motor::move( _out ) ) ; + } char const * name( void_t ) const noexcept { return _name ; } - inputs_t inputs( void_t ) noexcept { inputs_t ret ; this_t::inspect( [&]( this_ref_t any_in, member_info_in_t info ) { - ret.add( info.full_name, any_in.get_input() ) ; + ret.add( info.full_name, any_in.get_is() ) ; } ) ; return ret ; } public: - virtual void_t update( void_t ) noexcept = 0 ; - virtual motor::wire::iinput_slot_mtr_safe_t get_input( void_t ) noexcept = 0 ; - + // return bool if anything changed. + virtual bool_t update( void_t ) noexcept = 0 ; + + motor::wire::iinput_slot_mtr_safe_t get_is( void_t ) noexcept + { + return motor::share( _in ) ; + } + + motor::wire::ioutput_slot_mtr_safe_t get_os( void_t ) noexcept + { + return motor::share( _out ) ; + } + + protected: + + template< typename T > + motor::core::mtr_safe< T > get_is( void_t ) noexcept + { + return motor::share( reinterpret_cast< T * >( _in ) ) ; + } + + template< typename T > + T * borrow_is( void_t ) noexcept + { + return reinterpret_cast( _in ) ; + } + + template< typename T > + T const * borrow_is( void_t ) const noexcept + { + return reinterpret_cast( _in ) ; + } + + template< typename T > + motor::core::mtr_safe< T > get_os( void_t ) noexcept + { + return motor::share( reinterpret_cast( _out ) ) ; + } + + template< typename T > + T * borrow_os( void_t ) noexcept + { + return reinterpret_cast( _out ) ; + } + + template< typename T > + T const * borrow_os( void_t ) const noexcept + { + return reinterpret_cast( _out ) ; + } public: @@ -102,44 +160,40 @@ namespace motor using in_t = motor::wire::input_slot< T > ; using out_t = motor::wire::output_slot< T > ; - private: - - in_t * _in = motor::shared( in_t() ) ; - out_t * _out = motor::shared( out_t() ) ; - - public: - variable( char const * const name ) noexcept : base_t( name ) {} - variable( this_cref_t ) = delete ; - variable( this_rref_t rhv ) noexcept : - _out( motor::move( rhv._out ) ), _in( motor::move( rhv._in ) ) - { - } + variable( char const * const name ) noexcept : base_t( name, + motor::shared( in_t() ), motor::shared( out_t() ) ) {} - virtual ~variable( void_t ) noexcept - { - motor::release( motor::move( _in ) ) ; - motor::release( motor::move( _out ) ) ; - } + variable( this_cref_t ) = delete ; + variable( this_rref_t rhv ) noexcept : base_t( std::move( rhv ) ){} + virtual ~variable( void_t ) noexcept {} public: - virtual void_t update( void_t ) noexcept + // @note inputs should have pushed value. + virtual bool_t update( void_t ) noexcept { - _in->exchange() ; - *_out = _in->get_value() ; + T value ; + if( base_t::borrow_is()->get_value_and_reset( value ) ) + { + base_t::borrow_os()->set_and_exchange( value ) ; + return true ; + } + return false ; } + // get output slot value T const & get_value( void_t ) const noexcept { - return _in->get_value() ; + return base_t::borrow_os()->get_value() ; } - virtual motor::wire::iinput_slot_mtr_safe_t get_input( void_t ) noexcept + // set input slot + void_t set_value( T const & v ) noexcept { - return motor::share( _in ) ; + return base_t::borrow_is()->set_value( v ) ; } };