Add limited thread communication #1
Description
Add limited support of communication while either python or dm-script or both are running in separate threads and update constantly.
Target use
import time
with exec_dmscript(script, thread=True, autostart=True, queues={"texts": "py2dm", "commands": "dm2py", "progress": "py2dm"}) as script:
progress = 1
while script.queue("commands").get() != "cancel" and progress < 100:
script.queue("texts").put("Current time: {}".format(time.time())
script.queue("progress").put(progress)
progress += 1
time.sleep(0.2)
Restrictions
There will be no locking in the queus! This is designed for one thread at the python side and for one thread at the dm-script side. If there are multiple threads on one of the sides, the script on this side has to deal with locking. This can easily be done because both support locking.
For python there is a threading.Lock
. For dm-script a Mutex implementation is present. Both can block until the queue is set.
Implementation details
Synchronization has to go over the persistent tags. Only bool
, int
, float
and str
are supported. list
and dict
can be added later.
- Create a
TagList
in the persistent tags called "_execdmscript_queue_py2dm" or "dm2py" - Add a dm-script function
__execdmscript_get_queue_persistent_tag(name, type)
that contains the persistent tag names "hard coded" for each "name",type
is either "dm2py" or "py2dm" - Add a dm-script function
execdmscript_queue_gettype(name)
that returns the type of the__execdmscript_queue_py2dm_<id>
queue in dm-script (do not increase index!) - Add a dm-script function
execdmscript_queue_get(name, &value)
that returns the last added value of the__execdmscript_queue_py2dm_<id>
queue in dm-script and increases the__execdmscript_queue_py2dm_<id>_index
- Add a dm-script variable
__execdmscript_queue_py2dm_<id>_index
that saves the current index in the queue, deleting may mess up the python side
- Add a dm-script variable
- Add a dm-script function
execdmscript_queue_put(name, value)
that adds the given value to the__execdmscript_queue_dm2py_<id>
queue - Add a dm-script function
execdmscript_queue_empty(name)
that returns whether the queue is empty or not, this is only supported for "py2dm" queues - Add a
DMScriptWrapper._queues
dict that contains each queue with its name as the key - Add a
DMScriptWrapper.queue(name)
function that returns the queue for the name - Add a python
DMScriptNoLockQueue
- Add a
DMScriptNoLockQueue.unique_id
- Add a
DMScriptNoLockQueue.name
- Add a
- Add a python
DMScriptPy2DMNoLockQueue
inheritingDMScriptNoLockQueue
- Add a
put()
method that adds the given variable to the persistent tag
- Add a
- Add a python
DMScriptDM2PyNoLockQueue
inheritingDMScriptNoLockQueue
- Add an
DMScriptDM2PyNoLockQueue._current_index
- Add a
get()
method that returns the element on the_current_index
and increases the index by one - Add an
empty()
method that returns whether the_current_index
is the last index or not
- Add an
- Append the code with the dm-script queue functions
- Create the
__execdmscript_get_queue_persistent_tag(name, type)
by travelling through the queues and create an if-else with each name and the corresponding id- If the name does not exist, throw an Exception
Prospectus
Add a queue that contains a locking mechanism on both sides.
For implementing a locking mechanism that locks for both sides, one has to go very basic. The best approach would be the the Peterson's algorithm or similar ones because it can use only basic get and set oprations.