def StopInterval(intervalName, table, c=None):
  # This procedure may need to be locked to handle threads properly.
  if not c: c = static._get('c')
  interval = IntervalInContext()
  pair = ProcessPair()
  stopTime = elapsedTime = 0
  
  if not c.has_key('codeTimerOn'): return # can occur if StartInt is called from a
      # new thread that has never initialized code_timer.  In this case, assume
      # code timing should be turned off.
  if not c.codeTimerOn: return
  stopTime = time.time()
  pair = GetPairForProcess(table, c)
  interval = pair.current
  if interval.name == intervalName: # normal case
    # The current interval has come to an end.
    interval.stops = interval.stops + 1
    elapsedTime = stopTime - interval.startTime
    interval.totalTime = interval.totalTime + elapsedTime
    if elapsedTime < interval.minTime: interval.minTime = elapsedTime
    if elapsedTime > interval.maxTime:
      interval.maxTime = elapsedTime
      interval.maxIndex = interval.starts
    if interval.parent != None: pair.current = interval.parent
  else: # encountered a stop while a different interval is active
    interval.prematureStops = interval.prematureStops + 1
    if interval.prematureStops == 1: interval.prematureStopName = intervalName
def StartInterval(intervalName, table, c=None):
  # To work properly in multi-threaded code, this may need to be guarded
  # by a lock.  For now, we use the fact that 'c.' variables are thread-safe.
  #
  # We have encountered the beginning of a new interval.  Add a representation
  # for it as a child of the most recently entered active interval.
  if not c: c = static._get('c')
  interval = IntervalInContext()
  current = IntervalInContext()
  pair = ProcessPair()
  
  if not c.has_key('codeTimerOn'): return # can occur if StartInt is called from a
      # new thread that has never initialized code_timer.  In this case, assume
      # code timing should be turned off.
  if not c.codeTimerOn: return
  pair = GetPairForProcess(table, c)
  current = pair.current
  interval = FindChildIntervalInContext(intervalName, current)
  if interval == None:
    interval = AllocateIntervalInternal(intervalName, c)
    current.children = current.children+[interval]
    interval.parent = current

  interval.starts = interval.starts + 1
  interval.startTime = time.time()
  pair.current = interval
def Init():
  global defaultProcess
  defaultProcess = thread.get_ident()
  c = static._get('c')
  c.TablesRef = {}
  c.intervalPool = [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None] # A maximum of 25 IntervalInContext's
  c.intervalPoolMax = 25
  c.intervalPoolIndex = -1
def StopInt(intervalName, tableName):  
  c = static._get('c')
  if not c.has_key('codeTimerOn'): return # can occur if StartInt is called from a
      # new thread that has never initialized code_timer.  In this case, assume
      # code timing should be turned off.
  if not c.codeTimerOn: return
  table = GetTable(tableName)
  if table == None: table = CreateTable(tableName)
  StopInterval(intervalName, table, c)
def ResetTable(table):
  # This routine may need to be locked in general to support multiple threads
  # The table is a tree of nested intervals.  Return all of these intervals to the
  # interval pool except for the top level interval
  c = static._get('c')
  for pair in table.processes:
    for child in pair.outer.children:
      FreeIntervalAndChildren(child, c)
    pair.outer.children = []
    pair.current = pair.outer
  table.processes = []
def PrintTableHTML(f, table_name):
  table = GetTable(table_name)
  if table == None: return
  f.write('<pre>\n')
  c = static._get('c')
  if (not c.has_key('codeTimerOn')) or (not c.codeTimerOn):
    f.write("<!-- Code Timer appears to be turned off.  To see results, make sure you have")
    f.write(" called code_timer.CodeTimerOn(). -->");
  else:
    f.write("Code Timer performance times in milliseconds:");
  done = ForEachIntervalInContext(f, table, DoPrintIntervalInContext)
  f.write('</pre>\n')
def TimerOff():
  c = static._get('c')
  c.codeTimerOn = 0
def CodeTimerOn():
  c = static._get('c')
  c.codeTimerOn = 1
def AddTableToTables(table):
  c = static._get('c')
  if c.TablesRef.has_key(table.name): raise "ERROR"
  c.TablesRef[table.name] = table
def GetTable(name):
  # returns (table):
  c = static._get('c')
  if c.TablesRef.has_key(name): table = c.TablesRef[name]
  else: table = None
  return table