private void collectAndRegisterOtherDebuggersThreads(List<PyThreadInfo> threads) {
   for (RemoteDebugger d : getOtherDebuggers()) {
     threads.addAll(d.getThreads());
     for (PyThreadInfo t : d.getThreads()) {
       myThreadRegistry.register(t.getId(), d);
     }
   }
 }
  private List<PyThreadInfo> collectAllThreads() {
    List<PyThreadInfo> result = Lists.newArrayList();

    result.addAll(myMainDebugger.getThreads());

    // collect threads and add them to registry to faster access
    // we don't register mainDebugger as it is default if there is no mapping
    for (RemoteDebugger d : myOtherDebuggers) {
      result.addAll(d.getThreads());
      for (PyThreadInfo t : d.getThreads()) {
        myThreadRegistry.register(t.getId(), d);
      }
    }

    return result;
  }
  @NotNull
  private ProcessDebugger debugger(@NotNull String threadId) {
    ProcessDebugger debugger = myThreadRegistry.getDebugger(threadId);
    if (debugger != null) {
      return debugger;
    } else {
      // thread is not found in registry - lets search for it in attached debuggers

      for (ProcessDebugger d : myOtherDebuggers) {
        for (PyThreadInfo thread : d.getThreads()) {
          if (threadId.equals(thread.getId())) {
            return d;
          }
        }
      }

      // if not found then return main debugger
      return myMainDebugger;
    }
  }
 private static List<PyThreadInfo> addProcessIdToThreadName(
     List<PyThreadInfo> threads, List<PyThreadInfo> result) {
   for (PyThreadInfo t : threads) {
     String threadName = ThreadRegistry.threadName(t.getName(), t.getId());
     PyThreadInfo newThread =
         new PyThreadInfo(t.getId(), threadName, t.getFrames(), t.getStopReason(), t.getMessage());
     newThread.updateState(t.getState(), t.getFrames());
     result.add(newThread);
   }
   threads = result;
   return threads;
 }
 // todo: extract response processing
 private void processThreadEvent(ProtocolFrame frame) throws PyDebuggerException {
   switch (frame.getCommand()) {
     case AbstractCommand.CREATE_THREAD:
       {
         final PyThreadInfo thread = parseThreadEvent(frame);
         if (!thread.isPydevThread()) { // ignore pydevd threads
           myThreads.put(thread.getId(), thread);
         }
         break;
       }
     case AbstractCommand.SUSPEND_THREAD:
       {
         final PyThreadInfo event = parseThreadEvent(frame);
         PyThreadInfo thread = myThreads.get(event.getId());
         if (thread == null) {
           LOG.error(
               "Trying to stop on non-existent thread: "
                   + event.getId()
                   + ", "
                   + event.getStopReason()
                   + ", "
                   + event.getMessage());
           myThreads.put(event.getId(), event);
           thread = event;
         }
         thread.updateState(PyThreadInfo.State.SUSPENDED, event.getFrames());
         thread.setStopReason(event.getStopReason());
         thread.setMessage(event.getMessage());
         myDebugProcess.threadSuspended(thread);
         break;
       }
     case AbstractCommand.RESUME_THREAD:
       {
         final String id = ProtocolParser.getThreadId(frame.getPayload());
         final PyThreadInfo thread = myThreads.get(id);
         if (thread != null) {
           thread.updateState(PyThreadInfo.State.RUNNING, null);
           myDebugProcess.threadResumed(thread);
         }
         break;
       }
     case AbstractCommand.KILL_THREAD:
       {
         final String id = frame.getPayload();
         final PyThreadInfo thread = myThreads.get(id);
         if (thread != null) {
           thread.updateState(PyThreadInfo.State.KILLED, null);
           myThreads.remove(id);
         }
         break;
       }
     case AbstractCommand.SHOW_CONSOLE:
       {
         final PyThreadInfo event = parseThreadEvent(frame);
         PyThreadInfo thread = myThreads.get(event.getId());
         if (thread == null) {
           myThreads.put(event.getId(), event);
           thread = event;
         }
         thread.updateState(PyThreadInfo.State.SUSPENDED, event.getFrames());
         thread.setStopReason(event.getStopReason());
         thread.setMessage(event.getMessage());
         myDebugProcess.showConsole(thread);
         break;
       }
   }
 }
 @Override
 public void suspendAllThreads() {
   for (PyThreadInfo thread : getThreads()) {
     suspendThread(thread.getId());
   }
 }