runtime/Worker.py
author Edouard Tisserant
Fri, 22 Mar 2019 10:57:04 +0100
branchsearch_in_CTN
changeset 2528 6bfc8a9bf0e7
parent 2492 7dd551ac2fa0
child 2536 2747d6e72eb8
permissions -rw-r--r--
WIP adding searching capabilities in python files. was done :
- added search in body of Code File Tree Nodes (moved editor code so that we CTN search can have the same sections text layout as editor to search in)
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
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    10
from __future__ import absolute_import
2307
c44692b53736 Show more exceptions on stdout, particularly those that are raised by AutoLoad (first item in Main Thread worker)
Edouard Tisserant
parents: 2271
diff changeset
    11
import sys
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    12
import thread
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    13
from threading import Lock, Condition
2492
7dd551ac2fa0 check_sources.sh makes me become even less productive
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2486
diff changeset
    14
import six
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    15
2309
d8fb90a2e11f Please pylint and pep8
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2307
diff changeset
    16
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    17
class job(object):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    18
    """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    19
    job to be executed by a worker
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    20
    """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    21
    def __init__(self, call, *args, **kwargs):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    22
        self.job = (call, args, kwargs)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    23
        self.result = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    24
        self.success = False
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    25
        self.exc_info = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    26
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    27
    def do(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    28
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    29
        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
    30
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    31
        try:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    32
            call, args, kwargs = self.job
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    33
            self.result = call(*args, **kwargs)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    34
            self.success = True
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    35
        except Exception:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    36
            self.success = False
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    37
            self.exc_info = sys.exc_info()
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
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    40
class worker(object):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    41
    """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    42
    serialize main thread load/unload of PLC shared objects
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    43
    """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    44
    def __init__(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    45
        # Only one job at a time
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    46
        self._finish = False
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    47
        self._threadID = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    48
        self.mutex = Lock()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    49
        self.todo = Condition(self.mutex)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    50
        self.done = Condition(self.mutex)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    51
        self.free = Condition(self.mutex)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    52
        self.job = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    53
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    54
    def runloop(self, *args, **kwargs):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    55
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    56
        meant to be called by worker thread (blocking)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    57
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    58
        self._threadID = thread.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
    59
        self.mutex.acquire()
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    60
        if args or kwargs:
2307
c44692b53736 Show more exceptions on stdout, particularly those that are raised by AutoLoad (first item in Main Thread worker)
Edouard Tisserant
parents: 2271
diff changeset
    61
            _job = job(*args, **kwargs)
c44692b53736 Show more exceptions on stdout, particularly those that are raised by AutoLoad (first item in Main Thread worker)
Edouard Tisserant
parents: 2271
diff changeset
    62
            _job.do()
c44692b53736 Show more exceptions on stdout, particularly those that are raised by AutoLoad (first item in Main Thread worker)
Edouard Tisserant
parents: 2271
diff changeset
    63
            if _job.success:
c44692b53736 Show more exceptions on stdout, particularly those that are raised by AutoLoad (first item in Main Thread worker)
Edouard Tisserant
parents: 2271
diff changeset
    64
                # result is ignored
c44692b53736 Show more exceptions on stdout, particularly those that are raised by AutoLoad (first item in Main Thread worker)
Edouard Tisserant
parents: 2271
diff changeset
    65
                pass
c44692b53736 Show more exceptions on stdout, particularly those that are raised by AutoLoad (first item in Main Thread worker)
Edouard Tisserant
parents: 2271
diff changeset
    66
            else:
c44692b53736 Show more exceptions on stdout, particularly those that are raised by AutoLoad (first item in Main Thread worker)
Edouard Tisserant
parents: 2271
diff changeset
    67
                raise _job.exc_info[0], _job.exc_info[1], _job.exc_info[2]
2486
44c2a4e2b84d Fixed deadlock in runtime's Worker. Was discovered while using WAMP and PYRO simultaneously.
Edouard Tisserant
parents: 2467
diff changeset
    68
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    69
        while not self._finish:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    70
            self.todo.wait()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    71
            if self.job is not None:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    72
                self.job.do()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    73
                self.done.notify()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    74
            else:
2486
44c2a4e2b84d Fixed deadlock in runtime's Worker. Was discovered while using WAMP and PYRO simultaneously.
Edouard Tisserant
parents: 2467
diff changeset
    75
                break
44c2a4e2b84d Fixed deadlock in runtime's Worker. Was discovered while using WAMP and PYRO simultaneously.
Edouard Tisserant
parents: 2467
diff changeset
    76
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    77
        self.mutex.release()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    78
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    79
    def call(self, *args, **kwargs):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    80
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    81
        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
    82
        if job execution raise exception, re-raise same exception
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    83
        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
    84
        blocking until job done
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    85
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    86
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    87
        _job = job(*args, **kwargs)
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    88
2271
985973ed701b Removed useless condition in Worker.py that was allowing misfit non-serialized call when worker still not running its loop.
Edouard Tisserant
parents: 2270
diff changeset
    89
        if self._threadID == thread.get_ident():
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    90
            # if caller is worker thread execute immediately
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    91
            _job.do()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    92
        else:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    93
            # otherwise notify and wait for completion
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    94
            self.mutex.acquire()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    95
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    96
            while self.job is not None:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    97
                self.free.wait()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    98
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
    99
            self.job = _job
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   100
            self.todo.notify()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   101
            self.done.wait()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   102
            self.job = None
2486
44c2a4e2b84d Fixed deadlock in runtime's Worker. Was discovered while using WAMP and PYRO simultaneously.
Edouard Tisserant
parents: 2467
diff changeset
   103
            self.free.notify()
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   104
            self.mutex.release()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   105
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   106
        if _job.success:
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   107
            return _job.result
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   108
        else:
2429
15f18dc8b56a Merge, with surprizingly little conflicts
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2309
diff changeset
   109
            exc_type = _job.exc_info[0]
15f18dc8b56a Merge, with surprizingly little conflicts
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2309
diff changeset
   110
            exc_value = _job.exc_info[1]
15f18dc8b56a Merge, with surprizingly little conflicts
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2309
diff changeset
   111
            exc_traceback = _job.exc_info[2]
15f18dc8b56a Merge, with surprizingly little conflicts
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 2309
diff changeset
   112
            six.reraise(exc_type, exc_value, exc_traceback)
2270
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   113
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   114
    def quit(self):
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   115
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   116
        unblocks main thread, and terminate execution of runloop()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   117
        """
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   118
        # mark queue
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   119
        self._finish = True
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   120
        self.mutex.acquire()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   121
        self.job = None
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   122
        self.todo.notify()
d9175daf6522 Refactoring. Separated PLC Object, PYRO Server and MainWorker :
Edouard Tisserant
parents:
diff changeset
   123
        self.mutex.release()