public void resetTiming() {
   final HashSet<Object> dupe = new HashSet<Object>();
   for (final ChallengeSolver<?> s : solverList) {
     if (dupe.add(s.getService())) {
       s.getService().getConfig().setWaitForMap(null);
     }
   }
 }
 @SuppressWarnings("unchecked")
 private <T> ArrayList<ChallengeSolver<T>> createList(Challenge<T> c) {
   final ArrayList<ChallengeSolver<T>> ret = new ArrayList<ChallengeSolver<T>>();
   for (final ChallengeSolver<?> s : solverList) {
     try {
       if (s.isEnabled() && s.canHandle(c)) {
         ret.add((ChallengeSolver<T>) s);
       }
     } catch (final Throwable e) {
       logger.log(e);
     }
   }
   return ret;
 }
 public <T> SolverJob<T> handle(final Challenge<T> c) throws InterruptedException, SkipException {
   LogSource logger = LogController.getInstance().getPreviousThreadLogSource();
   if (logger == null) {
     logger = this.logger;
   }
   logger.info("Log to " + logger.getName());
   logger.info("Handle Challenge: " + c);
   final ArrayList<ChallengeSolver<T>> solver = createList(c);
   logger.info("Solver: " + solver);
   if (solver.size() == 0) {
     logger.info("No solver available!");
     throw new SkipException(SkipRequest.BLOCK_HOSTER);
   }
   final SolverJob<T> job = new SolverJob<T>(this, c, solver);
   job.setLogger(logger);
   final Plugin plugin = c.getPlugin();
   if (plugin != null) {
     if (plugin instanceof PluginForHost) {
       ((PluginForHost) plugin).setLastSolverJob(job);
     } else if (plugin instanceof PluginForDecrypt) {
       ((PluginForDecrypt) plugin).setLastSolverJob(job);
     }
   }
   final UniqueAlltimeID jobID = c.getId();
   synchronized (activeJobs) {
     activeJobs.add(job);
     idToJobMap.put(jobID, job);
   }
   try {
     for (final ChallengeSolver<T> cs : solver) {
       logger.info("Send to solver: " + cs + " " + job);
       cs.enqueue(job);
     }
     logger.info("Fire New Job Event");
     fireNewJobEvent(job);
     logger.info("Wait");
     while (!job.isSolved() && !job.isDone()) {
       synchronized (job) {
         if (!job.isSolved() && !job.isDone()) {
           job.wait(10000);
         }
       }
     }
     if (job.getSkipRequest() != null) {
       throw new SkipException(job.getSkipRequest());
     }
     final ResponseList<T> response = job.getResponseAndKill();
     logger.info("All Responses: " + job.getResponses());
     logger.info("Solving Done. Result: " + response);
     return job;
   } catch (InterruptedException e) { // for example downloads have been stopped
     job.kill();
     throw e;
   } finally {
     try {
       synchronized (activeJobs) {
         activeJobs.remove(job);
         idToJobMap.remove(jobID);
       }
     } finally {
       fireJobDone(job);
     }
   }
 }
 private synchronized boolean addSolver(ChallengeSolver<?> solver) {
   if (solverMap.put(solver.getService().getID(), solver.getService()) == null) {
     serviceList.add(solver.getService());
   }
   return solverList.add(solver);
 }