runtime/PLCObject.py
changeset 2720 971bb3503957
parent 2702 f0a70f0246da
child 2732 a3f0e4148714
equal deleted inserted replaced
2719:745b64e7c695 2720:971bb3503957
   396             raise
   396             raise
   397 
   397 
   398         self.PythonRuntimeCall("init", use_evaluator=False)
   398         self.PythonRuntimeCall("init", use_evaluator=False)
   399 
   399 
   400         self.PythonThreadCondLock = Lock()
   400         self.PythonThreadCondLock = Lock()
   401         self.PythonThreadCond = Condition(self.PythonThreadCondLock)
   401         self.PythonThreadCmdCond = Condition(self.PythonThreadCondLock)
   402         self.PythonThreadCmd = "Wait"
   402         self.PythonThreadAckCond = Condition(self.PythonThreadCondLock)
       
   403         self.PythonThreadCmd = None
       
   404         self.PythonThreadAck = None
   403         self.PythonThread = Thread(target=self.PythonThreadProc, name="PLCPythonThread")
   405         self.PythonThread = Thread(target=self.PythonThreadProc, name="PLCPythonThread")
   404         self.PythonThread.start()
   406         self.PythonThread.start()
   405 
   407 
   406     # used internaly
   408     # used internaly
   407     def PythonRuntimeCleanup(self):
   409     def PythonRuntimeCleanup(self):
   440 
   442 
   441     def PythonThreadProc(self):
   443     def PythonThreadProc(self):
   442         while True:
   444         while True:
   443             self.PythonThreadCondLock.acquire()
   445             self.PythonThreadCondLock.acquire()
   444             cmd = self.PythonThreadCmd
   446             cmd = self.PythonThreadCmd
   445             while cmd == "Wait":
   447             while cmd is None:
   446                 self.PythonThreadCond.wait()
   448                 self.PythonThreadCmdCond.wait()
   447                 cmd = self.PythonThreadCmd
   449                 cmd = self.PythonThreadCmd
   448                 self.PythonThreadCmd = "Wait"
   450             self.PythonThreadCmd = None
   449             self.PythonThreadCondLock.release()
   451             self.PythonThreadCondLock.release()
   450 
   452 
   451             if cmd == "Activate":
   453             if cmd == "PreStart":
       
   454                 self.PreStartPLC()
       
   455                 # Ack once PreStart done, must be finished before StartPLC
       
   456                 self.PythonThreadAcknowledge(cmd)
       
   457             elif cmd == "Start":
       
   458                 # Ack Immediately, for responsiveness
       
   459                 self.PythonThreadAcknowledge(cmd)
   452                 self.PythonRuntimeCall("start")
   460                 self.PythonRuntimeCall("start")
   453                 self.PreStartPLC()
   461                 self.LogMessage("Python extensions started")
   454                 self.PythonThreadLoop()
   462                 self.PythonThreadLoop()
   455                 self.PythonRuntimeCall("stop", reverse_order=True)
   463                 self.PythonRuntimeCall("stop", reverse_order=True)
   456             else:  # "Finish"
   464             elif cmd == "Finish":
       
   465                 self.PythonThreadAcknowledge(cmd)
   457                 break
   466                 break
       
   467 
       
   468     def PythonThreadAcknowledge(self, ack):
       
   469         self.PythonThreadCondLock.acquire()
       
   470         self.PythonThreadAck = ack
       
   471         self.PythonThreadAckCond.notify()
       
   472         self.PythonThreadCondLock.release()
   458 
   473 
   459     def PythonThreadCommand(self, cmd):
   474     def PythonThreadCommand(self, cmd):
   460         self.PythonThreadCondLock.acquire()
   475         self.PythonThreadCondLock.acquire()
   461         self.PythonThreadCmd = cmd
   476         self.PythonThreadCmd = cmd
   462         self.PythonThreadCond.notify()
   477         self.PythonThreadCmdCond.notify()
       
   478         ack = None
       
   479         while ack != cmd:
       
   480             self.PythonThreadAckCond.wait()
       
   481             ack = self.PythonThreadAck
       
   482             self.PythonThreadAck = None
       
   483 
   463         self.PythonThreadCondLock.release()
   484         self.PythonThreadCondLock.release()
   464 
   485 
   465     def _fail(self, msg):
   486     def _fail(self, msg):
   466         self.LogMessage(0, msg)
   487         self.LogMessage(0, msg)
   467         self.PLCStatus = PlcStatus.Broken
   488         self.PLCStatus = PlcStatus.Broken
   481         if self.PLClibraryHandle is None:
   502         if self.PLClibraryHandle is None:
   482             if not self.LoadPLC():
   503             if not self.LoadPLC():
   483                 self._fail(_("Problem starting PLC : can't load PLC"))
   504                 self._fail(_("Problem starting PLC : can't load PLC"))
   484 
   505 
   485         if self.CurrentPLCFilename is not None and self.PLCStatus == PlcStatus.Stopped:
   506         if self.CurrentPLCFilename is not None and self.PLCStatus == PlcStatus.Stopped:
       
   507             self.PythonThreadCommand("PreStart")
   486             c_argv = ctypes.c_char_p * len(self.argv)
   508             c_argv = ctypes.c_char_p * len(self.argv)
   487             res = self._startPLC(len(self.argv), c_argv(*self.argv))
   509             res = self._startPLC(len(self.argv), c_argv(*self.argv))
   488             if res == 0:
   510             if res == 0:
       
   511                 self.LogMessage("PLC started")
   489                 self.PLCStatus = PlcStatus.Started
   512                 self.PLCStatus = PlcStatus.Started
   490                 self.StatusChange()
   513                 self.StatusChange()
   491                 self.PythonThreadCommand("Activate")
   514                 self.PythonThreadCommand("Start")
   492                 self.LogMessage("PLC started")
       
   493             else:
   515             else:
   494                 self._fail(_("Problem starting PLC : error %d" % res))
   516                 self._fail(_("Problem starting PLC : error %d" % res))
   495 
   517 
   496     @RunInMain
   518     @RunInMain
   497     def StopPLC(self):
   519     def StopPLC(self):