web/ldt/utils/threading.py
author ymh <ymh.work@gmail.com>
Mon, 13 Dec 2010 23:55:19 +0100
changeset 22 83b28fc0d731
permissions -rw-r--r--
improve on ldt test framework start migration for text test
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
22
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
import threading
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
import inspect
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
import ctypes
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
def _async_raise(tid, exctype):
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
    """raises the exception, performs cleanup if needed"""
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
    if not inspect.isclass(exctype):
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
        raise TypeError("Only types can be raised (not instances)")
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
    if res == 0:
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
        raise ValueError("invalid thread id")
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
    elif res != 1:
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
        # """if it returns a number greater than one, you're in trouble, 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
        # and you should call it again with exc=NULL to revert the effect"""
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
        raise SystemError("PyThreadState_SetAsyncExc failed")
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
class Thread(threading.Thread):
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
    def _get_my_tid(self):
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
        """determines this (self's) thread id"""
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
        if not self.isAlive():
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
            raise threading.ThreadError("the thread is not active")
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
        # do we have it cached?
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
        if hasattr(self, "_thread_id"):
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
            return self._thread_id
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
        # no, look for it in the _active dict
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
        for tid, tobj in threading._active.items():
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
            if tobj is self:
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
                self._thread_id = tid
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
                return tid
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
        raise AssertionError("could not determine the thread's id")
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    def raise_exc(self, exctype):
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
        """raises the given exception type in the context of this thread"""
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
        _async_raise(self._get_my_tid(), exctype)
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
    def terminate(self):
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        """raises SystemExit in the context of the given thread, which should 
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
        cause the thread to exit silently (unless caught)"""
83b28fc0d731 improve on ldt test framework
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
        self.raise_exc(SystemExit)