Package _Framework :: Module Resource
[hide private]
[frames] | no frames]

Source Code for Module _Framework.Resource

  1  #Embedded file name: /Users/versonator/Hudson/live/Projects/AppLive/Resources/MIDI Remote Scripts/_Framework/Resource.py 
  2  from _Framework.Util import index_if, first 
3 4 -class Resource(object):
5
6 - def grab(self, client, *a, **k):
7 raise NotImplemented
8
9 - def release(self, client):
10 raise NotImplemented
11
12 - def get_owner(self):
13 raise NotImplementedError
14 15 owner = property(lambda self: self.get_owner())
16
17 18 -class CompoundResource(Resource):
19
20 - def __init__(self, first_resource = None, second_resource = None, *a, **k):
21 super(CompoundResource, self).__init__(*a, **k) 22 self._first_resource = first_resource 23 self._second_resource = second_resource
24
25 - def grab(self, client, *a, **k):
26 if self._first_resource.grab(client, *a, **k): 27 if self._second_resource.grab(client, *a, **k): 28 pass 29 else: 30 self._first_resource.release(client) 31 return self.owner == client
32
33 - def release(self, client):
34 if not client: 35 raise AssertionError 36 client == self.owner and self._second_resource.release(client) 37 self._first_resource.release(client) 38 return True 39 return False
40
41 - def get_owner(self):
42 return self._first_resource.owner or self._second_resource.owner
43 44 @property
45 - def first(self):
46 return self._first_resource
47 48 @property
49 - def second(self):
50 return self._second_resource
51
52 53 -def compose_resources(*resources):
54 return reduce(CompoundResource, resources)
55
56 57 -class ExclusiveResource(Resource):
58 """ 59 A resource that can not be grabbed any client if it is owned by 60 someone else already. 61 """ 62
63 - def __init__(self, on_grab_callback = None, on_release_callback = None, *a, **k):
64 super(ExclusiveResource, self).__init__(*a, **k) 65 self._owner = None 66 if on_grab_callback: 67 self.on_grab = on_grab_callback 68 if on_release_callback: 69 self.on_release = on_release_callback
70
71 - def grab(self, client, *a, **k):
72 if not client is not None: 73 raise AssertionError, 'Someone has to adquire resource' 74 self._owner == None and self.on_grab(client, *a, **k) 75 self._owner = client 76 return self._owner == client
77
78 - def release(self, client):
79 if not client: 80 raise AssertionError 81 self._owner = client == self._owner and None 82 self.on_release(client) 83 return True 84 return False
85
86 - def get_owner(self):
87 return self._owner
88
89 - def on_grab(self, client, *a, **k):
90 raise NotImplemented, 'Override or pass callback'
91
92 - def on_release(self, client):
93 raise NotImplemented, 'Override or pass callback'
94
95 96 -class SharedResource(Resource):
97 """ 98 A resource that has no owner and will always be grabbed. 99 """ 100
101 - def __init__(self, on_grab_callback = None, on_release_callback = None, *a, **k):
102 super(SharedResource, self).__init__(*a, **k) 103 if on_grab_callback: 104 self.on_grab = on_grab_callback 105 if on_release_callback: 106 self.on_release = on_release_callback 107 self._clients = set()
108
109 - def grab(self, client, *a, **k):
110 raise client is not None or AssertionError, 'Someone has to adquire resource' 111 self.on_grab(client, *a, **k) 112 self._clients.add(client) 113 return True
114
115 - def release(self, client):
116 if not client: 117 raise AssertionError 118 client in self._clients and self.on_release(client) 119 self._clients.remove(client) 120 for client in self._clients: 121 self.on_grab(client) 122 123 return True 124 return False
125
126 - def get_owner(self):
127 raise False or AssertionError, 'Shared resource has no owner'
128
129 - def on_grab(self, client, *a, **k):
130 raise NotImplemented, 'Override or pass callback'
131
132 - def on_release(self, client):
133 raise NotImplemented, 'Override or pass callback'
134
135 136 -class PrioritizedResource(Resource):
137 """ 138 A prioritized resource shares the resource among all the clients 139 with the same priority. 140 """ 141 default_priority = 0 142
143 - def __init__(self, on_grab_callback = None, on_release_callback = None, *a, **k):
144 super(PrioritizedResource, self).__init__(*a, **k) 145 self._clients = [] 146 self._owners = set() 147 if on_grab_callback: 148 self.on_grab = on_grab_callback 149 if on_release_callback: 150 self.on_release = on_release_callback
151
152 - def grab(self, client, priority = None):
153 if not client is not None: 154 raise AssertionError 155 if priority is None: 156 priority = self.default_priority 157 old_owners = self._owners 158 self._remove_client(client) 159 self._add_client(client, priority) 160 new_owners = self._actual_owners() 161 self._owners = new_owners != old_owners and new_owners 162 self._on_release_set(old_owners - new_owners) 163 self._on_grab_set(new_owners) 164 return client in new_owners
165
166 - def _on_release_set(self, clients):
167 for client in clients: 168 self.on_release(client)
169
170 - def _on_grab_set(self, clients):
171 for client in clients: 172 self.on_grab(client)
173
174 - def release(self, client):
175 if not client is not None: 176 raise AssertionError 177 old_owners = self._owners 178 self._remove_client(client) 179 new_owners = self._actual_owners() 180 self._owners = new_owners != old_owners and new_owners 181 self._on_release_set(old_owners - new_owners) 182 self._on_grab_set(new_owners) 183 return client in old_owners
184
185 - def release_all(self):
186 """ 187 Releases all stacked clients. 188 """ 189 for client, _ in list(self._clients): 190 self.release(client)
191
192 - def _add_client(self, client, priority):
193 idx = index_if(lambda (_, p): p > priority, self._clients) 194 self._clients.insert(idx, (client, priority))
195
196 - def _remove_client(self, client):
197 idx = index_if(lambda (c, _): c == client, self._clients) 198 if idx != len(self._clients): 199 del self._clients[idx]
200
201 - def _actual_owners(self):
202 max_priority = self.max_priority 203 return set([ client for client, priority in self._clients if priority == max_priority ])
204 205 @property
206 - def max_priority(self):
207 return self._clients[-1][1] if self._clients else self.default_priority
208 209 @property
210 - def stack_size(self):
211 return len(self._clients)
212
213 - def get_owner(self):
214 raise False or AssertionError, 'Shared resource has no owner'
215 216 @property
217 - def owners(self):
218 return self._actual_owners()
219
220 - def on_grab(self, client):
221 raise NotImplemented, 'Override or pass callback'
222
223 - def on_release(self, client):
224 raise NotImplemented, 'Override or pass callback'
225
226 227 -class StackingResource(Resource):
228 """ 229 A stacking resource is a special kind of resource that can preempt 230 the current owner. Resources are assigned to clients in order of 231 arrival, this is, a new client attempting to grab will produce the 232 former owner to be released. However, when the current owner 233 released ownership will be passed back to the last owner. 234 235 This, clients are organised in a stack, where grabbing puts the 236 client at the top, and releasing removes from wherever the client 237 is in the stack. Because ownership can change even a client does 238 not release, a client should not use the resource based on the 239 result of the grab() method but instead use whatever indirect API 240 the concrete resource provides to assign ownership. 241 242 Clients of a stacking resource can be prioritised to prevent 243 preemption from a client with less priority. (For example, a modal 244 dialog should not loose focus because of a normal window 245 appearing.) 246 """ 247 default_priority = 0 248
249 - def __init__(self, on_grab_callback = None, on_release_callback = None, *a, **k):
250 super(StackingResource, self).__init__(*a, **k) 251 self._clients = [] 252 self._owner = None 253 if on_grab_callback: 254 self.on_grab = on_grab_callback 255 if on_release_callback: 256 self.on_release = on_release_callback
257
258 - def grab(self, client, priority = None):
259 if not client is not None: 260 raise AssertionError 261 if priority is None: 262 priority = self.default_priority 263 old_owner = self._owner 264 self._remove_client(client) 265 self._add_client(client, priority) 266 new_owner = self._actual_owner() 267 if new_owner != old_owner: 268 old_owner is not None and self.on_release(old_owner) 269 self.on_grab(new_owner) 270 self._owner = new_owner 271 return new_owner == client
272
273 - def release(self, client):
274 if not client is not None: 275 raise AssertionError 276 old_owner = self._owner 277 self._remove_client(client) 278 new_owner = self._actual_owner() 279 if new_owner != old_owner: 280 self._owner = new_owner 281 self.on_release(old_owner) 282 new_owner is not None and self.on_grab(new_owner) 283 return old_owner == client
284
285 - def release_stacked(self):
286 """ 287 Releases all objects that are stacked but do not own the 288 resource. 289 """ 290 self.release_if(lambda client: client != self.owner)
291
292 - def release_if(self, predicate):
293 """ 294 Releases all objects that satisfy a predicate. 295 """ 296 for client, _ in list(self._clients): 297 if predicate(client): 298 self.release(client)
299
300 - def release_all(self):
301 """ 302 Releases all stacked clients. 303 """ 304 for client, _ in list(self._clients): 305 self.release(client)
306
307 - def _add_client(self, client, priority):
308 idx = index_if(lambda (_, p): p > priority, self._clients) 309 self._clients.insert(idx, (client, priority))
310
311 - def _remove_client(self, client):
312 idx = index_if(lambda (c, _): c == client, self._clients) 313 if idx != len(self._clients): 314 del self._clients[idx]
315
316 - def _actual_owner(self):
317 return self._clients[-1][0] if self._clients else None
318 319 @property
320 - def stack_clients(self):
321 return map(first, self._clients)
322 323 @property
324 - def max_priority(self):
325 return self._clients[-1][1] if self._clients else self.default_priority
326 327 @property
328 - def stack_size(self):
329 return len(self._clients)
330
331 - def get_owner(self):
332 return self._owner
333
334 - def on_grab(self, client):
335 raise NotImplemented, 'Override or pass callback'
336
337 - def on_release(self, client):
338 raise NotImplemented, 'Override or pass callback'
339