// ====================================================================== // Consumer::~Consumer // ====================================================================== Consumer::~Consumer (void) { YAT_TRACE("Consumer::~Consumer"); #if defined (YAT_DEBUG) YAT_LOG("Consumer::statistics::ctrl msg:: " << this->ctrl_msg_counter); YAT_LOG("Consumer::statistics::user msg:: " << this->user_msg_counter); YAT_LOG("Consumer::statistics::lost msg:: " << this->lost_msg_counter); YAT_LOG("Consumer::statistics::wrong order msg:: " << this->wrong_order_msg_counter); #endif }
// ====================================================================== // Task::~Task // ====================================================================== Task::~Task () { YAT_TRACE("Task::~Task"); #if defined (YAT_DEBUG) YAT_LOG("Task::run_undetached::entered " << this->next_msg_counter << " times in MsgQ::next_message"); YAT_LOG("Task::run_undetached::ctrl msg:: " << this->ctrl_msg_counter); YAT_LOG("Task::run_undetached::user msg:: " << this->user_msg_counter); YAT_LOG("Task::run_undetached::total processed msg:: " << this->user_msg_counter + this->ctrl_msg_counter); #endif }
// ====================================================================== // Task::wait_msg_handled // ====================================================================== void Task::wait_msg_handled (Message * _msg, size_t _tmo_ms) throw (Exception) { YAT_TRACE("Task::wait_msg_handled"); //- check input if (! _msg || ! _msg->waitable()) { if (_msg) _msg->release(); THROW_YAT_ERROR("INVALID_ARGUMENT", "invalid message [either null or not waitable]", "Task::wait_msg_handled"); } try { //- post a shallow copy of the msg this->msg_q_.post(_msg->duplicate()); } catch (...) { _msg->release(); THROW_YAT_ERROR("INTERNAL_ERROR", "message could not be posted", "Task::wait_msg_handled"); } YAT_LOG("Task::wait_msg_handled::waiting for msg [" << std::hex << (void*)_msg << std::dec << "] to be handled"); //- wait for the msg to be handled or tmo expiration if (_msg->wait_processed(_tmo_ms)) { YAT_LOG("Task::wait_msg_handled::msg [" << std::hex << (void*)_msg << std::dec << "] handled [gave error::" << (_msg->has_error() ? "yes" : "no") << "]" ); Exception msg_exception; bool msg_gave_error = _msg->has_error(); //- to store error localy before releasing msg if (msg_gave_error) msg_exception = _msg->get_error(); //- release msg _msg->release(); //- throw an exception if msg gave error if (msg_gave_error) throw msg_exception; //- msg did not gave error, just return return; } //- too bad, timeout expired... YAT_LOG("Task::wait_msg_handled::timeout expired while waiting for msg [" << std::hex << (void*)_msg << std::dec << "] to be handled"); //- release msg _msg->release(); //- throw timeout exception THROW_YAT_ERROR("TIMEOUT_EXPIRED", "timeout expired while waiting for message to be handled", "Task::wait_msg_handled"); }
// ====================================================================== // Task::exit // ====================================================================== void Task::exit () throw (Exception) { YAT_TRACE("Task::exit"); //- we may have to implicitly delete the thread bool delete_self = false; //- enter critical section this->m_lock.lock(); //- get underlying thread state Thread::State ts = this->state_i(); //- if the thread is running, then ask it to exit if (ts == yat::Thread::STATE_RUNNING) { yat::Message * msg = 0; try { msg = Message::allocate (yat::TASK_EXIT, EXIT_MSG_PRIORITY, true); } catch (Exception &ex) { this->m_lock.unlock(); RETHROW_YAT_ERROR(ex, "SOFTWARE_ERROR", "Could not stop task [yat::Message allocation failed]", "Task::exit"); } catch (...) { this->m_lock.unlock(); THROW_YAT_ERROR("UNKNOWN_ERROR", "Could not stop task [yat::Message allocation failed]", "Task::exit"); } //- unlock the thread lock (avoid deadlock during message handling) this->m_lock.unlock(); try { //- ... then wait for TASK_EXIT msg to be handled //- TODO: change kINFINITE_WAIT to a more flexible TIMEOUT YAT_LOG("Task::exit - waiting for the TASK_EXIT msg to be handled"); this->wait_msg_handled (msg, kINFINITE_WAIT); } catch (...) { //- ignore any error } //- wait for the thread to actually quit try { Thread::IOArg dummy = 0; YAT_LOG("Task::exit - about to join with the underlying thread"); this->join (&dummy); } catch (...) { //- ignore any error } } else if (ts == yat::Thread::STATE_NEW) { //- delete the thread (instanciated but never been started) YAT_LOG("Task::exit - about to delete the thread [has never been started]"); delete_self = true; //- leave critical section this->m_lock.unlock(); } else { //- nothing to do... YAT_LOG("Task::exit - do nothing"); //- leave critical section this->m_lock.unlock(); } //- delete (if required) if (delete_self) { YAT_LOG("Task::exit - deleting <this> Task instance"); delete this; } }
// ============================================================================ // Task::run_undetached // ============================================================================ void * Task::run_undetached (void *) { YAT_TRACE("Task::run_undetached"); #if defined (YAT_DEBUG) yat::Timestamp last_notification_timestamp, now; #endif //- init flag - set to true when TASK_INIT received bool received_init_msg = false; //- exit flag - set to true when TASK_EXIT received bool received_exit_msg = false; size_t msg_type; Message * msg = 0; //- actual tmo on msg waiting size_t tmo = this->actual_timeout(); //- trick: avoid handling TIMEOUT messages before INIT is itself handled //- may be the case for very short Task timeout do { //- release any previously obtained msg if (msg) msg->release(); #if defined (YAT_DEBUG) this->next_msg_counter++; #endif //- get/wait next message from the msgQ msg = this->msg_q_.next_message (tmo); //- mark TASK_INIT has received received_init_msg = true; } while (! msg || msg->type() != TASK_INIT); //- enter thread's main loop while (! received_exit_msg) { //- actual tmo on msg waiting tmo = this->actual_timeout(); #if defined (YAT_DEBUG) YAT_LOG("Task::run_undetached::waiting next msg or tmo::" << this->actual_timeout()); #endif //- get/wait next message from the msgQ if (! msg) { do { #if defined (YAT_DEBUG) this->next_msg_counter++; #endif //- get next message msg = this->msg_q_.next_message (tmo); //- do not handle TASK_INIT twice if (msg && msg->type() == TASK_INIT && received_init_msg) { msg->release(); msg = 0; } } while (! msg); } #if defined (YAT_DEBUG) _GET_TIME (now); YAT_LOG("Task::run_undetached::handling msg::elapsed msecs since last msg::" << _ELAPSED_MSEC(last_notification_timestamp, now) << " - actual tmo::" << this->actual_timeout()); _GET_TIME (last_notification_timestamp); #endif //- set msg user data msg->user_data(this->user_data_); //- we may need msg type after msg release msg_type = msg->type(); #if defined (YAT_DEBUG) if (msg->is_task_ctrl_message ()) this->ctrl_msg_counter++; else this->user_msg_counter++; #endif YAT_LOG("Task::run_undetached::handling msg [" << std::hex << (void*)msg << std::dec << "]"); //- got a valid message from message Q try { //- std::cout << "Task::handling msg::" //- << std::hex //- << long(msg) //- << std::dec //- << "::" //- << msg->to_string() //- << std::endl; //- call message handler if (this->lock_msg_handling_) { //- enter critical section MutexLock guard (this->m_lock); this->handle_message (*msg); } else { this->handle_message (*msg); } } catch (const Exception& e) { //- store exception into the message msg->set_error(e); } catch (...) { Exception e("UNKNOWN_ERROR", "unknown error caught while handling msg", "Task::run_undetached"); //- store exception into the message msg->set_error(e); } YAT_LOG("Task::run_undetached::msg [" << std::hex << (void*)msg << std::dec << "] handled - notifying waiters"); //- mark message as "processed" (this will signal waiters if any) msg->processed(); //- release our msg ref msg->release(); //- abort requested? if (msg_type == TASK_EXIT) { //- close the msgQ this->msg_q_.close(); //- mark TASK_EXIT as received (exit thread's main loop) received_exit_msg = true; } //- reset msg in order to get next msg from msgQ msg = 0; } //- thread's while loop return 0; }
// ============================================================================ // UnsolicitedMsgReader::handle_message // ============================================================================ void UnsolicitedMsgReader::handle_message (yat::Message& _msg) throw (yat::Exception) { YAT_TRACE("galil::UnsolicitedMsgReader::handle_message"); //- The Task's lock_ is locked //------------------------------------------------------------------- //- YAT_LOG("UnsolicitedMsgReader::handle_message::receiving msg " << _msg.to_string()); //- handle msg switch (_msg.type()) { //- THREAD_INIT ---------------------- case yat::TASK_INIT: { //- "initialization" code goes here YAT_LOG("UnsolicitedMsgReader::handle_message::THREAD_INIT::thread is starting up"); } break; //- THREAD_EXIT ---------------------- case yat::TASK_EXIT: { //- "release" code goes here YAT_LOG("UnsolicitedMsgReader::handle_message::THREAD_EXIT::thread is quitting"); } break; //- THREAD_PERIODIC ------------------ case yat::TASK_PERIODIC: { //- enter critical section yat::AutoMutex<yat::Mutex> guard(this->Task::m_lock); //- get unsolicited msg try { //- code relative to the task's periodic job goes here //- YAT_LOG("UnsolicitedMsgReader::handle_message::handling THREAD_PERIODIC msg"); std::string unsolicited_msg; this->hw_io()->out(unsolicited_msg); if (unsolicited_msg.size()) { YAT_LOG("***************************************************************************"); YAT_LOG("* UnsolicitedMsgReader::got the following unsolicited msg from controller *"); YAT_LOG("***************************************************************************"); YAT_LOG("unsolicited msg length..." << unsolicited_msg.size()); YAT_LOG("unsolicited msg.........." << unsolicited_msg); YAT_LOG("***************************************************************************"); } } catch (Tango::DevFailed& te) { YAT_LOG("UnsolicitedMsgReader::handle_message::TANGO exception caught"); _TANGO_TO_YAT_EXCEPTION(te, ye); throw ye; } catch (...) { YAT_LOG("UnsolicitedMsgReader::handle_message::UNKNOWN exception caught"); throw; } } break; default: //- YAT_LOG("UnsolicitedMsgReader::handle_message::unhandled msg type received"); break; } //- YAT_LOG("UnsolicitedMsgReader::handle_message::message_handler:msg " << _msg.to_string() << " successfully handled"); }
// ============================================================================ // UnsolicitedMsgReader::configure // ============================================================================ void UnsolicitedMsgReader::configure (const Config& _cfg) throw (Tango::DevFailed) { YAT_TRACE("galil::UnsolicitedMsgReader::UnsolicitedMsgReader"); //- enter critical section yat::AutoMutex<yat::Mutex> guard(this->Task::m_lock); //- copy configuration this->m_cfg = _cfg; //- enable periodic msgs this->enable_periodic_msg(true); this->set_periodic_msg_period(kDEFAULT_USMR_PERIOD); //- (re)open connection to peer try { this->m_hw_io->reopen(_cfg.galilbox_ip_addr, _cfg.galilbox_port); } catch (const std::bad_alloc&) { THROW_DEVFAILED(_CPTC("OUT_OF_MEMORY"), _CPTC("failed to connect to the controller [HWIO instanciation failed]"), _CPTC("galil::UnsolicitedMsgReader::configure")); } catch (Tango::DevFailed& df) { RETHROW_DEVFAILED(df, _CPTC("SOFTWARE_MEMORY"), _CPTC("failed to connect to the controller [Tango exception caught]"), _CPTC("galil::UnsolicitedMsgReader::configure")); } catch (...) { THROW_DEVFAILED(_CPTC("UNKNOWN_ERROR"), _CPTC("failed to connect to the controller [unknown exception caught]"), _CPTC("galil::UnsolicitedMsgReader::configure")); } try { //- disable unsolicited char "marking" [see CW cmd doc] yat::OSStream cmd; cmd << "CW2\r"; this->m_hw_io->in(cmd.str(), IOCheckError); //- redirect unsolicited msg to the connection handle we are using [using CF cmd] cmd.str(""); cmd << "CF" << this->m_hw_io->com_handle() << "\r"; this->m_hw_io->in(cmd.str(), IOCheckError); YAT_LOG("UnsolicitedMsgReader::configure::unsolicited msgs successfully redirected"); } catch (Tango::DevFailed& df) { RETHROW_DEVFAILED(df, _CPTC("SOFTWARE_MEMORY"), _CPTC("failed to redirect unsolicited messages [Tango exception caught]"), _CPTC("galil::UnsolicitedMsgReader::configure")); } catch (...) { THROW_DEVFAILED(_CPTC("UNKNOWN_ERROR"), _CPTC("failed to redirect unsolicited messages [unknown exception caught]"), _CPTC("galil::UnsolicitedMsgReader::configure")); } //- start the task if not running if (this->state() != yat::Thread::STATE_RUNNING) this->go(_cfg.startup_timeout_ms); }
// ============================================================================ // Consumer::handle_message // ============================================================================ void Consumer::handle_message (yat::Message& _msg) { //- YAT_TRACE("Consumer::handle_message"); //- handle msg switch (_msg.type()) { //- TASK_INIT ---------------------- case yat::TASK_INIT: { //- "initialization" code goes here YAT_LOG("Consumer::handle_message::TASK_INIT::task is starting up"); this->ctrl_msg_counter++; } break; //- TASK_EXIT ---------------------- case yat::TASK_EXIT: { //- "release" code goes here YAT_LOG("Consumer::handle_message::TASK_EXIT::task is quitting"); this->ctrl_msg_counter++; } break; //- TASK_PERIODIC ------------------ case yat::TASK_PERIODIC: { //- code relative to the task's periodic job goes here YAT_LOG("Consumer::handle_message::handling TASK_PERIODIC msg"); } break; //- TASK_TIMEOUT ------------------- case yat::TASK_TIMEOUT: { //- code relative to the task's tmo handling goes here YAT_LOG("Consumer::handle_message::handling TASK_TIMEOUT msg"); } break; //- USER_DEFINED_MSG ----------------- case kDUMMY_MSG: { //- YAT_LOG("Consumer::handle_message::handling kDUMMY_MSG user msg"); this->user_msg_counter++; #if defined (YAT_DEBUG) if (_msg.id() < last_msg_id) this->wrong_order_msg_counter++; else this->lost_msg_counter += _msg.id() - (this->last_msg_id + 1); #endif //- simulate some time consuming activity yat::ThreadingUtilities::sleep(0, 10000); } break; //- kDATA_MSG ------------------- case kDATA_MSG: { //- code relative to the task's tmo handling goes here SharedBuffer* sb = _msg.detach_data<SharedBuffer>(); YAT_LOG("got a SharedBuffer containing " << sb->length() << " elements"); sb->release(); } break; default: YAT_LOG("Consumer::handle_message::unhandled msg type received"); break; } #if defined (YAT_DEBUG) this->last_msg_id = _msg.id(); #endif }
// ============================================================================ // Box::ucode_version // ============================================================================ const std::string Box::ucode_version () throw (Tango::DevFailed) { YAT_TRACE("galil::Box::ucode_version"); //- new style (V2.2 and later) �code variable try { std::string gen_rev; std::string spe_rev; //- get the McRev SHARED_HW_IO->inout(std::string("McRevGen=?\r"), gen_rev); SHARED_HW_IO->inout(std::string("McRevSpe=?\r"), spe_rev); YAT_LOG("galil::Box::ucode_version::controller returned (as string): " << "\n generic revision : " << gen_rev << "\n specific revision : " << spe_rev); unsigned long ucode_gen_rev = yat::XString<unsigned long>::to_num(gen_rev); unsigned long ucode_spe_rev = yat::XString<unsigned long>::to_num(spe_rev); YAT_LOG("galil::Box::ucode_version::controller returned (as ulong): " << "\n generic revision : " << ucode_gen_rev << "\n specific revision : " << ucode_spe_rev); unsigned long generic_rev = (ucode_gen_rev & 0xFF000000) / 0x1000000; unsigned long generic_evo = (ucode_gen_rev & 0x00FF0000) / 0x0010000; unsigned long generic_evo_minor = (ucode_gen_rev & 0x0000FF00) / 0x0000100; unsigned long generic_evo_min_dev = (ucode_gen_rev & 0x000000FF); unsigned long specific_rev = (ucode_spe_rev & 0xFF000000) / 0x1000000; unsigned long specific_evo = (ucode_spe_rev & 0x00FF0000) / 0x0010000; unsigned long specific_evo_minor = (ucode_spe_rev & 0x0000FF00) / 0x0000100; unsigned long specific_evo_min_dev = (ucode_spe_rev & 0x000000FF); yat::OSStream txt; txt << "Generic uCode : " << generic_rev << "." << generic_evo << "." << generic_evo_minor << "." << generic_evo_min_dev << std::endl << "Specific uCode : " << specific_rev << "." << specific_evo << "." << specific_evo_minor << "." << specific_evo_min_dev; return txt.str(); } catch (yat::Exception & ye) { _YAT_TO_TANGO_EXCEPTION(ye, te); ERROR_STREAM << te << std::endl; RETHROW_DEVFAILED(te, _CPTC("SOFTWARE_ERROR"), _CPTC("yat::Exception caught while trying to obtain Box::ucode_version"), _CPTC("Box::ucode_version")); } catch (Tango::DevFailed& df) { ERROR_STREAM << "Box::�code_version trying to get �code versions McRevGen and McRevSpe catched DevFailed : \n" << df << std::endl; //- do not rethrow, let a chance to old McRev variable } catch (...) { ERROR_STREAM << "trying to get �code versions McRevGen and McRevSpe catched DevFailed : " << "Box::ucode_version::unknown exception caught" << std::endl; //- do not throw, let a chance to old McRev variable } //- old style (V2.1 and before) �code variable std::string ucode_rev_str; try { //- get the McRev SHARED_HW_IO->inout(std::string("McRev=?\r"), ucode_rev_str); } catch (Tango::DevFailed& df) { ERROR_STREAM << df << std::endl; RETHROW_DEVFAILED(df, _CPTC("COMMUNICATION_FAILED"), _CPTC("could not obtain the uCode version number"), _CPTC("galil::Box::ucode_version")); } catch (...) { ERROR_STREAM << "Box::ucode_version::unknown exception caught" << std::endl; THROW_DEVFAILED(_CPTC("UNKNOWN_ERROR"), _CPTC("unknown exception caught while trying to obtain the uCode version number"), _CPTC("galil::Box::ucode_version")); } YAT_LOG("galil::Box::ucode_version::controller returned (as string): " << ucode_rev_str); unsigned long ucode_rev = 0; try { ucode_rev = yat::XString<unsigned long>::to_num(ucode_rev_str); } catch (yat::Exception & ye) { _YAT_TO_TANGO_EXCEPTION(ye, te); ERROR_STREAM << te << std::endl; RETHROW_DEVFAILED(te, _CPTC("SOFTWARE_ERROR"), _CPTC("yat::Exception caught while trying to obtain Box::ucode_version"), _CPTC("Box::ucode_version")); } YAT_LOG("galil::Box::ucode_version::controller returned (as ulong): " << ucode_rev); unsigned long generic_rev = (ucode_rev & 0xFF000000) / 0x1000000; unsigned long generic_evo = (ucode_rev & 0x00FF0000) / 0x0010000; unsigned long specific_rev = (ucode_rev & 0x0000FF00) / 0x0000100; unsigned long specific_evo = ucode_rev & 0x000000FF; yat::OSStream txt; txt << "Generic uCode: " << generic_rev << "." << generic_evo << " - " << "Specific uCode: " << specific_rev << "." << specific_evo; return txt.str(); }
// ---------------------------------------------------------------------------- // Socket::receive // ---------------------------------------------------------------------------- size_t Socket::receive (char * ib, size_t nb) throw (SocketException) { YAT_TRACE("yat::Socket::receive [char*]"); CHECK_SOCK_DESC("yat::Socket::receive"); size_t rb = 0; size_t total_rb = 0; bool was_interrupted = false; do { //- read some data rb = ::recv(this->m_os_desc, ib + total_rb, (int)(nb - total_rb), 0); //- in case of error/exception.... if (rb <= 0) { //- connection may have been reset/closed by peer if (rb == 0) { THROW_SOCKET_ERROR(SoErr_ConnectionClosed, "OS <recv> call failed", "yat::Socket::receive"); } //- operation may block caller (for non blocking socket) if (this->current_op_is_blocking()) { THROW_SOCKET_ERROR(SoErr_WouldBlock, "OS <recv> call failed", "yat::Socket::receive"); } #if ! defined(WIN32) if (errno == EINTR) { was_interrupted = true; continue; } #else if (::WSAGetLastError() == WSAECONNRESET) { this->close(); THROW_SOCKET_ERROR(SoErr_ConnectionClosed, "OS <recv> call failed", "yat::Socket::receive"); } #endif //- reamining error cases THROW_SOCKET_ERROR(err_no, "OS <recv> call failed", "yat::Socket::receive"); } total_rb += rb; } while (was_interrupted); YAT_LOG("yat::Socket::receive::got " << rb << " bytes from peer"); return total_rb; }