Examples

Note

In order for the cthread package to be fully functional, the developer must follow two coding practices:

  1. Any code within the cthread.ControllableThread._active_callback() callback function and any registered alternative state callback function must be:

    • Non-blocking (at the very least it must only block for a short period of time), and

    • Contain no indefinite while or for loops.

    In short, the cthread.ControllableThread._active_callback() callback function and any registered alternative state callback functions must be written to minimize its execution time. This allows the thread to be controllable. This is because it is only at the end of each callback function that a check is conducted to determine whether the state of the thread must be updated.

  2. The code within the cthread.ControllableThread._started_callback() cthread.ControllableThread._paused_callback(), cthread.ControllableThread._resumed_callback(), and cthread.ControllableThread._killed_callback() callback functions will only execute once. There is a wrapper function for each callback function within the cthread.ControllableThread class. This wrapper function automatically updates the thread state to cthread.ThreadState.ACTIVE at the completion of the cthread.ControllableThread._started_callback() and cthread.ControllableThread._resumed_callback() callback functions, and cthread.ThreadState.IDLE at the completion of the cthread.ControllableThread._paused_callback() callback function. These callbacks should be written in such a way that they pause or resume/start thread functionality.

Quickstart

This code example can be found in the file examples/quickstart.py. It is an example of how to create a class that inherits from ControllableThread. No functionality has been added to any of the states. The lines:

1
2
        # Add any state specific code here (and remove the 'pass') #
        pass

can be replaced in each of the state callback functions with functional state code that is specific to the user’s needs.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import cthread
import logging
import queue as q
import time

# Configure the logger #
logging.basicConfig(level=logging.INFO,
        format='%(asctime)s %(levelname)s %(name)s %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

class Quickstart(cthread.ControllableThread):

    def _started_callback(self):
        # Add any state specific code here (and remove the 'pass') #
        pass

    def _active_callback(self):
        # Add any state specific code here (and remove the 'pass') #
        pass

    def _paused_callback(self):
        # Add any state specific code here (and remove the 'pass') #
        pass

    def _resumed_callback(self):
        # Add any state specific code here (and remove the 'pass') #
        pass

    def _killed_callback(self):
        # Add any state specific code here (and remove the 'pass') #
        pass

if __name__ == "__main__":

    queue = q.PriorityQueue()
    quickstart = Quickstart(name="QuickstartThread", queue=queue)

    quickstart.start() # Start the thread.  MUST be called first #
    time.sleep(1)

    quickstart.pause() # Pause the thread. #
    time.sleep(1)

    quickstart.resume() # Resume the thread #
    time.sleep(1)

    quickstart.reset() # Reset the thread #
    time.sleep(1)

    quickstart.kill() # Kill the thread #

This code gives the following output:

>> Starting thread: QuickstartThread...
>> (Re)initialising thread...
>> Thread activated!
>> Pausing thread...
>> Thread paused!
>> Resuming thread...
>> Thread activated!
>> (Re)initialising thread...
>> Thread activated!
>> Killing thread...
>> Stopped thread: QuickstartThread!

Alternative Thread states

This code example can be found in the file examples/alternative_state.py. It is an example of how to create a class that inherits from ControllableThread with additional allowable thread states. No functionality has been added to any of the additional states. The lines:

1
2
        # 2. Add any alternative state specific code here #
        pass

can be replaced in each of the additional state callback functions with functional state code that is specific to the user’s needs.

Note

There are two steps that must be followed when creating a cthread.ControllableThread instance with alternative states:

  1. Initialise the cthread.ControllableThread parent class with additional kwargs of the form name: callback. Each state name and callback function must be unique.

  2. Supply a callback function for each alternative state with the same name as that which was passed to the parent class in step 1 above.

These two steps are highlighted in the proceeding code.

Then, in order to transition the thread into one of the alternative states, the public method cthread.ControllableThread.run() must be called with the name parameter identical to the name specified in the kwargs from step 1 above.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import cthread
import logging
import queue as q
import time

# Configure the logger #
logging.basicConfig(level=logging.INFO,
        format='%(asctime)s %(levelname)s %(name)s %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

class AlternativeState(cthread.ControllableThread):

    def __init__(self, queue):
        # 1. Initialise ControllableThread with additional kwargs #
        cthread.ControllableThread.__init__(self,
                name="AlternativeStateThread",
                queue=queue,
                ALT1=self._alt1_callback,
                ALT2=self._alt2_callback
        )

    def _started_callback(self):
        pass

    def _active_callback(self):
        pass

    def _paused_callback(self):
        pass

    def _resumed_callback(self):
        pass

    def _killed_callback(self):
        pass

    def _alt1_callback(self):
        # 2. Add any alternative state specific code here #
        pass

    def _alt2_callback(self):
        # 2. Add any alternative state specific code here #
        pass

if __name__ == "__main__":

    queue = q.PriorityQueue()
    quickstart = AlternativeState(queue)

    quickstart.start() # Start the thread.  MUST be called first #
    time.sleep(1)

    quickstart.alt(name="ALT1") # ALT1 state #
    time.sleep(1)

    quickstart.alt(name="ALT2") # ALT2 state #
    time.sleep(1)

    quickstart.kill() # Kill the thread #

This code gives the following output:

>> Starting thread: Starting thread: AlternativeStateThread...
>> (Re)initialising thread...
>> Thread activated!
>> Transitioning thread to ALT1 state...
>> Transitioning thread to ALT2 state....
>> Killing thread...
>> Stopped thread: AlternativeStateThread!