NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

__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}