def test_local_1(self): import thread from thread import _local as tlsobject freed = [] class X: def __del__(self): freed.append(1) ok = [] TLS1 = tlsobject() TLS2 = tlsobject() TLS1.aa = "hello" def f(i): success = False try: a = TLS1.aa = i b = TLS1.bbb = X() c = TLS2.cccc = i * 3 d = TLS2.ddddd = X() self.busywait(0.05) assert TLS1.aa == a assert TLS1.bbb is b assert TLS2.cccc == c assert TLS2.ddddd is d success = True finally: ok.append(success) for i in range(20): thread.start_new_thread(f, (i,)) self.waitfor(lambda: len(ok) == 20, delay=3) assert ok == 20 * [True] # see stdout/stderr for failures in the threads self.waitfor(lambda: len(freed) >= 40) assert len(freed) == 40 # in theory, all X objects should have been freed by now. Note that # Python's own thread._local objects suffer from the very same "bug" that # tls.py showed originally, and leaves len(freed)==38: the last thread's # __dict__ remains stored in the TLS1/TLS2 instances, although it is not # really accessible any more. assert TLS1.aa == "hello"
def test_local_1(self): import thread from thread import _local as tlsobject freed = [] class X: def __del__(self): freed.append(1) ok = [] TLS1 = tlsobject() TLS2 = tlsobject() TLS1.aa = "hello" def f(i): success = False try: a = TLS1.aa = i b = TLS1.bbb = X() c = TLS2.cccc = i * 3 d = TLS2.ddddd = X() self.busywait(0.05) assert TLS1.aa == a assert TLS1.bbb is b assert TLS2.cccc == c assert TLS2.ddddd is d success = True finally: ok.append(success) for i in range(20): thread.start_new_thread(f, (i, )) self.waitfor(lambda: len(ok) == 20, delay=3) assert ok == 20 * [True ] # see stdout/stderr for failures in the threads self.waitfor(lambda: len(freed) >= 40) assert len(freed) == 40 # in theory, all X objects should have been freed by now. Note that # Python's own thread._local objects suffer from the very same "bug" that # tls.py showed originally, and leaves len(freed)==38: the last thread's # __dict__ remains stored in the TLS1/TLS2 instances, although it is not # really accessible any more. assert TLS1.aa == "hello"
def specialize_call(self, hop): assert isinstance(hop.args_r[0], raddress.AddressRepr) adr, = hop.inputargs(hop.args_r[0]) hop.exception_cannot_occur() return hop.genop('cast_adr_to_int', [adr], resulttype = lltype.Signed) # ____________________________________________________________ # errno # this saves in a thread-local way the "current" value that errno # should have in C. We have to save it away from one external C function # call to the next. Otherwise a non-zero value left behind will confuse # CPython itself a bit later, and/or CPython will stamp on it before we # try to inspect it via rposix.get_errno(). TLS = tlsobject() # helpers to save/restore the C-level errno -- platform-specific because # ctypes doesn't just do the right thing and expose it directly :-( # on 2.6 ctypes does it right, use it if sys.version_info >= (2, 6): def _save_c_errno(): TLS.errno = ctypes.get_errno() def _restore_c_errno(): pass else: def _where_is_errno():