runtime/Worker.py
author Edouard Tisserant <edouard@beremiz.fr>
Thu, 05 Dec 2024 16:45:37 +0100
changeset 4061 e0dfe8b8db4a
parent 3851 4e1906d119d5
permissions -rw-r--r--
py_ext: rework logic CSV reader FB output refresh logic.

Saving with CSV write FB now triggers CSV read FBs to refresh outputs immediately.
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     1
#!/usr/bin/env python
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     2
# -*- coding: utf-8 -*-
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     3
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     4
# This file is part of Beremiz runtime.
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     5
#
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     6
# Copyright (C) 2018: Edouard TISSERANT
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     7
#
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     8
# See COPYING.Runtime file for copyrights details.
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
     9
3750
f62625418bff automated conversion using 2to3-3.9 tool
GP Orcullo <kinsamanka@gmail.com>
parents: 3642
diff changeset
    10
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
    11
from threading import Lock, Condition, Thread, get_ident
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    12
2309
d8fb90a2e11f Please pylint and pep8
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2307
diff changeset
    13
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    14
class job(object):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    15
    """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    16
    job to be executed by a worker
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    17
    """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    18
    def __init__(self, call, *args, **kwargs):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    19
        self.job = (call, args, kwargs)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    20
        self.result = None
2604
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
    21
        self.success = None
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    22
        self.exc_info = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    23
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    24
    def do(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    25
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    26
        do the job by executing the call, and deal with exceptions
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    27
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    28
        try:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    29
            call, args, kwargs = self.job
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    30
            self.result = call(*args, **kwargs)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    31
            self.success = True
3753
5256e4bd92e6 remove six.reraise
GP Orcullo <kinsamanka@gmail.com>
parents: 3750
diff changeset
    32
        except Exception as e:
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    33
            self.success = False
3753
5256e4bd92e6 remove six.reraise
GP Orcullo <kinsamanka@gmail.com>
parents: 3750
diff changeset
    34
            self.exc_info = e
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    35
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    36
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    37
class worker(object):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    38
    """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    39
    serialize main thread load/unload of PLC shared objects
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    40
    """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    41
    def __init__(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    42
        # Only one job at a time
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    43
        self._finish = False
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    44
        self._threadID = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    45
        self.mutex = Lock()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    46
        self.todo = Condition(self.mutex)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    47
        self.done = Condition(self.mutex)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    48
        self.free = Condition(self.mutex)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    49
        self.job = None
2611
a1bf03277cec Fixed typo leading to some exception in some rare corner cases in worker.py
Edouard Tisserant
parents: 2604
diff changeset
    50
        self.enabled = False
3642
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
    51
        self.stopper = None
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
    52
        self.own_thread = None
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    53
2536
2747d6e72eb8 Fix invalid python3 syntax
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2492
diff changeset
    54
    def reraise(self, job):
2747d6e72eb8 Fix invalid python3 syntax
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2492
diff changeset
    55
        """
2747d6e72eb8 Fix invalid python3 syntax
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2492
diff changeset
    56
        reraise exception happend in a job
2747d6e72eb8 Fix invalid python3 syntax
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2492
diff changeset
    57
        @param job: job where original exception happend
2747d6e72eb8 Fix invalid python3 syntax
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2492
diff changeset
    58
        """
3753
5256e4bd92e6 remove six.reraise
GP Orcullo <kinsamanka@gmail.com>
parents: 3750
diff changeset
    59
        raise job.exc_info
2536
2747d6e72eb8 Fix invalid python3 syntax
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2492
diff changeset
    60
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    61
    def runloop(self, *args, **kwargs):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    62
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    63
        meant to be called by worker thread (blocking)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    64
        """
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
    65
        self._threadID = get_ident()
2467
fce6ab7ae156 Enure that autostart blocks other @RunInMain PLCObject methods, and _unblocks_ them once autostart is done...
Edouard Tisserant
parents: 2463
diff changeset
    66
        self.mutex.acquire()
2604
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
    67
        self.enabled = True
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    68
        if args or kwargs:
3851
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    69
            self.job = job(*args, **kwargs)
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    70
            self.job.do()
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    71
            # fail if first job fails
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    72
            if not self.job.success:
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    73
                self.reraise(self.job)
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    74
            self.job = None
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    75
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    76
        self.free.notify()
2486
44c2a4e2b84d Fixed deadlock in runtime's Worker. Was discovered while using WAMP and PYRO simultaneously.
Edouard Tisserant
parents: 2467
diff changeset
    77
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    78
        while not self._finish:
3849
c3f4e114af38 Fix untested code in worker.py...
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3846
diff changeset
    79
            self.todo.wait_for(lambda: self.job is not None)
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
    80
            self.job.do()
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
    81
            self.done.notify()
3851
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    82
            self.job = None
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    83
            self.free.notify()
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
    84
            
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    85
        self.mutex.release()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    86
3642
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
    87
    def interleave(self, waker, stopper, *args, **kwargs):
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
    88
        """
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
    89
        as for twisted reactor's interleave, it passes all jobs to waker func
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
    90
        additionaly, it creates a new thread to wait for new job.
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
    91
        """
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
    92
        self.feed = Condition(self.mutex)
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
    93
        self._threadID = get_ident()
3642
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
    94
        self.stopper = stopper
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
    95
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
    96
        def do_pending_job():
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
    97
            self.mutex.acquire()
3851
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    98
            self.job.do()
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
    99
            self.done.notify_all()
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   100
            self.mutex.release()
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   101
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   102
        def wakerfeedingloop():
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   103
            self.mutex.acquire()
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   104
            self.enabled = True
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   105
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   106
            # Handle first job
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   107
            if args or kwargs:
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   108
                self.job = job(*args, **kwargs)
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   109
                waker(do_pending_job)
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   110
                self.done.wait_for(lambda: self.job.success is not None)
3851
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
   111
                # fail if first job fails
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   112
                if not self.job.success:
3851
4e1906d119d5 Runtime: fix non-interleaved worker loop
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3849
diff changeset
   113
                    self.reraise(self.job)
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   114
                self.job = None
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   115
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   116
            self.free.notify()
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   117
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   118
            while not self._finish:
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   119
                self.todo.wait_for(lambda: self.job is not None)
3642
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
   120
                if self._finish:
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
   121
                    break
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   122
                waker(do_pending_job)
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   123
                self.done.wait_for(lambda: self.job.success is not None)
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   124
                self.job = None
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   125
                self.free.notify()
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   126
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   127
            self.mutex.release()
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   128
3585
efdefbad49eb runtime: fix bugs introduced in previous commit, and refactor some code
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3584
diff changeset
   129
        self.own_thread = Thread(target = wakerfeedingloop)
efdefbad49eb runtime: fix bugs introduced in previous commit, and refactor some code
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3584
diff changeset
   130
        self.own_thread.start()
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   131
3585
efdefbad49eb runtime: fix bugs introduced in previous commit, and refactor some code
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3584
diff changeset
   132
    def stop(self):
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   133
        """
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   134
        !interleave
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   135
        """
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   136
        self.mutex.acquire()
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   137
        self._finish = True
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   138
        self.enabled = False
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   139
        self.job = None
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   140
        self.todo.notify()
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   141
        self.done.notify_all()
3584
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   142
        self.mutex.release()
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   143
        self.own_thread.join()
8a54fd58a552 Runtime: wx.app.mainLoop and twisted reactor now share main thread with runtime.Worker.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2611
diff changeset
   144
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   145
    def call(self, *args, **kwargs):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   146
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   147
        creates a job, execute it in worker thread, and deliver result.
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   148
        if job execution raise exception, re-raise same exception
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   149
        meant to be called by non-worker threads, but this is accepted.
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   150
        blocking until job done
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   151
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   152
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   153
        _job = job(*args, **kwargs)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   154
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   155
        if self._threadID == get_ident():
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   156
            # if caller is worker thread execute immediately
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   157
            _job.do()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   158
        else:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   159
            # otherwise notify and wait for completion
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   160
            self.mutex.acquire()
2604
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
   161
            if not self.enabled:
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
   162
                self.mutex.release()
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
   163
                raise EOFError("Worker is disabled")
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   164
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   165
            self.free.wait_for(lambda: self.job is None)
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   166
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   167
            self.job = _job
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   168
            self.todo.notify()
3846
cf027bfe2653 Runtime/MainWorker: fix blocking race condition
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3753
diff changeset
   169
            self.done.wait_for(lambda: _job.success is not None)
2486
44c2a4e2b84d Fixed deadlock in runtime's Worker. Was discovered while using WAMP and PYRO simultaneously.
Edouard Tisserant
parents: 2467
diff changeset
   170
            self.free.notify()
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   171
            self.mutex.release()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   172
2604
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
   173
        if _job.success is None:
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
   174
            raise EOFError("Worker job was interrupted")
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
   175
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   176
        if _job.success:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   177
            return _job.result
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   178
        else:
2536
2747d6e72eb8 Fix invalid python3 syntax
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2492
diff changeset
   179
            self.reraise(_job)
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   180
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   181
    def quit(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   182
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   183
        unblocks main thread, and terminate execution of runloop()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   184
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   185
        # mark queue
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   186
        self._finish = True
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   187
        self.mutex.acquire()
2604
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
   188
        self.enabled = False
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   189
        self.job = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   190
        self.todo.notify()
2604
c8a25a3a7f8b Runtime worker : unblock the last waiting job and prevent any new job to wait when Main Worker is being shut down.
Edouard Tisserant
parents: 2537
diff changeset
   191
        self.done.notify()
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   192
        self.mutex.release()
3642
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
   193
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
   194
    def finish(self):
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
   195
        if self.own_thread is None:
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
   196
            self.quit()
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
   197
        if self.stopper is not None:
cd3d15e8ef42 Runtime: fix PLC not terminating when being Repaired (i.e purged).
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3585
diff changeset
   198
            self.stopper()