runtime/Worker.py
author Edouard Tisserant <edouard@beremiz.fr>
Thu, 25 Apr 2024 09:37:09 +0200
changeset 3934 8072072038d2
parent 3851 4e1906d119d5
permissions -rw-r--r--
BACnet: Fixed grid cell choice editor. Consequence of wxPython4.
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()