diff --git a/CHANGELOG b/CHANGELOG index 5be851e..c320791 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +Version 1.1.9 +============= + +- Changing creation of unique persistent tag names from timestamp with milliseconds to using uuids + to fix tag collision in parallel threads or immediately consecutive calls + Version 1.1.8 (Hotfix) ====================== diff --git a/VERSION b/VERSION index db15278..a5e4282 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.8 \ No newline at end of file +1.1.9 \ No newline at end of file diff --git a/execdmscript/__init__.py b/execdmscript/__init__.py index 21c2d06..5e8bae6 100644 --- a/execdmscript/__init__.py +++ b/execdmscript/__init__.py @@ -27,10 +27,8 @@ ``` This uses the persistent tags to communicate from dm-script to python. - -Note that this is not thread-safe! """ from .execdmscript import * -__version__ = "1.1.8" \ No newline at end of file +__version__ = "1.1.9" \ No newline at end of file diff --git a/execdmscript/execdmscript.py b/execdmscript/execdmscript.py index b3675dc..9716a2b 100644 --- a/execdmscript/execdmscript.py +++ b/execdmscript/execdmscript.py @@ -2,6 +2,7 @@ import re import sys import time +import uuid import errno import types import random @@ -636,6 +637,21 @@ def get_persistent_tag(path: typing.Optional[typing.Union[typing.Sequence[str], raise KeyError(("No value was found in the persistent tags for " + "the path '{}'.").format(path)) +def unique_tag(tagname: str) -> str: + """Get the `tagname` with an appended UUID. + + Parameters + ---------- + tagname : str + The tagname + + Returns + ------- + str + A unique tagname to use + """ + return "{}_{}".format(tagname, str(uuid.uuid4()).replace("-", "_")) + class DMScriptWrapper: """Wraps one or more dm-scripts. """ @@ -689,8 +705,8 @@ def __init__(self, will be placed in the current working directory, default: None """ self.scripts = DMScriptWrapper.normalizeScripts(scripts) - self._creation_time_id = str(round(time.time() * 100)) - self.persistent_tag = "python-dm-communication-" + self._creation_time_id + self._unique_id = str(uuid.uuid4()).replace("-", "_") + self.persistent_tag = "__execdmscript_{}".format(self._unique_id) self.readvars = readvars self.setvars = setvars self.synchronized_vars = {} @@ -1060,9 +1076,9 @@ def getSeparateThreadStartCode(self, index: int) -> str: """ return "\n".join(( - "object thread_cancel_signal{}_{} = NewCancelSignal();".format(self._creation_time_id, index), - "object thread_done_signal{}_{} = NewSignal(0);".format(self._creation_time_id, index), - "class ExecDMScriptThread{}_{} : Thread{{".format(self._creation_time_id, index), + "object thread_cancel_signal{}_{} = NewCancelSignal();".format(self._unique_id, index), + "object thread_done_signal{}_{} = NewSignal(0);".format(self._unique_id, index), + "class ExecDMScriptThread{}_{} : Thread{{".format(self._unique_id, index), "void RunThread(object self){" )) @@ -1088,11 +1104,11 @@ def getSeparateThreadEndCode(self, index: int) -> str: return "\n".join(( "// inform that the thread is done now", - "thread_done_signal{}_{}.setSignal();".format(self._creation_time_id, index), + "thread_done_signal{}_{}.setSignal();".format(self._unique_id, index), "}", # end ExecDMScriptThread::RunThread() "}", # end ExecDMScriptThread class "alloc(ExecDMScriptThread{}_{}).StartThread();".format( - self._creation_time_id, index + self._unique_id, index ) )) @@ -1114,7 +1130,7 @@ def getSeparateThreadWaitCode(self, index: int) -> str: return "\n".join(( "// wait for the thread {}".format(index), "thread_done_signal{id}_{i}.WaitOnSignal(infinity(), thread_cancel_signal{id}_{i});".format( - id=self._creation_time_id, i=index + id=self._unique_id, i=index ) )) @@ -1153,7 +1169,7 @@ def getSyncDMCode(self) -> str: dmscript = [] # the name of the tag group to use - sync_code_tg_name = "sync_taggroup_" + self._creation_time_id + sync_code_tg_name = "sync_taggroup_" + self._unique_id # declare and initialize the used variables sync_code_prefix = "\n".join((