ThreadManager¶
ThreadManager is a special thread which is designed make it easier to control many threads at the same time.
It is a subclass of the MultiRunThread and manages the flow of information to and from running thread instances.
Thread Manager commands:
- SET_THREAD_TYPES - send a dictionary of keys to thread classes which you will wish to instantiate through the Thread Manager
- NEW_THREAD - Create a new instance of a thread given a thread name and thread type
- DESTROY_THREAD - Destroy a running thread and prevent any delayed output from leaking
- ACTIVE_THREADS - Get a dictionary of all the threads which are active in the ThreadManager and what class of thread they are. Returns a message to the sender with ACTIVE_THREADS command
Threads which are running in the ThreadManager can be accessed through the address [“THREAD_MANAGER_NAME”, “THREAD_NAME”] with their usual commands.
Further explanation of the commands and how the ThreadManager works are given below:
The ThreadManager has a special dictionary of thread_types which may be set with the command SET_THREAD_TYPES. This maps human readable strings or identifiers to the more complex class names of thread types. It also means the operating the ThreadManager does not require importing the thread classes themselves locally, as this will have been done when the ThreadManager was setup, all that needs to be known is the identifier.
ThreadManagers are always addressed with a list, whether the message is for the thread manager or for a thread being managed. The ThreadManager checks the first value in the address to ensure it should be processing the message. If it finds its own name, it replaces the receiver attribute of the message with a new tuple with the first value sliced out. If it does not find its own name, the message will be sent away to the output queue with the name of the ThreadManager prepended to the front of the “from” message element. This will allow complex patterns to be easily built up, with layers of ThreadManagers, because threads do not need to know the whole hierarchy, only the name of their direct manager. They can also contact sibling threads through the same mechanism as an external message source, simplifying the ThreadManager code.
The top level ThreadManager (at the top of the hierarchy) will have None as its parent as it was not created by a ThreadManager. Therefore, when it sends a message outside the thread hierarchy, it will not prepend anything to the “from” address and therefore the message address will be a valid place to send a reply.
This constructing and destructing of messages as they travel up and down ensures that when a message is received by a thread, it can send a message back to the same location and be sure that it is a valid location (or was when the message was sent).
To create a new thread with the thread manager, send a NEW_THREAD command directly to the thread manager and provide a dictionary containing values for the thread type. The ThreadManager will look in its list of currently active threads to see if it has a thread with that name. If it does, the request will be rejected. If not, a new thread of that type and with that name will be created, with the owner being the name of the ThreadManager.
From then on, the thread will be addressed through the ThreadManager with an address of [thread_manager_name, thread_name].
Each thread being manager by a ThreadManager has its own internal input queue to receive messsages. This prevents name clashing which would inevitably occur by using a single queue for many threads.
Output queues from the threads are connected to the ThreadManager input queue, to be processed the same way as messages external to the ThreadManager. This allows the ThreadManager to wait for input on one queue only and to process all messages the same way. It also opens up the potential for threads to contact other threads, although this situation should be managed carefully.
Threads which are running happily are kept in the ThreadManager’s active thread list. The ThreadManager will preiodically review this list to see if any of the threads are stopped. Threads which are stopped are removed from the list.
Occasionally, it may be necessary to ask the ThreadManager to kill a thread and prevent its output from being sent. This might be the case if a thread has main function which takes a long time and sends a big message at the end, but is no longer needed. In this case, send a DESTROY_THREAD command directly to the ThreadManager with the name of the thread to be destroyed as the package. In this case, the thread will be moved to a list of threads to be destroyed and the output will be captured by the ThreadManager instead of being sent onwards. A new thread with the same name cannot be created until the thread is neither an active thread nor in the list of destroyed threads. This will require some garbage collection of the ThreadManager. Also a good function to return useful information about which names are currently being used