From: Ron F. <ro...@us...> - 2007-02-26 18:29:26
|
Update of /cvsroot/nscldaq/clients/controlpush In directory sc8-pr-cvs7.sourceforge.net:/tmp/cvs-serv19676 Modified Files: CChannel.cpp CChannel.h CTCLChannelCommand.cpp CTCLChannelCommand.h CTCLEpicsPackage.cpp Log Message: Fix some issues that may have led to lockup and failures in the tcl epics channel layer stuff. Index: CChannel.h =================================================================== RCS file: /cvsroot/nscldaq/clients/controlpush/CChannel.h,v retrieving revision 8.5 retrieving revision 8.6 diff -C2 -d -r8.5 -r8.6 *** CChannel.h 28 Sep 2006 19:45:00 -0000 8.5 --- CChannel.h 26 Feb 2007 18:27:56 -0000 8.6 *************** *** 65,68 **** --- 65,69 ---- Slot m_pHandler; void* m_pHandlerData; + evid m_eventHandlerId; public: Index: CTCLEpicsPackage.cpp =================================================================== RCS file: /cvsroot/nscldaq/clients/controlpush/CTCLEpicsPackage.cpp,v retrieving revision 8.3 retrieving revision 8.4 diff -C2 -d -r8.3 -r8.4 *** CTCLEpicsPackage.cpp 10 Oct 2006 14:08:37 -0000 8.3 --- CTCLEpicsPackage.cpp 26 Feb 2007 18:27:56 -0000 8.4 *************** *** 18,21 **** --- 18,23 ---- #include "CTCLEpicsCommand.h" #include "CTCLChannelCommand.h" + #include <CChannel.h> + #include <TCLInterpreter.h> #include <cadef.h> *************** *** 28,32 **** #endif - typedef map<string,CTCLChannelCommand*> CommandMap; static char* version= "1.0"; --- 30,33 ---- *************** *** 34,67 **** static const int caPollInterval(16); // ms per epics poll. - static CommandMap linkages; static void pollEpics(ClientData ignored) { ! ca_pend_event(0.00000001); Tcl_CreateTimerHandler(caPollInterval, pollEpics, (ClientData)NULL); - CommandMap::iterator i = linkages.begin(); - while (i != linkages.end()) { - CTCLChannelCommand* pCommand = i->second; - if(pCommand->hasChanged()) { - pCommand->UpdateLinkedVariable(); - } - i++; - } - } ! void addLinkage(CTCLChannelCommand* pCommand) ! { ! linkages[pCommand->getName()] = pCommand; ! } ! void removeLinkage(CTCLChannelCommand* pCommand) ! { ! CommandMap::iterator i = linkages.find(pCommand->getName()); ! if (i != linkages.end()) { ! linkages.erase(i); ! } ! } extern "C" { --- 35,52 ---- static const int caPollInterval(16); // ms per epics poll. + // Ensures that ca_pend_event is called often enough + // for epics to stay happy. + // static void pollEpics(ClientData ignored) { ! CChannel::doEvents(0.01); Tcl_CreateTimerHandler(caPollInterval, pollEpics, (ClientData)NULL); } ! ! extern "C" { Index: CChannel.cpp =================================================================== RCS file: /cvsroot/nscldaq/clients/controlpush/CChannel.cpp,v retrieving revision 8.6 retrieving revision 8.7 diff -C2 -d -r8.6 -r8.7 *** CChannel.cpp 31 Oct 2006 22:15:47 -0000 8.6 --- CChannel.cpp 26 Feb 2007 18:27:56 -0000 8.7 *************** *** 31,35 **** m_pConverter(0), m_pHandler(0), ! m_pHandlerData(0) { } --- 31,36 ---- m_pConverter(0), m_pHandler(0), ! m_pHandlerData(0), ! m_eventHandlerId(0) { } *************** *** 40,44 **** --- 41,47 ---- { if (m_fConnected || (m_fUpdateHandlerEstablished)) { + ca_clear_event(m_eventHandlerId); ca_clear_channel(m_nChannel); + doEvents(0.1); } delete m_pConverter; *************** *** 192,196 **** pChannel->m_pConverter = CConversionFactory::Converter(ca_field_type(id)); ca_add_event(pChannel->m_pConverter->requestType(), ! id, UpdateHandler, (void*)pChannel, NULL); pChannel->m_fUpdateHandlerEstablished; } --- 195,200 ---- pChannel->m_pConverter = CConversionFactory::Converter(ca_field_type(id)); ca_add_event(pChannel->m_pConverter->requestType(), ! id, UpdateHandler, (void*)pChannel, ! &(pChannel->m_eventHandlerId)); pChannel->m_fUpdateHandlerEstablished; } Index: CTCLChannelCommand.h =================================================================== RCS file: /cvsroot/nscldaq/clients/controlpush/CTCLChannelCommand.h,v retrieving revision 8.3 retrieving revision 8.4 diff -C2 -d -r8.3 -r8.4 *** CTCLChannelCommand.h 5 Oct 2006 12:33:59 -0000 8.3 --- CTCLChannelCommand.h 26 Feb 2007 18:27:56 -0000 8.4 *************** *** 54,61 **** class CTCLChannelCommand : public CTCLObjectProcessor { private: CChannel* m_pChannel; CTCLVariable* m_pLinkedVar; ! bool m_Changed; // Canonicals: --- 54,67 ---- class CTCLChannelCommand : public CTCLObjectProcessor { + // TclEvent queued for changes: + public: + struct ChangeEvent { + Tcl_Event rawEvent; + CTCLChannelCommand* pChangedChannel; + }; private: CChannel* m_pChannel; CTCLVariable* m_pLinkedVar; ! Tcl_ThreadId m_interpreterThread; // Canonicals: *************** *** 75,79 **** void UpdateLinkedVariable(); - bool hasChanged() const; // Utilties: --- 81,84 ---- *************** *** 87,91 **** int Unlink(CTCLInterpreter& interp); STD(string) Usage(); ! static void markChange(CChannel* pChannel, void* pObject); --- 92,98 ---- int Unlink(CTCLInterpreter& interp); STD(string) Usage(); ! static void markChange(CChannel* pChannel, ! void* pObject); // Called in Epics thread ! static int update(Tcl_Event* pEvent, int flags); // Called in Tcl thread. Index: CTCLChannelCommand.cpp =================================================================== RCS file: /cvsroot/nscldaq/clients/controlpush/CTCLChannelCommand.cpp,v retrieving revision 8.4 retrieving revision 8.5 diff -C2 -d -r8.4 -r8.5 *** CTCLChannelCommand.cpp 31 Oct 2006 18:41:16 -0000 8.4 --- CTCLChannelCommand.cpp 26 Feb 2007 18:27:56 -0000 8.5 *************** *** 41,49 **** CTCLObjectProcessor(interp, name), m_pChannel(0), ! m_pLinkedVar(0), ! m_Changed(false) { m_pChannel = new CChannel(name); m_pChannel->Connect(); } /*! --- 41,49 ---- CTCLObjectProcessor(interp, name), m_pChannel(0), ! m_pLinkedVar(0) { m_pChannel = new CChannel(name); m_pChannel->Connect(); + m_interpreterThread = Tcl_GetCurrentThread(); } /*! *************** *** 54,59 **** delete m_pChannel; - removeLinkage(this); delete m_pLinkedVar; } --- 54,61 ---- delete m_pChannel; delete m_pLinkedVar; + m_pChannel = 0; + m_pLinkedVar = 0; + } *************** *** 289,298 **** if (m_pLinkedVar) { - removeLinkage(this); delete m_pLinkedVar; } m_pLinkedVar = new CTCLVariable(&interp, tclVarName, kfFALSE); m_pLinkedVar->Set(m_pChannel->getValue().c_str(), TCL_GLOBAL_ONLY); - addLinkage(this); m_pChannel->setSlot(CTCLChannelCommand::markChange, this); --- 291,299 ---- if (m_pLinkedVar) { delete m_pLinkedVar; + } m_pLinkedVar = new CTCLVariable(&interp, tclVarName, kfFALSE); m_pLinkedVar->Set(m_pChannel->getValue().c_str(), TCL_GLOBAL_ONLY); m_pChannel->setSlot(CTCLChannelCommand::markChange, this); *************** *** 307,321 **** { if (m_pLinkedVar) { - removeLinkage(this); m_pChannel->setSlot(NULL, NULL); delete m_pLinkedVar; } } ! bool ! CTCLChannelCommand::hasChanged() const ! { ! return m_Changed; ! } /* Provide command usage. --- 308,318 ---- { if (m_pLinkedVar) { m_pChannel->setSlot(NULL, NULL); delete m_pLinkedVar; + m_pLinkedVar = 0; } } ! /* Provide command usage. *************** *** 347,351 **** { if (m_pLinkedVar) { - m_Changed = false; m_pLinkedVar->Set(m_pChannel->getValue().c_str(), TCL_GLOBAL_ONLY); } --- 344,347 ---- *************** *** 353,357 **** /* ! Set the changed flag */ void --- 349,353 ---- /* ! Queue a Tcl event to actually do the update. */ void *************** *** 360,363 **** CTCLChannelCommand* command = static_cast<CTCLChannelCommand*>(pObject); ! command->m_Changed = true; } --- 356,377 ---- CTCLChannelCommand* command = static_cast<CTCLChannelCommand*>(pObject); ! ChangeEvent* pEvent = (ChangeEvent*)Tcl_Alloc(sizeof(ChangeEvent)); ! pEvent->rawEvent.proc = CTCLChannelCommand::update; ! pEvent->pChangedChannel = command; ! Tcl_ThreadQueueEvent(command->m_interpreterThread, (Tcl_Event*)pEvent, TCL_QUEUE_TAIL); ! Tcl_ThreadAlert(command->m_interpreterThread); ! } ! ! /* ! This function is called in the thread of the interpreter after ! an epics variable has changed. ! */ ! int ! CTCLChannelCommand::update(Tcl_Event* p, int flags) ! { ! CTCLChannelCommand::ChangeEvent* pEvent = (CTCLChannelCommand::ChangeEvent*)p; ! pEvent->pChangedChannel->UpdateLinkedVariable(); ! ! return 1; ! } |