public void executeOnCompletion(final IOAsyncTask completion) {
    if (errorCode != -1) {
      completion.onError(errorCode, errorMessage);
      return;
    }

    boolean executeNow = false;

    synchronized (this) {
      if (tasks == null) {
        tasks = new LinkedList<TaskHolder>();
        minimalReplicated = replicationLineUp.intValue();
        minimalStore = storeLineUp.intValue();
        minimalPage = pageLineUp.intValue();
      }

      // On this case, we can just execute the context directly
      if (replicationLineUp.intValue() == replicated
          && storeLineUp.intValue() == stored
          && pageLineUp.intValue() == paged) {
        // We want to avoid the executor if everything is complete...
        // However, we can't execute the context if there are executions pending
        // We need to use the executor on this case
        if (executorsPending.get() == 0) {
          // No need to use an executor here or a context switch
          // there are no actions pending.. hence we can just execute the task directly on the same
          // thread
          executeNow = true;
        } else {
          execute(completion);
        }
      } else {
        tasks.add(new TaskHolder(completion));
      }
    }

    if (executeNow) {
      // Executing outside of any locks
      completion.done();
    }
  }
 /** @param task */
 private void execute(final IOAsyncTask task) {
   executorsPending.incrementAndGet();
   try {
     executor.execute(
         new Runnable() {
           public void run() {
             try {
               // If any IO is done inside the callback, it needs to be done on a new context
               OperationContextImpl.clearContext();
               task.done();
             } finally {
               executorsPending.decrementAndGet();
             }
           }
         });
   } catch (Throwable e) {
     HornetQServerLogger.LOGGER.errorExecutingIOAsyncTask(e);
     executorsPending.decrementAndGet();
     task.onError(
         HornetQExceptionType.INTERNAL_ERROR.getCode(),
         "It wasn't possible to complete IO operation - " + e.getMessage());
   }
 }
 @Override
 public void executeOnCompletion(final IOAsyncTask runnable) {
   runnable.done();
 }
 @Override
 public void afterCompleteOperations(final IOAsyncTask run) {
   run.done();
 }