package toothpick;

import java.util.Stack;
import toothpick.config.Binding;

import static java.lang.String.format;

public abstract class Configuration {

  public static volatile Configuration instance;

  abstract void checkIllegalBinding(Binding binding);

  abstract void checkCyclesStart(Class clazz);

  abstract void checkCyclesEnd();

  static {
    //default mode is production
    production();
  }

  public static void development() {
    instance = new Configuration() {
      private Stack<Class> cycleDetectionStack = new Stack<>();

      @Override
      void checkIllegalBinding(Binding binding) {

      }

      @Override
      void checkCyclesStart(Class clazz) {
        if (cycleDetectionStack.contains(clazz)) {
          //TODO make the message better
          throw new CyclicDependencyException(format("Class %s creates a cycle", clazz.getName()));
        }

        cycleDetectionStack.push(clazz);
      }

      @Override
      void checkCyclesEnd() {
        cycleDetectionStack.pop();
      }
    };
  }

  public static void production() {
    instance = new Configuration() {
      @Override
      void checkIllegalBinding(Binding binding) {
        //do nothing
      }

      @Override
      void checkCyclesStart(Class clazz) {
        //do nothing
      }

      @Override
      void checkCyclesEnd() {
        //do nothing
      }
    };
  }

  /**
   * Allows to pass custom configurations.
   *
   * @param configuration the configuration to use
   */
  static void setConfiguration(Configuration configuration) {
    instance = configuration;
  }
}

@@ -37,16 +37,65 @@
 .Stack;%0A
+import java.util.concurrent.locks.ReentrantLock;%0A
 import t
@@ -119,16 +119,16 @@
 inding;%0A
-
 %0Aimport 
@@ -591,16 +591,127 @@
 ack%3C%3E();
+%0A      //used to make the cycle check atomic. %0A      private ReentrantLock reentrantLock = new ReentrantLock();
 %0A%0A      
@@ -1083,16 +1083,46 @@
 clazz);%0A
+        reentrantLock.lock();%0A
       %7D%0A
@@ -1160,32 +1160,32 @@
 ckCyclesEnd() %7B%0A
-
         cycleDet
@@ -1199,24 +1199,56 @@
 tack.pop();%0A
+        reentrantLock.unlock();%0A
       %7D%0A    

Make cycle detection atomic. No 2 threads should use getInstance at the same time. The lock is shared for all scopes. This is a problem.