diff --git a/cwFlow.cpp b/cwFlow.cpp index b32f2c9..348bb75 100644 --- a/cwFlow.cpp +++ b/cwFlow.cpp @@ -754,6 +754,37 @@ namespace cw return rc; } + void _make_flow_to_ui_callback( flow_t* p ) + { + + // There is no concurrent contention for the linked list when + // this function is called and so all accesses use relaxed memory order. + + // Get the first variable to send to the UI + variable_t* var = p->ui_var_tail->ui_var_link.load(std::memory_order_relaxed); + + while( var!=nullptr) + { + // Send the var to the UI + if( p->ui_callback != nullptr ) + p->ui_callback( p->ui_callback_arg, var->ui_var ); + + // Get the next var to send to the UI + variable_t* var0 = var->ui_var_link.load(std::memory_order_relaxed); + + // Nullify the list links as they are used + var->ui_var_link.store(nullptr,std::memory_order_relaxed); + + var = var0; + } + + // Empty the UI message list. + p->ui_var_head.store(&p->ui_var_stub,std::memory_order_relaxed); + p->ui_var_tail = &p->ui_var_stub; + p->ui_var_stub.ui_var_link.store(nullptr,std::memory_order_relaxed); + + } + } } @@ -776,7 +807,9 @@ cw::rc_t cw::flow::create( handle_t& hRef, const object_t* classCfg, const object_t* pgmCfg, const object_t* udpCfg, - const char* proj_dir ) + const char* proj_dir, + ui_callback_t ui_callback, + void* ui_callback_arg) { rc_t rc = kOkRC; bool printClassDictFl = false; @@ -810,6 +843,10 @@ cw::rc_t cw::flow::create( handle_t& hRef, p->maxCycleCount = kInvalidCnt; p->proj_dir = proj_dir; p->printLogHdrFl = true; + p->ui_callback = ui_callback; + p->ui_callback_arg= ui_callback_arg; + p->ui_var_head.store(&p->ui_var_stub); + p->ui_var_tail = &p->ui_var_stub; // parse the optional args if((rc = pgmCfg->readv("network", 0, p->networkCfg, @@ -889,7 +926,8 @@ const char* cw::flow::preset_label( handle_t h, unsigned preset_idx ) if( preset_idx >= p->presetN ) { - + cwLogError(kInvalidArgRC,"The preset index %i is invalid.",preset_idx); + return nullptr; } return p->presetA[ preset_idx ].label; @@ -1032,9 +1070,19 @@ cw::rc_t cw::flow::exec_cycle( handle_t h ) } else { - rc = exec_cycle(*p->net); + // Execute one cycle of the network + if((rc = exec_cycle(*p->net)) == kOkRC ) + { + // During network execution variables which need to update the UI + // are collected in a linked list based on p->ui_var_tail. + // Callback to the UI with those variables here. + _make_flow_to_ui_callback(p); + + } + p->cycleIndex += 1; } + return rc; } @@ -1069,6 +1117,8 @@ cw::rc_t cw::flow::apply_preset( handle_t h, const multi_preset_selector_t& mps return network_apply_preset(*p->net,mps); } +cw::rc_t cw::flow::set_variable_user_id( handle_t h, const ui_var_t* ui_var, unsigned user_id ) +{ return set_variable_user_id( *_handleToPtr(h)->net, ui_var, user_id ); } cw::rc_t cw::flow::set_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, bool value ) diff --git a/cwFlow.h b/cwFlow.h index 0be164d..1735d40 100644 --- a/cwFlow.h +++ b/cwFlow.h @@ -10,7 +10,7 @@ namespace cw void print_abuf( const struct abuf_str* abuf ); void print_external_device( const external_device_t* dev ); - + // Parse the cfg's but don't yet instantiate the network. // Upon completion of this function the caller can // query the network for configuration information which can @@ -18,8 +18,10 @@ namespace cw rc_t create(handle_t& hRef, const object_t* classCfg, // processor class dictionary const object_t* pgmCfg, // top level program cfg - const object_t* udpCfg = nullptr, - const char* projDir = nullptr); + const object_t* udpCfg = nullptr, + const char* projDir = nullptr, + ui_callback_t ui_callback = nullptr, + void* ui_callback_arg = nullptr); // Network cfg. information which is available following create(). bool is_non_real_time( handle_t h ); @@ -32,6 +34,7 @@ namespace cw const char* preset_label( handle_t h, unsigned preset_idx ); // Instantiate the network and prepare for runtime. + // The UI is not available until after initialization. rc_t initialize( handle_t handle, external_device_t* deviceA = nullptr, unsigned deviceN = 0, @@ -66,6 +69,9 @@ namespace cw rc_t get_variable_value( handle_t h, const char* inst_label, const char* var_label, unsigned chIdx, double& valueRef ); + // The 'user_id' shows up as the 'user_id' in the ui_var field. + rc_t set_variable_user_id( handle_t h, const ui_var_t* ui_var, unsigned user_id ); + rc_t set_variable_value( handle_t h, const ui_var_t* ui_var, bool value ); rc_t set_variable_value( handle_t h, const ui_var_t* ui_var, int value ); rc_t set_variable_value( handle_t h, const ui_var_t* ui_var, unsigned value );