Changeset 1197


Ignore:
Timestamp:
02/05/23 22:48:52 (10 months ago)
Author:
Maciej Komosinski
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • framspy/frams.py

    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.
     19
     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.
    1923
    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.
    310 
    311314        """
    312         # goals:
     315
    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("frams.py: 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
     332                       
     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
     341
     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
    341363
    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.