__init__.py (26398B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\locks\__init__.py 2 from __future__ import print_function 3 import blue 4 import sys 5 import stackless 6 import traceback2 as traceback 7 import re 8 import weakref 9 import contextlib 10 import heapq 11 import logmodule as log 12 import functools 13 import copy 14 from itertools import chain 15 from collections import defaultdict, deque 16 from ccpProfile import TimedFunction 17 FORMAT = traceback.FORMAT_LOGSRV | traceback.FORMAT_SINGLE 18 19 def Startup(new): 20 StartEventQueue(new) 21 22 23 def ChannelTasklets(channel): 24 result = [] 25 t = first = channel.queue 26 while t: 27 result.append(t) 28 t = t.next 29 if t is first: 30 break 31 32 return result 33 34 35 class LockInheritanceMap(object): 36 37 def __init__(self): 38 self.inherits = {} 39 40 def AddInheritance(self, parent, child): 41 if child in self.inherits: 42 raise ValueError('%r already inherits locks' % child) 43 parents = (parent,) 44 try: 45 parents += self.inherits[parent] 46 except KeyError: 47 pass 48 49 self.inherits[child] = parents 50 51 def RemoveInheritance(self, child): 52 del self.inherits[child] 53 54 def Inherits(self, parent, child = None): 55 if child is None: 56 child = stackless.getcurrent() 57 try: 58 return child is parent or parent in self.inherits[child] 59 except KeyError: 60 return False 61 62 def GetInheritances(self): 63 return [ (c, p[0]) for c, p in self.inherits.iteritems() ] 64 65 @contextlib.contextmanager 66 def Inheritance(self, parent): 67 child = stackless.getcurrent() 68 self.AddInheritance(parent, child) 69 try: 70 yield 71 finally: 72 self.RemoveInheritance(child) 73 74 75 _inheritance = LockInheritanceMap() 76 Inheritance = _inheritance.Inheritance 77 Inherits = _inheritance.Inherits 78 79 class EventQueue(object): 80 81 def __init__(self): 82 self.queue = [] 83 self.fuzz = 0.001 84 85 @staticmethod 86 def clock(): 87 return blue.os.GetWallclockTimeNow() * 1e-07 88 89 def push(self, when, what): 90 heapq.heappush(self.queue, (when, what)) 91 if self.queue[0][0] == when: 92 delta = max(0.0, when - self.clock()) 93 blue.pyos.NextScheduledEvent(int(delta * 1000.0)) 94 95 def pump(self): 96 if not self.queue: 97 return 98 now = self.clock() + self.fuzz 99 batch = [] 100 while self.queue and self.queue[0][0] <= now: 101 batch.append(heapq.heappop(self.queue)) 102 103 for when, what in batch: 104 what() 105 106 def next_time(self): 107 if self.queue: 108 return self.queue[0][0] 109 110 def next_delay(self): 111 if self.queue: 112 return max(0.0, self.queue[0][0] - self.clock()) 113 114 115 eventQueue = EventQueue() 116 117 def StartEventQueue(new): 118 119 def Loop(): 120 while True: 121 try: 122 eventQueue.pump() 123 t = eventQueue.next_delay() 124 if t is not None: 125 blue.pyos.NextScheduledEvent(int(t * 1000)) 126 except Exception: 127 log.LogException() 128 sys.exc_clear() 129 130 blue.pyos.synchro.Yield() 131 132 new(Loop).context = 'EventQueueLoop' 133 134 135 class LockTimeout(StopIteration): 136 pass 137 138 139 def WaitWithTimeout(channel, timeout): 140 waiting = True 141 me = stackless.getcurrent() 142 143 def wakeup(): 144 if waiting: 145 me.raise_exception(LockTimeout) 146 147 eventQueue.push(eventQueue.clock() + timeout, wakeup) 148 try: 149 channel.receive() 150 except LockTimeout: 151 return True 152 finally: 153 waiting = False 154 155 return False 156 157 158 class ContextMixin(object): 159 160 def __enter__(self): 161 self.acquire() 162 return self 163 164 def __exit__(self, exc, val, tb): 165 try: 166 self.release() 167 except Exception: 168 if exc: 169 log.LogException('supressed error in ContextMixin.__exit__') 170 else: 171 raise 172 173 174 class LockMixin(ContextMixin): 175 176 def LockedFor(self): 177 if self.lockedWhen: 178 return (blue.os.GetWallclockTime() - self.lockedWhen) * 1e-07 179 return -1.0 180 181 def __repr__(self): 182 return '<%s %r, t=%f at %#x>' % (self.__class__.__name__, 183 self.name, 184 self.LockedFor(), 185 id(self)) 186 187 188 class FifoLock(LockMixin): 189 __guid__ = 'locks.FifoLock' 190 191 def __init__(self, name = 'noname'): 192 self.name = name 193 self.waiting = stackless.channel() 194 self.waiting.preference = 1 195 self.owning = None 196 self.lockedWhen = None 197 lockManager.Register(self) 198 199 def acquire(self, blocking = True): 200 if self.owning: 201 if not blocking: 202 return False 203 try: 204 self.waiting.receive() 205 except: 206 self._except_release() 207 raise 208 209 else: 210 self.owning = stackless.getcurrent() 211 self.lockedWhen = blue.os.GetTime() 212 return True 213 214 def _except_release(self): 215 try: 216 if self.owning is stackless.getcurrent(): 217 self.release() 218 except Exception: 219 pass 220 221 def release(self): 222 self.owning = None 223 self.lockedWhen = None 224 if self.waiting.balance < 0: 225 self.owning = self.waiting.queue 226 self.lockedWhen = blue.os.GetTime() 227 self.waiting.send(None) 228 229 def IsCool(self): 230 return self.owning is None 231 232 def HoldingTasklets(self): 233 if self.owning: 234 return [self.owning] 235 return [] 236 237 def WaitingTasklets(self): 238 return ChannelTasklets(self.waiting) 239 240 def LockedAt(self): 241 return self.lockedWhen 242 243 def Unblock(self): 244 self.release() 245 246 247 class Lock(LockMixin): 248 249 def __init__(self, name = 'noname'): 250 self.name = name 251 self.waiting = stackless.channel() 252 self.waiting.preference = 1 253 self.nWaiting = 0 254 self.owning = [] 255 self.lockedWhen = None 256 lockManager.Register(self) 257 258 def acquire(self, blocking = 1): 259 if not blocking: 260 return self.try_acquire() 261 while not self.try_acquire(): 262 try: 263 self.nWaiting += 1 264 try: 265 self.waiting.receive() 266 finally: 267 self.nWaiting -= 1 268 269 except: 270 self._safe_pump() 271 raise 272 273 return True 274 275 def try_acquire(self): 276 if not self.owning: 277 self.lockedWhen = blue.os.GetWallclockTime() 278 self.owning.append(stackless.getcurrent()) 279 return True 280 return False 281 282 def release(self): 283 if not self.owning: 284 raise RuntimeError('invalid unlock') 285 self.owning.pop() 286 if not self.owning: 287 self.lockedWhen = None 288 self._pump() 289 290 def _release_save(self): 291 r = self.owning 292 self.owning = [] 293 self.lockedWhen = None 294 self._pump() 295 return r 296 297 def _acquire_restore(self, state): 298 self.acquire() 299 self.owning = state 300 301 def _pump(self): 302 if not self.owning and self.waiting.balance: 303 self.waiting.send(None) 304 305 def _safe_pump(self): 306 try: 307 self._pump() 308 except Exception: 309 pass 310 311 def _is_owned(self): 312 return self.owning and self.owning[0] is stackless.getcurrent() 313 314 def IsCool(self): 315 return not (self.owning or self.nWaiting) 316 317 def LockedAt(self): 318 return self.lockedWhen 319 320 def HoldingTasklets(self): 321 return self.owning[:] 322 323 def WaitingTasklets(self): 324 return ChannelTasklets(self.waiting) 325 326 def Unblock(self): 327 self._release_save() 328 329 330 class RLock(Lock): 331 332 def try_acquire(self): 333 current = stackless.getcurrent() 334 if not self.owning or Inherits(self.owning[0], current): 335 if not self.owning: 336 self.lockedWhen = blue.os.GetWallclockTime() 337 self.owning.append(current) 338 return True 339 return False 340 341 def _is_owned(self): 342 return self.owning and Inherits(self.owning[0], stackless.getcurrent()) 343 344 345 class Condition(ContextMixin): 346 347 def __init__(self, lock = None, name = 'noname'): 348 if not lock: 349 lock = RLock(name) 350 self.lock = lock 351 self.name = name 352 self.waiting = stackless.channel() 353 self.waiting.preference = 1 354 self.acquire = lock.acquire 355 self.try_acquire = lock.try_acquire 356 self.release = lock.release 357 try: 358 self._release_save = lock._release_save 359 self._acquire_restore = lock._acquire_restore 360 except AttributeError: 361 pass 362 363 try: 364 self._is_owned = lock._is_owned 365 except AttributeError: 366 pass 367 368 def __repr__(self): 369 return '<Condition %r, %r, %d at %#x)>' % (self.name, 370 self.lock, 371 -self.waiting.balance, 372 id(self)) 373 374 def _release_save(self): 375 self.lock.release() 376 377 def _acquire_restore(self, x): 378 self.lock.acquire() 379 380 def _is_owned(self): 381 if self.lock.acquire(0): 382 self.lock.release() 383 return False 384 else: 385 return True 386 387 def wait(self, timeout = None): 388 if not self._is_owned(): 389 raise RuntimeError('must have lock when waiting') 390 saved = self._release_save() 391 try: 392 if timeout is None: 393 self.waiting.receive() 394 else: 395 WaitWithTimeout(self.waiting, timeout) 396 finally: 397 self._acquire_restore(saved) 398 399 def notify(self): 400 if not self._is_owned(): 401 raise RuntimeError('must have lock when waiting') 402 if self.waiting.balance: 403 self.waiting.send(None) 404 405 def notify_all(self): 406 if not self._is_owned(): 407 raise RuntimeError('must have lock when waiting') 408 for i in xrange(-self.waiting.balance): 409 self.waiting.send(None) 410 411 notifyAll = notify_all 412 413 def Unblock(self): 414 for i in xrange(-self.waiting.balance): 415 self.waiting.send(None) 416 417 418 class Event(object): 419 420 def __init__(self, name = 'none'): 421 self.waiting = stackless.channel() 422 self.waiting.preference = 1 423 self.name = name 424 self.state = False 425 426 def is_set(self): 427 return self.state 428 429 isSet = is_set 430 431 def set(self): 432 self.state = True 433 for i in xrange(-self.waiting.balance): 434 self.waiting.send(None) 435 436 def clear(self): 437 self.state = False 438 439 def wait(self, timeout = None): 440 if not self.state: 441 if timeout is None: 442 self.waiting.receive() 443 else: 444 WaitWithTimeout(self.waiting, timeout) 445 446 447 class RWLock(LockMixin): 448 449 def __init__(self, lockName = 'noname'): 450 self.name = lockName 451 self.rchan = stackless.channel() 452 self.wchan = stackless.channel() 453 self.rchan.preference = self.wchan.preference = 1 454 self.nWaiting = [0, 0] 455 self.state = 0 456 self.owning = [] 457 self.lockedWhen = None 458 lockManager.Register(self) 459 460 def __repr__(self): 461 return '<RWLock %r held by %r, state:%d, rdwait:%d, wrwait:%d, t:%f at %#x>' % (self.name, 462 self.owning, 463 self.state, 464 -self.rchan.balance, 465 -self.wchan.balance, 466 self.LockedFor(), 467 id(self)) 468 469 def try_acquire(self): 470 current = stackless.getcurrent() 471 if self.state == 0 or self.state < 0 and Inherits(self.owning[0], current): 472 self.state -= 1 473 self.owning.append(current) 474 if not self.lockedWhen: 475 self.lockedWhen = blue.os.GetWallclockTime() 476 return True 477 return False 478 479 def try_acquire_read(self): 480 if self.state < 0: 481 return self.try_acquire() 482 current = stackless.getcurrent() 483 if not self.nWaiting[1]: 484 ok = True 485 else: 486 for owning in self.owning: 487 if Inherits(owning, current): 488 ok = True 489 break 490 else: 491 ok = False 492 493 if ok: 494 self.state += 1 495 self.owning.append(current) 496 if not self.lockedWhen: 497 self.lockedWhen = blue.os.GetWallclockTime() 498 return True 499 return False 500 501 def acquire(self, blocking = True): 502 while not self.try_acquire(): 503 if not blocking: 504 return False 505 self._wait(self.wchan, 1) 506 507 return True 508 509 def acquire_read(self, blocking = True): 510 while not self.try_acquire_read(): 511 if not blocking: 512 return False 513 self._wait(self.rchan, 0) 514 515 def _wait(self, channel, i): 516 try: 517 self.nWaiting[i] += 1 518 try: 519 channel.receive() 520 finally: 521 self.nWaiting[i] -= 1 522 523 except: 524 self._safe_pump() 525 raise 526 527 def _safe_pump(self): 528 try: 529 self._pump() 530 except Exception: 531 pass 532 533 def release(self): 534 try: 535 self.owning.remove(stackless.getcurrent()) 536 except ValueError: 537 raise RuntimeError('Trying to release a rwlock without a matching lock!') 538 539 if self.state > 0: 540 self.state -= 1 541 else: 542 self.state += 1 543 if self.state == 0: 544 self.lockedWhen = None 545 self._pump() 546 547 def _pump(self): 548 while True: 549 if self.nWaiting[1]: 550 if self.state == 0 and -self.wchan.balance == self.nWaiting[1]: 551 self.wchan.send(None) 552 elif self.state >= 0 and self.rchan.balance: 553 self.rchan.send(None) 554 continue 555 break 556 557 class LockContext(object): 558 559 def __init__(self, lock): 560 self.lock = lock 561 562 def __enter__(self): 563 self.lock.acquire_read() 564 565 def __exit__(self, e, v, tb): 566 self.lock.release() 567 568 def acquired_read(self): 569 return self.LockContext(self) 570 571 def acquired(self): 572 return self 573 574 def _is_owned(self): 575 return self.state < 0 and Inherits(self.owning[0]) 576 577 def _release_save(self): 578 r = self.owning 579 self.owning = [] 580 self.state = 0 581 self.lockedWhen = None 582 self._pump() 583 return r 584 585 def _acquire_restore(self, x): 586 self.acquire() 587 self.owning = x 588 self.state = -len(x) 589 590 def IsCool(self): 591 return self.state == 0 and self.nWaiting[0] == 0 and self.nWaiting[1] == 0 592 593 def WaitingTasklets(self): 594 return ChannelTasklets(self.rchan) + ChannelTasklets(self.wchan) 595 596 def HoldingTasklets(self): 597 return self.owning[:] 598 599 def LockedAt(self): 600 return self.lockedWhen 601 602 def Unblock(self): 603 self._release_save() 604 605 606 def SingletonCall(f): 607 mapping = {} 608 609 @functools.wraps(f) 610 def helper(*args): 611 key = args 612 c = mapping.get(key, None) 613 if c: 614 return c.receive() 615 c = stackless.channel() 616 c.preference = 0 617 mapping[key] = c 618 try: 619 r = f(*args) 620 del mapping[key] 621 for i in xrange(-c.balance): 622 c.send(r) 623 624 return r 625 except: 626 del mapping[key] 627 e, v = sys.exc_info()[:2] 628 for i in xrange(-c.balance): 629 c.send_exception(e, v) 630 631 raise 632 633 return helper 634 635 636 class GraphNode(object): 637 638 def __init__(self): 639 self.e_in = set() 640 self.e_out = set() 641 642 643 class Graph(object): 644 645 def __init__(self): 646 self.nodes = defaultdict(GraphNode) 647 648 def __getitem__(self, key): 649 node = self.nodes[key] 650 node.key = key 651 return node 652 653 def __len__(self): 654 return len(self.nodes) 655 656 def AddEdge(self, a, b): 657 self[a].e_out.add(b) 658 self[b].e_in.add(a) 659 660 def PathsFrom(self, node): 661 result = [] 662 stack = [] 663 664 def descend(o): 665 r = o in stack 666 stack.append(o) 667 children = self.nodes[o].e_out 668 if children and not r: 669 for n in children: 670 descend(n) 671 672 else: 673 result.append(stack[:]) 674 stack.pop(-1) 675 676 descend(node) 677 descend = None 678 return result 679 680 def CyclesFrom(self, node): 681 result = [] 682 stack = [] 683 684 def descend(o): 685 if o in stack: 686 result.append(stack[stack.index(o):]) 687 return 688 neighbours = self.nodes[o].e_out 689 if not neighbours: 690 return 691 stack.append(o) 692 for n in neighbours: 693 descend(n) 694 695 stack.pop(-1) 696 697 descend(node) 698 descend = None 699 return result 700 701 def FindRoots(self): 702 result = [] 703 for i, e in self.nodes.iteritems(): 704 if not e.e_in: 705 result.append(i) 706 707 return result 708 709 @TimedFunction('Graph::FindCycles') 710 def FindCycles(self): 711 cycles = [] 712 for SCC in self.Tarjan_SCC(): 713 if len(SCC) <= 1: 714 continue 715 startnode = min(SCC, key=lambda n: n.index) 716 cycles += self.CyclesFrom(startnode.key) 717 718 return cycles 719 720 def Tarjan_SCC(self): 721 722 class idx: 723 i = 0 724 725 S = deque() 726 result = [] 727 728 def strongconnect(node): 729 node.index = idx.i 730 node.lowlink = idx.i 731 idx.i += 1 732 S.append(node) 733 node.onStack = True 734 for nextnode in node.e_out: 735 w = self.nodes[nextnode] 736 if not hasattr(w, 'index'): 737 strongconnect(w) 738 node.lowlink = min(node.lowlink, w.lowlink) 739 elif w.onStack: 740 node.lowlink = min(node.lowlink, w.index) 741 742 if node.lowlink == node.index: 743 strongcomponent = [] 744 while True: 745 successor = S.pop() 746 successor.onStack = False 747 strongcomponent.append(successor) 748 if successor == node: 749 break 750 751 result.append(strongcomponent) 752 753 for k, n in self.nodes.iteritems(): 754 if not hasattr(n, 'index'): 755 strongconnect(n) 756 757 return result 758 759 760 @TimedFunction('Locks::GetDependencyGraph') 761 def GetDependencyGraph(): 762 g = Graph() 763 for l in lockManager.GetLocks(): 764 time = l.LockedFor() 765 if time >= 0: 766 g[l].time = time 767 for t in l.HoldingTasklets(): 768 g.AddEdge(t, l) 769 770 for t in l.WaitingTasklets(): 771 g.AddEdge(l, t) 772 773 for c, p in _inheritance.GetInheritances(): 774 g.AddEdge(c, p) 775 776 return g 777 778 779 sem_re = re.compile('Semaphore (.+) has been held up') 780 781 def GetDependencyGraphFromConflictLog(text): 782 lines = text.splitlines() 783 lockCnt = 0 784 locks = [] 785 g = Graph() 786 for l in lines: 787 l = l.strip() 788 if not l: 789 continue 790 m = sem_re.search(l) 791 if m: 792 name = m.group(1) + str(lockCnt) 793 lockCnt += 1 794 currentLock = name 795 locks.append(name) 796 elif 'waiting thread' in l: 797 where = l.index('<') 798 name = l[where:] 799 g.AddEdge(currentLock, name) 800 elif 'holding thread' in l: 801 where = l.index('<') 802 name = l[where:] 803 g.AddEdge(name, currentLock) 804 805 return g 806 807 808 @TimedFunction('Locks::LockCycleReport') 809 def LockCycleReport(graph = None, out = None, timeLimit = None, pathLimit = 10): 810 if not graph: 811 g = GetDependencyGraph() 812 else: 813 g = graph 814 if out is None: 815 out = sys.stdout 816 cycles = g.FindCycles() 817 roots = g.FindRoots() 818 819 def PathTime(graphpath): 820 return sum((getattr(g[node], 'time', 0) for node in graphpath)) 821 822 npaths = 0 823 paths = [] 824 for r in roots: 825 p = g.PathsFrom(r) 826 npaths += len(p) 827 longest = max(p, key=lambda pl: len(pl)) 828 t = PathTime(longest) 829 if timeLimit is None or t is None or t > timeLimit: 830 paths.append((longest, t)) 831 832 if not cycles and not paths: 833 return False 834 paths.sort(key=lambda pa: (pa[1], len(pa[0])), reverse=True) 835 if pathLimit: 836 del paths[pathLimit:] 837 players = [] 838 seen = set() 839 nc = 0 840 mapping = {} 841 for p in chain(cycles, (p[0] for p in paths)): 842 for n in p: 843 if n not in seen: 844 seen.add(n) 845 players.append(n) 846 mapping[n] = 'N%d' % nc 847 nc += 1 848 849 print('Found %s cycles' % len(cycles), file=out) 850 for i, cycle in enumerate(cycles): 851 print('%2d: ' % i, end=' ', file=out) 852 for e in cycle: 853 print('%s -> ' % mapping[e], end=' ', file=out) 854 855 print(file=out) 856 857 print('Found %s roots in %s paths (showing longest path for each root)' % (len(paths), npaths), file=out) 858 for i, pathentry in enumerate(paths): 859 path = pathentry[0] 860 time = pathentry[1] 861 if time is not None: 862 print('%2d, t=%4.0fs: ' % (i, time), end=' ', file=out) 863 else: 864 print('%2d, : ' % (i,), end=' ', file=out) 865 for e in path[:-1]: 866 print('%s -> ' % mapping[e], end=' ', file=out) 867 868 print('%s' % mapping[path[-1]], file=out) 869 870 minimum = 0 871 if cycles: 872 minimum = max(minimum, len(cycles[0])) 873 if paths: 874 minimum = max(minimum, len(paths[0][0])) 875 maximum = max(minimum, 10) 876 print('where:', file=out) 877 for v in players[0:maximum]: 878 k = mapping[v] 879 print(' %3s = %r' % (k, v), end=' ', file=out) 880 if stackless and isinstance(v, stackless.tasklet): 881 print(':', file=out) 882 try: 883 if not v.alive: 884 print('dead', file=out) 885 elif v.frame: 886 for s in traceback.format_list(traceback.extract_stack(v.frame, 40), format=FORMAT): 887 print(' ' + s, end=' ', file=out) 888 889 else: 890 print('no frame', file=out) 891 except Exception: 892 pass 893 894 elif hasattr(v, 'WaitingTasklets') and hasattr(v, 'HoldingTasklets'): 895 print('( blocks tasklets', [ '0x%x' % id(t) for t in v.WaitingTasklets() ], 'and held by', [ '0x%x' % id(t) for t in v.HoldingTasklets() ], ')', file=out) 896 897 return True 898 899 900 def OldLockReport(threshold = None, out = None): 901 if out is None: 902 out = sys.stdout 903 now = blue.os.GetWallclockTime() 904 result = False 905 for each in lockManager.GetLocks(): 906 if threshold is None or each.LockedAt() and (now - each.LockedAt()) * 1e-07 >= threshold: 907 waiting = each.WaitingTasklets() 908 if not waiting: 909 continue 910 result = True 911 holding = each.HoldingTasklets() 912 if each.LockedAt(): 913 dt = (now - each.LockedAt()) * 1e-07 914 else: 915 dt = -1 916 print('Semaphore %r has been held up for a long time (%ss).' % (each, dt), file=out) 917 for t in waiting: 918 print('waiting thread: %r' % t, file=out) 919 if False: 920 try: 921 for s in traceback.format_list(traceback.extract_stack(t.frame, 40)): 922 print(s, end=' ', file=out) 923 924 except Exception: 925 sys.exc_clear() 926 927 for t in holding: 928 print('holding thread: %r' % t, file=out) 929 try: 930 for s in traceback.format_list(traceback.extract_stack(t.frame, 40)): 931 print(s, end=' ', file=out) 932 933 except Exception: 934 sys.exc_clear() 935 936 if t.paused: 937 print("Holding thread is paused, let's restart it!!! Oh, and tell Kristjan", file=out) 938 try: 939 t.insert() 940 print('unpaused.', file=out) 941 except Exception: 942 sys.exc_clear() 943 944 elif not t.alive: 945 print('Holding thread is dead. Just release the semaphore and tell Kristjan', file=out) 946 if hasattr(each, 'Unblock'): 947 each.Unblock() 948 print('semaphore released', file=out) 949 else: 950 try: 951 each.release(True) 952 print('semaphore released', file=out) 953 except Exception: 954 sys.exc_clear() 955 956 return result 957 958 959 class LockManager(object): 960 961 def __init__(self): 962 self.locks = weakref.WeakKeyDictionary() 963 self.locksByName = weakref.WeakValueDictionary() 964 965 def Register(self, lock): 966 self.locks[lock] = None 967 968 def GetLocks(self): 969 return self.locks.keys() 970 971 def TempLock(self, key, lockClass = RLock): 972 lock = self.locksByName.get(key, None) 973 if lock is None: 974 lock = lockClass(str(key)) 975 self.locksByName[key] = lock 976 return lock 977 978 979 lockManager = LockManager() 980 Register = lockManager.Register 981 GetLocks = lockManager.GetLocks 982 TempLock = lockManager.TempLock 983 exports = {'locks.GetDependencyGraphFromConflictLog': GetDependencyGraphFromConflictLog, 984 'locks.GetDependencyGraph': GetDependencyGraph, 985 'locks.LockCycleReport': LockCycleReport, 986 'locks.OldLockReport': OldLockReport, 987 'locks.Register': Register, 988 'locks.GetLocks': GetLocks, 989 'locks.TempLock': TempLock, 990 'locks.Inheritance': Inheritance, 991 'locks.Inherits': Inherits, 992 'locks.Lock': Lock, 993 'locks.RLock': RLock, 994 'locks.RWLock': RWLock, 995 'locks.Condition': Condition, 996 'locks.Event': Event, 997 'locks.FifoLock': FifoLock, 998 'locks.eventQueue': eventQueue, 999 'locks.Startup': Startup, 1000 'locks.SingletonCall': SingletonCall}