Changeset 1197

02/05/23 22:48:52 (10 months ago)
Maciej Komosinski

Added the "-t" option in init() to make concurrent calls from different threads sequential, thus making them safe

1 edited


  • framspy/

    r1189 r1197  
    1717If you want to run many independent instances of this class in parallel, use the "multiprocessing" module and then each process
    1818that uses this module will initialize it and get access to a separate instance of the Framsticks library.
     20If you want to use this module from multiple threads concurrently, use the "-t" option for init().
     21This will make concurrent calls from different threads sequential, thus making them safe.
     22However, this will likely degrade the performance (due to required locking) compared to the single-threaded use.
    2024For interfaces in other languages (e.g. using the Framsticks library in your C++ code), see ../cpp/frams/frams-objects.h
    308312        '-LNAME' is the optional library name (full name including the file name extension), default is 'frams-objects.dll/.so' depending on the platform.
    309313        All other arguments are passed to Framsticks and not interpreted by this function.
    311314        """
    312         # goals:
    313316        frams_d = None
    314317        frams_D = None
    323326                elif a[:2] == '-L':
    324327                        lib_name = a[2:]
     328                elif a[:2] == '-t':
     329                        print(" thread synchronization enabled.")  # Due to performance penalty, only use if you are really calling methods from different threads.
     330                        from functools import wraps
     331                        from threading import RLock
     333                        def threads_synchronized(lock):
     334                                def wrapper(f):
     335                                        @wraps(f)
     336                                        def inner_wrapper(*args, **kwargs):
     337                                                with lock:
     338                                                        return f(*args, **kwargs)
     339                                        return inner_wrapper
     340                                return wrapper
     342                        thread_synchronizer = threads_synchronized(RLock())
     343                        for name in ExtValue.__dict__:
     344                                attr = getattr(ExtValue, name)
     345                                if callable(attr) and attr:  # decorate all methods of ExtValue with a reentrant lock so that different threads do not use them concurrently
     346                                        setattr(ExtValue, name, thread_synchronizer(attr))
    325347                elif lib_path is None:
    326348                        lib_path = a
    340362        abs_data = os.path.join(os.path.abspath(lib_path), "data")  # use absolute path for -d and -D so python is free to cd anywhere without confusing Framsticks
    342         # for the hypothetical case without lib_path the abs_data must be obtained from somewhere else
     364        # for the hypothetical case without lib_path, the abs_data must be obtained from somewhere else
    343365        if frams_d is None:
    344366                frams_d = '-d' + abs_data
Note: See TracChangeset for help on using the changeset viewer.