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): |