|
46 | 46 | import ctypes |
47 | 47 | import re |
48 | 48 | import stat |
| 49 | +import select |
| 50 | +import time |
49 | 51 | from os.path import abspath |
50 | 52 | from struct import pack, unpack |
51 | 53 | from subprocess import Popen |
@@ -314,6 +316,8 @@ def __init__(self, address=None, name_pattern=SYSTEM_DEVICE_NAME_CONVENTION, nam |
314 | 316 |
|
315 | 317 | # ~autogen |
316 | 318 |
|
| 319 | + self._poll = None |
| 320 | + |
317 | 321 | # ~autogen generic-get-set classes.motor>currentClass |
318 | 322 |
|
319 | 323 | @property |
@@ -806,6 +810,64 @@ def reset(self, **kwargs): |
806 | 810 |
|
807 | 811 | # ~autogen |
808 | 812 |
|
| 813 | + def wait(self, cond, timeout=None): |
| 814 | + """ |
| 815 | + Blocks until ``cond(self.state)`` is ``True``. The condition is |
| 816 | + checked when there is an I/O event related to the ``state`` attribute. |
| 817 | + Exits early when ``timeout`` (in milliseconds) is reached. |
| 818 | +
|
| 819 | + Returns ``True`` if the condition is met, and ``False`` if the timeout |
| 820 | + is reached. |
| 821 | + """ |
| 822 | + |
| 823 | + tic = time.time() |
| 824 | + |
| 825 | + if self._poll is None: |
| 826 | + if self._state is None: |
| 827 | + self._state = self._attribute_file_open('state') |
| 828 | + self._poll = select.poll() |
| 829 | + self._poll.register(self._state, select.POLLPRI) |
| 830 | + |
| 831 | + while True: |
| 832 | + self._poll.poll(None if timeout is None else timeout) |
| 833 | + |
| 834 | + if timeout is not None and time.time() >= tic + timeout / 1000: |
| 835 | + return False |
| 836 | + |
| 837 | + if cond(self.state): |
| 838 | + return True |
| 839 | + |
| 840 | + |
| 841 | + def wait_until(self, s, timeout=None): |
| 842 | + """ |
| 843 | + Blocks until ``s`` is in ``self.state``. The condition is checked when |
| 844 | + there is an I/O event related to the ``state`` attribute. Exits early |
| 845 | + when ``timeout`` (in milliseconds) is reached. |
| 846 | +
|
| 847 | + Returns ``True`` if the condition is met, and ``False`` if the timeout |
| 848 | + is reached. |
| 849 | +
|
| 850 | + Example:: |
| 851 | +
|
| 852 | + m.wait_until('stalled') |
| 853 | + """ |
| 854 | + return self.wait(lambda state: s in state, timeout) |
| 855 | + |
| 856 | + def wait_while(self, s, timeout=None): |
| 857 | + """ |
| 858 | + Blocks until ``s`` is not in ``self.state``. The condition is checked |
| 859 | + when there is an I/O event related to the ``state`` attribute. Exits |
| 860 | + early when ``timeout`` (in milliseconds) is reached. |
| 861 | +
|
| 862 | + Returns ``True`` if the condition is met, and ``False`` if the timeout |
| 863 | + is reached. |
| 864 | +
|
| 865 | + Example:: |
| 866 | +
|
| 867 | + m.wait_while('running') |
| 868 | + """ |
| 869 | + return self.wait(lambda state: s not in state, timeout) |
| 870 | + |
809 | 871 | def list_motors(name_pattern=Motor.SYSTEM_DEVICE_NAME_CONVENTION, **kwargs): |
810 | 872 | """ |
811 | 873 | This is a generator function that enumerates all tacho motors that match |
|
0 commit comments