// Path: src/main/java/org/ardverk/concurrent/EventUtils.java
// public class EventUtils {
// 
//   private static final EventThreadProvider PROVIDER = newEventThreadProvider();
//   
//   private static EventThreadProvider newEventThreadProvider() {
//     for (EventThreadProvider element : ServiceLoader.load(
//         EventThreadProvider.class)) {
//       return element;
//     }
//     
//     return new DefaultEventThreadProvider();
//   }
//   
//   private EventUtils() {}
// 
//   /**
//    * Returns true if the caller {@link Thread} is the same as the event 
//    * {@link Thread}. In other words {@link Thread}s can use method to 
//    * determinate if they are the event {@link Thread}.
//    */
//   public static boolean isEventThread() {
//     return PROVIDER.isEventThread();
//   }
// 
//   /**
//    * Executes the given {@link Runnable} on the event {@link Thread}.
//    */
//   public static void fireEvent(Runnable event) {
//     PROVIDER.fireEvent(event);
//   }
//   
//   /**
//    * The default event {@link Thread} provider that is being used 
//    * if no other {@link EventThreadProvider} was given.
//    */
//   private static class DefaultEventThreadProvider 
//       implements EventThreadProvider {
// 
//     private final AtomicReference<Thread> reference 
//       = new AtomicReference<Thread>();
//     
//     private final ThreadFactory factory 
//         = new DefaultThreadFactory("DefaultEventThread") {
//       @Override
//       public Thread newThread(Runnable r) {
//         Thread thread = super.newThread(r);
//         reference.set(thread);
//         return thread;
//       } 
//     };
//     
//     private final Executor executor 
//       = Executors.newSingleThreadExecutor(factory);
//     
//     @Override
//     public boolean isEventThread() {
//       return reference.get() == Thread.currentThread();
//     }
//     
//     @Override
//     public void fireEvent(Runnable event) {
//       if (event == null) {
//         throw new NullPointerException("event");
//       }
//       
//       executor.execute(event);
//     }
//   }
// }


import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.ardverk.concurrent.EventUtils;
      this.t = null;
      
      fireUnbind(t);
    }
  }

  public void addBindingListener(BindingListener<T> l) {
    listeners.add(l);
  }

  public void removeBindingListener(BindingListener<T> l) {
    listeners.remove(l);
  }

  @SuppressWarnings("unchecked")
  public BindingListener<T>[] getBindingListeners() {
    return listeners.toArray(new BindingListener[0]);
  }

  protected void fireBind(final T t) {
    if (!listeners.isEmpty()) {
      Runnable event = new Runnable() {
        @Override
        public void run() {
          for (BindingListener<T> l : listeners) {
            l.handleBind(t);
          }
        }
      };
      
// Path: src/main/java/org/ardverk/concurrent/EventUtils.java
// public class EventUtils {
// 
//   private static final EventThreadProvider PROVIDER = newEventThreadProvider();
//   
//   private static EventThreadProvider newEventThreadProvider() {
//     for (EventThreadProvider element : ServiceLoader.load(
//         EventThreadProvider.class)) {
//       return element;
//     }
//     
//     return new DefaultEventThreadProvider();
//   }
//   
//   private EventUtils() {}
// 
//   /**
//    * Returns true if the caller {@link Thread} is the same as the event 
//    * {@link Thread}. In other words {@link Thread}s can use method to 
//    * determinate if they are the event {@link Thread}.
//    */
//   public static boolean isEventThread() {
//     return PROVIDER.isEventThread();
//   }
// 
//   /**
//    * Executes the given {@link Runnable} on the event {@link Thread}.
//    */
//   public static void fireEvent(Runnable event) {
//     PROVIDER.fireEvent(event);
//   }
//   
//   /**
//    * The default event {@link Thread} provider that is being used 
//    * if no other {@link EventThreadProvider} was given.
//    */
//   private static class DefaultEventThreadProvider 
//       implements EventThreadProvider {
// 
//     private final AtomicReference<Thread> reference 
//       = new AtomicReference<Thread>();
//     
//     private final ThreadFactory factory 
//         = new DefaultThreadFactory("DefaultEventThread") {
//       @Override
//       public Thread newThread(Runnable r) {
//         Thread thread = super.newThread(r);
//         reference.set(thread);
//         return thread;
//       } 
//     };
//     
//     private final Executor executor 
//       = Executors.newSingleThreadExecutor(factory);
//     
//     @Override
//     public boolean isEventThread() {
//       return reference.get() == Thread.currentThread();
//     }
//     
//     @Override
//     public void fireEvent(Runnable event) {
//       if (event == null) {
//         throw new NullPointerException("event");
//       }
//       
//       executor.execute(event);
//     }
//   }
// }


// Path: src/main/java/org/ardverk/lang/BindableObject.java
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.ardverk.concurrent.EventUtils;

      this.t = null;
      
      fireUnbind(t);
    }
  }

  public void addBindingListener(BindingListener<T> l) {
    listeners.add(l);
  }

  public void removeBindingListener(BindingListener<T> l) {
    listeners.remove(l);
  }

  @SuppressWarnings("unchecked")
  public BindingListener<T>[] getBindingListeners() {
    return listeners.toArray(new BindingListener[0]);
  }

  protected void fireBind(final T t) {
    if (!listeners.isEmpty()) {
      Runnable event = new Runnable() {
        @Override
        public void run() {
          for (BindingListener<T> l : listeners) {
            l.handleBind(t);
          }
        }
      };
      
      EventUtils.fireEvent(event);