]> git.llucax.com Git - z.facultad/75.59/filosofos.git/blob - src/sync.py
Primer version con monitores.
[z.facultad/75.59/filosofos.git] / src / sync.py
1 # -*- coding: iso-8859-1 -*-
2 # vim: set expandtab tabstop=4 shiftwidth=4 :
3
4 from threading import Lock
5
6 _gettersetter_code = """
7 def get(self):
8     lock = getattr(self, '__%(attr)sLock')
9     lock.acquire()
10     val = getattr(self, '__%(attr)s')
11     lock.release()
12     return val
13 def set(self, val):
14     if not hasattr(self, '__%(attr)sLock'):
15         setattr(self, '__%(attr)sLock', Lock())
16     lock = getattr(self, '__%(attr)sLock')
17     lock.acquire()
18     setattr(self, '__%(attr)s', val)
19     lock.release()
20 """
21
22 __all__ = ('SyncProp', 'Synchronizable', 'synchronized')
23
24 class SyncProp:
25     """Synchronized property.
26     When using a class attribute as an SyncProp object it protects the property
27     access and modification using a lock (mutex). You should allways inherit
28     from  Synchronizable if you are using SyncProp's.
29     Note that SyncProp only works with non-mutable objects, because it will not
30     protect from method calls.
31
32     Example:
33         class MyClass(Synchronizable):
34             prop = SyncProp("My property.")
35
36         c = MyClass()
37         c.prop = 1      # is like:
38                         # c.__propLock.acquire()
39                         # c.prop = 1
40                         # c.__propLock.release()
41         print c.prop    # is like:
42                         # c.__propLock.acquire()
43                         # tmp = c.prop
44                         # c.__propLock.release()
45                         # print tmp
46                         # del tmp
47     """
48     def __init__(self, docstring=''):
49         "Constructor"
50         self.doc = docstring
51
52 class SynchronizableMeta(type):
53     """Synchronizable meta class.
54     This is the class that makes all the magic. It translate SyncProp attributes
55     to the synchronized properties.
56     """
57     def __new__(cls, clsname, bases, attrs):
58         "Translates SyncProp attributes to the synchronized properties."
59         cls = type.__new__(cls, clsname, bases, attrs)
60         for (attr, obj) in attrs.iteritems():
61             if isinstance(obj, SyncProp):
62                 exec _gettersetter_code % {'attr': attr}
63                 setattr(cls, attr, property(get, set, None, obj.doc))
64         return cls
65
66 class Synchronizable(object):
67     """Synchronizable classes base.
68     All the classes winth SyncProp attributes should inherit from this class to
69     wrap the SyncProp attributes between locks (mutexes).
70
71     Example:
72         class MyClass(Synchronizable):
73             prop = SyncProp("My property.")
74
75         c = MyClass()
76         c.prop = 1      # is like:
77                         # c.__propLock.acquire()
78                         # c.prop = 1
79                         # c.__propLock.release()
80         print c.prop    # is like:
81                         # c.__propLock.acquire()
82                         # tmp = c.prop
83                         # c.__propLock.release()
84                         # print tmp
85                         # del tmp
86     """
87
88     __metaclass__ = SynchronizableMeta
89
90 def synchronized(lockattrname=None):
91     """Synchronized method decorator.
92     This decorator make a method call synchronized. It's not required to
93     inherit classes with synchronized methods from Synchrnonizable. You
94     can optionally pass to the decorator the name of the lock (mutex)
95     attribute to use.
96
97     Example:
98         class MyClass:
99             @synchronized
100             def syncMethod(self, msg):
101                 print self.__name__, msg
102
103         c = MyClass()
104         c.syncMethod("hi!") # is like:
105                             # c.__syncMethodLock.acquire()
106                             # c.synchMethod("hi!")
107                             # c.__syncMethodLock.release()
108     """
109
110     def wrapper(method):
111         def syncMethod(self, *args, **kargs):
112             "Wrapper method."
113             name = lockattrname
114             if name is not None:
115                 name = '__' + method.__name__ + 'Lock'
116             if not hasattr(self, name):
117                 setattr(self, name, Lock())
118             lock = getattr(self, name)
119             lock.acquire()
120             ret = method(self, *args, **kargs)
121             lock.release()
122             return ret
123         return syncMethod
124     return wrapper
125
126 # Simple test
127 if __name__ == '__main__':
128
129     import time
130     from threading import Thread, enumerate, currentThread, Lock
131
132     class Obj:
133         "Dummy test class"
134
135     class SyncObj(Synchronizable):
136         "Dummy test class"
137         value = SyncProp("Dummy value")
138
139         def sleep(self):
140             name = currentThread().getName()
141             print name, 'durmiendo'
142             time.sleep(float('0.'+name))
143         sleep = synchronized(sleep)
144
145     def incObj():
146         for i in xrange(100):
147             #lock.acquire()
148             obj.value = 0xf0f0f0f0f0f0f0+(i<<20)+(i<<14)+(i<<6)
149             #lock.release()
150             #time.sleep(0.0000014)
151             #obj.sleep()
152
153     lock = Lock()
154     obj = SyncObj()
155     #obj = Obj()
156     obj.value = 100000000000000000000000000000
157     for i in xrange(200):
158         Thread(target=incObj, name=str(i+1)).start()
159     for t in enumerate():
160         if t is not currentThread():
161             t.join()
162     print obj.value
163