src.fairreckitlib.core.threading.thread_base

This module contains the base class for threads.

Classes:

ThreadBase: base class that implements basic threading functionality.

This program has been developed by students from the bachelor Computer Science at Utrecht University within the Software Project course. © Copyright Utrecht University (Department of Information and Computing Sciences)

  1"""This module contains the base class for threads.
  2
  3Classes:
  4
  5    ThreadBase: base class that implements basic threading functionality.
  6
  7This program has been developed by students from the bachelor Computer Science at
  8Utrecht University within the Software Project course.
  9© Copyright Utrecht University (Department of Information and Computing Sciences)
 10"""
 11
 12from abc import ABCMeta, abstractmethod
 13from threading import Thread
 14from typing import Any, Callable
 15
 16from ..events.event_dispatcher import EventDispatcher
 17
 18
 19class ThreadBase(metaclass=ABCMeta):
 20    """Base class for all threads.
 21
 22    Wraps the threading module in a class interface. The main function of each
 23    thread consists of three steps:
 24
 25    1) Initialize
 26    2) Run
 27    3) Terminate
 28
 29    Threads are not running on creation, only after the start() function is called.
 30    The function is_running() will return True as long as the thread is active,
 31    once the stop() function is called it requests the thread to finish.
 32    Threads cannot be cancelled so any derived class logic needs to account for this request
 33    by checking the is_running function pointer (in step 2) regularly.
 34
 35    Abstract methods:
 36
 37    on_initialize (optional)
 38    on_run (required)
 39    on_terminate (optional)
 40
 41    Public methods:
 42
 43    get_name
 44    is_running
 45    start
 46    stop
 47    """
 48
 49    def __init__(self, name: str, verbose: bool, **kwargs):
 50        """Construct the BaseThread.
 51
 52        Args:
 53            name the name of the thread.
 54            verbose: whether the thread should give verbose output.
 55
 56        Keyword Args:
 57            varying: these are passed to the run function from step 2.
 58        """
 59        self.running = False
 60        self.thread = Thread(target=self.main, name=name, kwargs=kwargs)
 61        self.terminate_callback = None
 62
 63        self.verbose = verbose
 64        self.event_dispatcher = EventDispatcher()
 65
 66    def start(self, terminate_callback: Callable[[Any], None]) -> bool:
 67        """Start running the thread.
 68
 69        Args:
 70            terminate_callback: call back function that is called once the thread is
 71            finished running and is terminated. This function has one argument
 72            which is the thread itself.
 73
 74        Returns:
 75            True when the thread successfully started or False when the thread is already running.
 76        """
 77        if self.running:
 78            return False
 79
 80        self.running = True
 81        self.terminate_callback = terminate_callback
 82        self.thread.start()
 83
 84        return True
 85
 86    def stop(self) -> None:
 87        """Stop running the thread.
 88
 89        Does not cancel the thread, but rather requests for the thread to finish
 90        by settings the is_running flag to False. Derived classes need to account
 91        for this request by checking the status regularly.
 92        """
 93        self.running = False
 94
 95    def get_name(self) -> str:
 96        """Get the name of the thread.
 97
 98        Returns:
 99            the thread's name.
100        """
101        return self.thread.name
102
103    def is_running(self) -> bool:
104        """Get if the thread is still running.
105
106        Returns:
107            whether the thread is running.
108        """
109        return self.running
110
111    def on_initialize(self) -> None:
112        """Initialize the thread.
113
114        This function is called once when the thread is started.
115        It should not be used directly, add specific logic in derived classes.
116        """
117
118    @abstractmethod
119    def on_run(self, **kwargs) -> None:
120        """Run the thread.
121
122        This function is called once after the thread is initialized.
123        It should not be used directly, add specific logic in derived classes.
124
125        Keyword Args:
126            varying: these are passed directly from the thread's constructor.
127        """
128        raise NotImplementedError()
129
130    def on_terminate(self) -> None:
131        """Terminate the thread.
132
133        This function is called once after the thread is done running.
134        It should not be used directly, add specific logic in derived classes.
135        Moreover, derived classes are expected to call their super implementation
136        after their own implementation is finished.
137        """
138        self.terminate_callback(self)
139
140    def main(self, **kwargs) -> None:
141        """Run the main function target of the thread.
142
143        Keyword Args:
144            varying: these are passed directly from the thread's constructor.
145        """
146        self.on_initialize()
147        self.on_run(**kwargs)
148        self.on_terminate()
class ThreadBase:
 20class ThreadBase(metaclass=ABCMeta):
 21    """Base class for all threads.
 22
 23    Wraps the threading module in a class interface. The main function of each
 24    thread consists of three steps:
 25
 26    1) Initialize
 27    2) Run
 28    3) Terminate
 29
 30    Threads are not running on creation, only after the start() function is called.
 31    The function is_running() will return True as long as the thread is active,
 32    once the stop() function is called it requests the thread to finish.
 33    Threads cannot be cancelled so any derived class logic needs to account for this request
 34    by checking the is_running function pointer (in step 2) regularly.
 35
 36    Abstract methods:
 37
 38    on_initialize (optional)
 39    on_run (required)
 40    on_terminate (optional)
 41
 42    Public methods:
 43
 44    get_name
 45    is_running
 46    start
 47    stop
 48    """
 49
 50    def __init__(self, name: str, verbose: bool, **kwargs):
 51        """Construct the BaseThread.
 52
 53        Args:
 54            name the name of the thread.
 55            verbose: whether the thread should give verbose output.
 56
 57        Keyword Args:
 58            varying: these are passed to the run function from step 2.
 59        """
 60        self.running = False
 61        self.thread = Thread(target=self.main, name=name, kwargs=kwargs)
 62        self.terminate_callback = None
 63
 64        self.verbose = verbose
 65        self.event_dispatcher = EventDispatcher()
 66
 67    def start(self, terminate_callback: Callable[[Any], None]) -> bool:
 68        """Start running the thread.
 69
 70        Args:
 71            terminate_callback: call back function that is called once the thread is
 72            finished running and is terminated. This function has one argument
 73            which is the thread itself.
 74
 75        Returns:
 76            True when the thread successfully started or False when the thread is already running.
 77        """
 78        if self.running:
 79            return False
 80
 81        self.running = True
 82        self.terminate_callback = terminate_callback
 83        self.thread.start()
 84
 85        return True
 86
 87    def stop(self) -> None:
 88        """Stop running the thread.
 89
 90        Does not cancel the thread, but rather requests for the thread to finish
 91        by settings the is_running flag to False. Derived classes need to account
 92        for this request by checking the status regularly.
 93        """
 94        self.running = False
 95
 96    def get_name(self) -> str:
 97        """Get the name of the thread.
 98
 99        Returns:
100            the thread's name.
101        """
102        return self.thread.name
103
104    def is_running(self) -> bool:
105        """Get if the thread is still running.
106
107        Returns:
108            whether the thread is running.
109        """
110        return self.running
111
112    def on_initialize(self) -> None:
113        """Initialize the thread.
114
115        This function is called once when the thread is started.
116        It should not be used directly, add specific logic in derived classes.
117        """
118
119    @abstractmethod
120    def on_run(self, **kwargs) -> None:
121        """Run the thread.
122
123        This function is called once after the thread is initialized.
124        It should not be used directly, add specific logic in derived classes.
125
126        Keyword Args:
127            varying: these are passed directly from the thread's constructor.
128        """
129        raise NotImplementedError()
130
131    def on_terminate(self) -> None:
132        """Terminate the thread.
133
134        This function is called once after the thread is done running.
135        It should not be used directly, add specific logic in derived classes.
136        Moreover, derived classes are expected to call their super implementation
137        after their own implementation is finished.
138        """
139        self.terminate_callback(self)
140
141    def main(self, **kwargs) -> None:
142        """Run the main function target of the thread.
143
144        Keyword Args:
145            varying: these are passed directly from the thread's constructor.
146        """
147        self.on_initialize()
148        self.on_run(**kwargs)
149        self.on_terminate()

Base class for all threads.

Wraps the threading module in a class interface. The main function of each thread consists of three steps:

1) Initialize 2) Run 3) Terminate

Threads are not running on creation, only after the start() function is called. The function is_running() will return True as long as the thread is active, once the stop() function is called it requests the thread to finish. Threads cannot be cancelled so any derived class logic needs to account for this request by checking the is_running function pointer (in step 2) regularly.

Abstract methods:

on_initialize (optional) on_run (required) on_terminate (optional)

Public methods:

get_name is_running start stop

ThreadBase(name: str, verbose: bool, **kwargs)
50    def __init__(self, name: str, verbose: bool, **kwargs):
51        """Construct the BaseThread.
52
53        Args:
54            name the name of the thread.
55            verbose: whether the thread should give verbose output.
56
57        Keyword Args:
58            varying: these are passed to the run function from step 2.
59        """
60        self.running = False
61        self.thread = Thread(target=self.main, name=name, kwargs=kwargs)
62        self.terminate_callback = None
63
64        self.verbose = verbose
65        self.event_dispatcher = EventDispatcher()

Construct the BaseThread.

Args: name the name of the thread. verbose: whether the thread should give verbose output.

Keyword Args: varying: these are passed to the run function from step 2.

def start(self, terminate_callback: Callable[[Any], NoneType]) -> bool:
67    def start(self, terminate_callback: Callable[[Any], None]) -> bool:
68        """Start running the thread.
69
70        Args:
71            terminate_callback: call back function that is called once the thread is
72            finished running and is terminated. This function has one argument
73            which is the thread itself.
74
75        Returns:
76            True when the thread successfully started or False when the thread is already running.
77        """
78        if self.running:
79            return False
80
81        self.running = True
82        self.terminate_callback = terminate_callback
83        self.thread.start()
84
85        return True

Start running the thread.

Args: terminate_callback: call back function that is called once the thread is finished running and is terminated. This function has one argument which is the thread itself.

Returns: True when the thread successfully started or False when the thread is already running.

def stop(self) -> None:
87    def stop(self) -> None:
88        """Stop running the thread.
89
90        Does not cancel the thread, but rather requests for the thread to finish
91        by settings the is_running flag to False. Derived classes need to account
92        for this request by checking the status regularly.
93        """
94        self.running = False

Stop running the thread.

Does not cancel the thread, but rather requests for the thread to finish by settings the is_running flag to False. Derived classes need to account for this request by checking the status regularly.

def get_name(self) -> str:
 96    def get_name(self) -> str:
 97        """Get the name of the thread.
 98
 99        Returns:
100            the thread's name.
101        """
102        return self.thread.name

Get the name of the thread.

Returns: the thread's name.

def is_running(self) -> bool:
104    def is_running(self) -> bool:
105        """Get if the thread is still running.
106
107        Returns:
108            whether the thread is running.
109        """
110        return self.running

Get if the thread is still running.

Returns: whether the thread is running.

def on_initialize(self) -> None:
112    def on_initialize(self) -> None:
113        """Initialize the thread.
114
115        This function is called once when the thread is started.
116        It should not be used directly, add specific logic in derived classes.
117        """

Initialize the thread.

This function is called once when the thread is started. It should not be used directly, add specific logic in derived classes.

@abstractmethod
def on_run(self, **kwargs) -> None:
119    @abstractmethod
120    def on_run(self, **kwargs) -> None:
121        """Run the thread.
122
123        This function is called once after the thread is initialized.
124        It should not be used directly, add specific logic in derived classes.
125
126        Keyword Args:
127            varying: these are passed directly from the thread's constructor.
128        """
129        raise NotImplementedError()

Run the thread.

This function is called once after the thread is initialized. It should not be used directly, add specific logic in derived classes.

Keyword Args: varying: these are passed directly from the thread's constructor.

def on_terminate(self) -> None:
131    def on_terminate(self) -> None:
132        """Terminate the thread.
133
134        This function is called once after the thread is done running.
135        It should not be used directly, add specific logic in derived classes.
136        Moreover, derived classes are expected to call their super implementation
137        after their own implementation is finished.
138        """
139        self.terminate_callback(self)

Terminate the thread.

This function is called once after the thread is done running. It should not be used directly, add specific logic in derived classes. Moreover, derived classes are expected to call their super implementation after their own implementation is finished.

def main(self, **kwargs) -> None:
141    def main(self, **kwargs) -> None:
142        """Run the main function target of the thread.
143
144        Keyword Args:
145            varying: these are passed directly from the thread's constructor.
146        """
147        self.on_initialize()
148        self.on_run(**kwargs)
149        self.on_terminate()

Run the main function target of the thread.

Keyword Args: varying: these are passed directly from the thread's constructor.