Skip to content

Commit

Permalink
Add lock around argtypes to prevent race condition, Fix Issue 7
Browse files Browse the repository at this point in the history
<rev> Add lock around `argtypes` to prevent race condition between
setting `argtypes` and calling functions, in cases the functions run in
parallel.

Some special cases needed unconditional locks around both the setting of
`argtypes` and the actual function call, like the variadic power-up
state functions in system.py, and the register events functions in
task.py.

<rev> Fix issue - `tests/max_config/nidaqmxMaxConfig.nce` is a binary
file and hard to track in git history, since I'm modifying the file
anyway.
#7
  • Loading branch information
Wondernutz committed Jul 26, 2017
1 parent fe11664 commit 82f7ee5
Show file tree
Hide file tree
Showing 50 changed files with 15,215 additions and 6,291 deletions.
15 changes: 11 additions & 4 deletions nidaqmx/_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
from __future__ import print_function
from __future__ import unicode_literals

from ctypes.util import find_library
import ctypes
from numpy.ctypeslib import ndpointer
import platform
import six
import sys
import platform
from ctypes.util import find_library
from numpy.ctypeslib import ndpointer
import threading

from nidaqmx.errors import Error

Expand Down Expand Up @@ -131,10 +132,16 @@ class DaqFunctionImporter(object):

def __init__(self, library):
self._library = library
self._lib_lock = threading.Lock()

def __getattr__(self, function):
try:
return getattr(self._library, function)
cfunc = getattr(self._library, function)
if not hasattr(cfunc, 'arglock'):
with self._lib_lock:
if not hasattr(cfunc, 'arglock'):
cfunc.arglock = threading.Lock()
return cfunc
except AttributeError:
raise DaqFunctionNotSupportedError(
'The NI-DAQmx function "{0}" is not supported in this '
Expand Down
709 changes: 460 additions & 249 deletions nidaqmx/_task_modules/ai_channel_collection.py

Large diffs are not rendered by default.

30 changes: 21 additions & 9 deletions nidaqmx/_task_modules/ao_channel_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,13 @@ def add_ao_current_chan(
Indicates the newly created channel object.
"""
cfunc = lib_importer.windll.DAQmxCreateAOCurrentChan
cfunc.argtypes = [
lib_importer.task_handle, ctypes_byte_str, ctypes_byte_str,
ctypes.c_double, ctypes.c_double, ctypes.c_int, ctypes_byte_str]
if cfunc.argtypes is None:
with cfunc.arglock:
if cfunc.argtypes is None:
cfunc.argtypes = [
lib_importer.task_handle, ctypes_byte_str,
ctypes_byte_str, ctypes.c_double, ctypes.c_double,
ctypes.c_int, ctypes_byte_str]

error_code = cfunc(
self._handle, physical_channel, name_to_assign_to_channel,
Expand Down Expand Up @@ -124,9 +128,13 @@ def add_ao_func_gen_chan(
Indicates the newly created channel object.
"""
cfunc = lib_importer.windll.DAQmxCreateAOFuncGenChan
cfunc.argtypes = [
lib_importer.task_handle, ctypes_byte_str, ctypes_byte_str,
ctypes.c_int, ctypes.c_double, ctypes.c_double, ctypes.c_double]
if cfunc.argtypes is None:
with cfunc.arglock:
if cfunc.argtypes is None:
cfunc.argtypes = [
lib_importer.task_handle, ctypes_byte_str,
ctypes_byte_str, ctypes.c_int, ctypes.c_double,
ctypes.c_double, ctypes.c_double]

error_code = cfunc(
self._handle, physical_channel, name_to_assign_to_channel,
Expand Down Expand Up @@ -169,9 +177,13 @@ def add_ao_voltage_chan(
Indicates the newly created channel object.
"""
cfunc = lib_importer.windll.DAQmxCreateAOVoltageChan
cfunc.argtypes = [
lib_importer.task_handle, ctypes_byte_str, ctypes_byte_str,
ctypes.c_double, ctypes.c_double, ctypes.c_int, ctypes_byte_str]
if cfunc.argtypes is None:
with cfunc.arglock:
if cfunc.argtypes is None:
cfunc.argtypes = [
lib_importer.task_handle, ctypes_byte_str,
ctypes_byte_str, ctypes.c_double, ctypes.c_double,
ctypes.c_int, ctypes_byte_str]

error_code = cfunc(
self._handle, physical_channel, name_to_assign_to_channel,
Expand Down
8 changes: 6 additions & 2 deletions nidaqmx/_task_modules/channel_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,12 @@ def channel_names(self):
channel collection.
"""
cfunc = lib_importer.windll.DAQmxGetTaskChannels
cfunc.argtypes = [
lib_importer.task_handle, ctypes.c_char_p, ctypes.c_uint]
if cfunc.argtypes is None:
with cfunc.arglock:
if cfunc.argtypes is None:
cfunc.argtypes = [
lib_importer.task_handle, ctypes.c_char_p,
ctypes.c_uint]

temp_size = 0
while True:
Expand Down
Loading

0 comments on commit 82f7ee5

Please sign in to comment.