1 | # -*- coding: iso-8859-1 -*- |
---|
2 | |
---|
3 | |
---|
4 | # |
---|
5 | # synchronized objects and methods. |
---|
6 | # By André Bjärby |
---|
7 | # From http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65202 |
---|
8 | # |
---|
9 | |
---|
10 | from types import * |
---|
11 | |
---|
12 | def _get_method_names (obj): |
---|
13 | if type(obj) == InstanceType: |
---|
14 | return _get_method_names(obj.__class__) |
---|
15 | |
---|
16 | elif type(obj) == ClassType: |
---|
17 | result = [] |
---|
18 | for name, func in obj.__dict__.items(): |
---|
19 | if type(func) == FunctionType: |
---|
20 | result.append((name, func)) |
---|
21 | |
---|
22 | for base in obj.__bases__: |
---|
23 | result.extend(_get_method_names(base)) |
---|
24 | |
---|
25 | return result |
---|
26 | |
---|
27 | |
---|
28 | class _SynchronizedMethod: |
---|
29 | |
---|
30 | def __init__ (self, method, obj, lock): |
---|
31 | self.__method = method |
---|
32 | self.__obj = obj |
---|
33 | self.__lock = lock |
---|
34 | |
---|
35 | def __call__ (self, *args, **kwargs): |
---|
36 | self.__lock.acquire() |
---|
37 | try: |
---|
38 | #print 'Calling method %s from obj %s' % (self.__method, self.__obj) |
---|
39 | return self.__method(self.__obj, *args, **kwargs) |
---|
40 | finally: |
---|
41 | self.__lock.release() |
---|
42 | |
---|
43 | class SynchronizedObject: |
---|
44 | def __init__ (self, obj, ignore=[], lock=None): |
---|
45 | import threading |
---|
46 | |
---|
47 | self.__methods = {} |
---|
48 | self.__obj = obj |
---|
49 | lock = lock and lock or threading.RLock() |
---|
50 | for name, method in _get_method_names(obj): |
---|
51 | if not name in ignore: |
---|
52 | self.__methods[name] = _SynchronizedMethod(method, obj, lock) |
---|
53 | |
---|
54 | def __getattr__ (self, name): |
---|
55 | try: |
---|
56 | return self.__methods[name] |
---|
57 | except KeyError: |
---|
58 | return getattr(self.__obj, name) |
---|
59 | |
---|