def on(hook_type, state_or_event_name = nil, async = nil, &callback)
      sync_exclusive do
        if state_or_event_name.nil?
          state_or_event_name = HookEvent.any_state_or_event(hook_type)
        end
        async = false if async.nil?
        ensure_valid_callback_name!(hook_type, state_or_event_name)
        callback.extend(Async) if async == :async
        hooks.register(hook_type, state_or_event_name, callback)
      end
    end
def on(hook_type, state_or_event_name = nil, async = nil, &callback)
      sync_exclusive do
        if state_or_event_name.nil?
          state_or_event_name = HookEvent.any_state_or_event(hook_type)
        end
        async = false if async.nil?
        ensure_valid_callback_name!(hook_type, state_or_event_name)
        callback.extend(Async) if async == :async
        hooks.register(hook_type, state_or_event_name, callback)
      end
    end
Register callback for a given hook type

 @param [HookEvent] hook_type
 @param [Symbol] state_or_event_name
 @param [Proc] callback

 @example
   observer.on HookEvent::Enter, :green

 @api public