def add_observer(observer=nil, func=:update, &block)
      if observer.nil? && block.nil?
        raise ArgumentError, 'should pass observer as a first argument or block'
      elsif observer && block
        raise ArgumentError.new('cannot provide both an observer and a block')
      end

      if block
        observer = block
        func = :call
      end

      begin
        @mutex.lock
        new_observers = @observers.dup
        new_observers[observer] = func
        @observers = new_observers
        observer
      ensure
        @mutex.unlock
      end
    end
def add_observer(observer=nil, func=:update, &block)
      if observer.nil? && block.nil?
        raise ArgumentError, 'should pass observer as a first argument or block'
      elsif observer && block
        raise ArgumentError.new('cannot provide both an observer and a block')
      end

      if block
        observer = block
        func = :call
      end

      begin
        @mutex.lock
        new_observers = @observers.dup
        new_observers[observer] = func
        @observers = new_observers
        observer
      ensure
        @mutex.unlock
      end
    end
Adds an observer to this set. If a block is passed, the observer will be
 created by this method and no other params should be passed

 @param [Object] observer
   the observer to add

 @param [Symbol] func
   the function to call on the observer during notification. The default
   is :update.

 @return [Object]
   the added observer