Skip to content

Commit

Permalink
fix: protect threading users against clutter (#771)
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamHPNielsen authored and jenshnielsen committed Sep 29, 2017
1 parent ad4a3ee commit 0435245
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
23 changes: 22 additions & 1 deletion qcodes/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
_NO_SNAPSHOT = {'type': None, 'description': 'Action without snapshot'}


# exception when threading is attempted used to simultaneously
# query the same instrument for several values
class UnsafeThreadingException(Exception):
pass


def _actions_snapshot(actions, update):
"""Make a list of snapshots from a list of actions."""
snapshot = []
Expand Down Expand Up @@ -113,9 +119,13 @@ def __init__(self, params_indices, data_set, use_threads):
self.getters = []
self.param_ids = []
self.composite = []
paramcheck = [] # list to check if parameters are unique
for param, action_indices in params_indices:
self.getters.append(param.get)

if param._instrument:
paramcheck.append((param, param._instrument))

if hasattr(param, 'names'):
part_ids = []
for i in range(len(param.names)):
Expand All @@ -128,6 +138,17 @@ def __init__(self, params_indices, data_set, use_threads):
self.param_ids.append(param_id)
self.composite.append(False)

if self.use_threads:
insts = [p[1] for p in paramcheck]
if (len(set(insts)) != len(insts)):
duplicates = [p for p in paramcheck if insts.count(p[1]) > 1]
raise UnsafeThreadingException('Can not use threading to '
'read '
'several things from the same '
'instrument. Specifically, you '
'asked for'
' {}.'.format(duplicates))

def __call__(self, loop_indices, **ignore_kwargs):
out_dict = {}
if self.use_threads:
Expand Down Expand Up @@ -166,7 +187,7 @@ class BreakIf:

"""
Loop action that breaks out of the loop if a condition is truthy.
Args:
condition (callable): a callable taking no arguments.
Can be a simple function that returns truthy when it's time to quit
Expand Down
32 changes: 32 additions & 0 deletions qcodes/tests/test_threading.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import gc

from unittest import TestCase

from qcodes import Loop
from qcodes.actions import UnsafeThreadingException
from qcodes.tests.instrument_mocks import DummyInstrument


class TestUnsafeThreading(TestCase):

def setUp(self):
self.inst1 = DummyInstrument(name='inst1',
gates=['v1', 'v2'])
self.inst2 = DummyInstrument(name='inst2',
gates=['v1', 'v2'])

def tearDown(self):
self.inst1.close()
self.inst2.close()

del self.inst1
del self.inst2

gc.collect()

def test_unsafe_exception(self):
to_meas = (self.inst1.v1, self.inst1.v2)
loop = Loop(self.inst2.v1.sweep(0, 1, num=10)).each(*to_meas)

with self.assertRaises(UnsafeThreadingException):
loop.run(use_threads=True)

0 comments on commit 0435245

Please sign in to comment.