//===-- Broadcaster.h -------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_Broadcaster_h_
#define liblldb_Broadcaster_h_

#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
#include "lldb/lldb-forward.h" // for ListenerSP, EventSP, Broadcast...

#include "llvm/ADT/SmallVector.h"

#include <cstdint> // for uint32_t, UINT32_MAX
#include <map>
#include <memory> // for shared_ptr, operator==, enable...
#include <mutex>
#include <set> // for set
#include <string>
#include <utility> // for pair
#include <vector>

namespace lldb_private {
class Broadcaster;
}
namespace lldb_private {
class EventData;
}
namespace lldb_private {
class Listener;
}
namespace lldb_private {
class Stream;
}

namespace lldb_private {

//----------------------------------------------------------------------
// lldb::BroadcastEventSpec
//
// This class is used to specify a kind of event to register for.  The Debugger
// maintains a list of BroadcastEventSpec's and when it is made
//----------------------------------------------------------------------
class BroadcastEventSpec {
public:
  BroadcastEventSpec(const ConstString &broadcaster_class, uint32_t event_bits)
      : m_broadcaster_class(broadcaster_class), m_event_bits(event_bits) {}

  BroadcastEventSpec(const BroadcastEventSpec &rhs);

  ~BroadcastEventSpec() = default;

  const ConstString &GetBroadcasterClass() const { return m_broadcaster_class; }

  uint32_t GetEventBits() const { return m_event_bits; }

  // Tell whether this BroadcastEventSpec is contained in in_spec. That is: (a)
  // the two spec's share the same broadcaster class (b) the event bits of this
  // spec are wholly contained in those of in_spec.
  bool IsContainedIn(BroadcastEventSpec in_spec) const {
    if (m_broadcaster_class != in_spec.GetBroadcasterClass())
      return false;
    uint32_t in_bits = in_spec.GetEventBits();
    if (in_bits == m_event_bits)
      return true;
    else {
      if ((m_event_bits & in_bits) != 0 && (m_event_bits & ~in_bits) == 0)
        return true;
    }
    return false;
  }

  bool operator<(const BroadcastEventSpec &rhs) const;
  BroadcastEventSpec &operator=(const BroadcastEventSpec &rhs);

private:
  ConstString m_broadcaster_class;
  uint32_t m_event_bits;
};

class BroadcasterManager
    : public std::enable_shared_from_this<BroadcasterManager> {
public:
  friend class Listener;

protected:
  BroadcasterManager();

public:
  // Listeners hold onto weak pointers to their broadcaster managers.  So they
  // must be made into shared pointers, which you do with
  // MakeBroadcasterManager.

  static lldb::BroadcasterManagerSP MakeBroadcasterManager();

  ~BroadcasterManager() = default;

  uint32_t RegisterListenerForEvents(const lldb::ListenerSP &listener_sp,
                                     BroadcastEventSpec event_spec);

  bool UnregisterListenerForEvents(const lldb::ListenerSP &listener_sp,
                                   BroadcastEventSpec event_spec);

  lldb::ListenerSP GetListenerForEventSpec(BroadcastEventSpec event_spec) const;

  void SignUpListenersForBroadcaster(Broadcaster &broadcaster);

  void RemoveListener(const lldb::ListenerSP &listener_sp);

  void RemoveListener(Listener *listener);

  void Clear();

private:
  typedef std::pair<BroadcastEventSpec, lldb::ListenerSP> event_listener_key;
  typedef std::map<BroadcastEventSpec, lldb::ListenerSP> collection;
  typedef std::set<lldb::ListenerSP> listener_collection;
  collection m_event_map;
  listener_collection m_listeners;

  mutable std::recursive_mutex m_manager_mutex;

  // A couple of comparator classes for find_if:

  class BroadcasterClassMatches {
  public:
    BroadcasterClassMatches(const ConstString &broadcaster_class)
        : m_broadcaster_class(broadcaster_class) {}

    ~BroadcasterClassMatches() = default;

    bool operator()(const event_listener_key input) const {
      return (input.first.GetBroadcasterClass() == m_broadcaster_class);
    }

  private:
    ConstString m_broadcaster_class;
  };

  class BroadcastEventSpecMatches {
  public:
    BroadcastEventSpecMatches(BroadcastEventSpec broadcaster_spec)
        : m_broadcaster_spec(broadcaster_spec) {}

    ~BroadcastEventSpecMatches() = default;

    bool operator()(const event_listener_key input) const {
      return (input.first.IsContainedIn(m_broadcaster_spec));
    }

  private:
    BroadcastEventSpec m_broadcaster_spec;
  };

  class ListenerMatchesAndSharedBits {
  public:
    explicit ListenerMatchesAndSharedBits(BroadcastEventSpec broadcaster_spec,
                                          const lldb::ListenerSP listener_sp)
        : m_broadcaster_spec(broadcaster_spec), m_listener_sp(listener_sp) {}

    ~ListenerMatchesAndSharedBits() = default;

    bool operator()(const event_listener_key input) const {
      return (input.first.GetBroadcasterClass() ==
                  m_broadcaster_spec.GetBroadcasterClass() &&
              (input.first.GetEventBits() &
               m_broadcaster_spec.GetEventBits()) != 0 &&
              input.second == m_listener_sp);
    }

  private:
    BroadcastEventSpec m_broadcaster_spec;
    const lldb::ListenerSP m_listener_sp;
  };

  class ListenerMatches {
  public:
    explicit ListenerMatches(const lldb::ListenerSP in_listener_sp)
        : m_listener_sp(in_listener_sp) {}

    ~ListenerMatches() = default;

    bool operator()(const event_listener_key input) const {
      if (input.second == m_listener_sp)
        return true;
      else
        return false;
    }

  private:
    const lldb::ListenerSP m_listener_sp;
  };

  class ListenerMatchesPointer {
  public:
    ListenerMatchesPointer(const Listener *in_listener)
        : m_listener(in_listener) {}

    ~ListenerMatchesPointer() = default;

    bool operator()(const event_listener_key input) const {
      if (input.second.get() == m_listener)
        return true;
      else
        return false;
    }

    bool operator()(const lldb::ListenerSP input) const {
      if (input.get() == m_listener)
        return true;
      else
        return false;
    }

  private:
    const Listener *m_listener;
  };
};

//----------------------------------------------------------------------
/// @class Broadcaster Broadcaster.h "lldb/Core/Broadcaster.h" An event
/// broadcasting class.
///
/// The Broadcaster class is designed to be subclassed by objects that wish to
/// vend events in a multi-threaded environment. Broadcaster objects can each
/// vend 32 events. Each event is represented by a bit in a 32 bit value and
/// these bits can be set:
///     @see Broadcaster::SetEventBits(uint32_t)
/// or cleared:
///     @see Broadcaster::ResetEventBits(uint32_t)
/// When an event gets set the Broadcaster object will notify the Listener
/// object that is listening for the event (if there is one).
///
/// Subclasses should provide broadcast bit definitions for any events they
/// vend, typically using an enumeration:
///     \code
///         class Foo : public Broadcaster
///         {
///         public:
///         //----------------------------------------------------------
///         // Broadcaster event bits definitions.
///         //----------------------------------------------------------
///         enum
///         {
///             eBroadcastBitOne   = (1 << 0),
///             eBroadcastBitTwo   = (1 << 1),
///             eBroadcastBitThree = (1 << 2),
///             ...
///         };
///     \endcode
//----------------------------------------------------------------------
class Broadcaster {
  friend class Listener;
  friend class Event;

public:
  //------------------------------------------------------------------
  /// Construct with a broadcaster with a name.
  ///
  /// @param[in] name
  ///     A NULL terminated C string that contains the name of the
  ///     broadcaster object.
  //------------------------------------------------------------------
  Broadcaster(lldb::BroadcasterManagerSP manager_sp, const char *name);

  //------------------------------------------------------------------
  /// Destructor.
  ///
  /// The destructor is virtual since this class gets subclassed.
  //------------------------------------------------------------------
  virtual ~Broadcaster();

  void CheckInWithManager();

  //------------------------------------------------------------------
  /// Broadcast an event which has no associated data.
  ///
  /// @param[in] event_type
  ///     The element from the enum defining this broadcaster's events
  ///     that is being broadcast.
  ///
  /// @param[in] event_data
  ///     User event data that will be owned by the lldb::Event that
  ///     is created internally.
  ///
  /// @param[in] unique
  ///     If true, then only add an event of this type if there isn't
  ///     one already in the queue.
  ///
  //------------------------------------------------------------------
  void BroadcastEvent(lldb::EventSP &event_sp) {
    m_broadcaster_sp->BroadcastEvent(event_sp);
  }

  void BroadcastEventIfUnique(lldb::EventSP &event_sp) {
    m_broadcaster_sp->BroadcastEventIfUnique(event_sp);
  }

  void BroadcastEvent(uint32_t event_type,
                      const lldb::EventDataSP &event_data_sp) {
    m_broadcaster_sp->BroadcastEvent(event_type, event_data_sp);
  }

  void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr) {
    m_broadcaster_sp->BroadcastEvent(event_type, event_data);
  }

  void BroadcastEventIfUnique(uint32_t event_type,
                              EventData *event_data = nullptr) {
    m_broadcaster_sp->BroadcastEventIfUnique(event_type, event_data);
  }

  void Clear() { m_broadcaster_sp->Clear(); }

  virtual void AddInitialEventsToListener(const lldb::ListenerSP &listener_sp,
                                          uint32_t requested_events);

  //------------------------------------------------------------------
  /// Listen for any events specified by \a event_mask.
  ///
  /// Only one listener can listen to each event bit in a given Broadcaster.
  /// Once a listener has acquired an event bit, no other broadcaster will
  /// have access to it until it is relinquished by the first listener that
  /// gets it. The actual event bits that get acquired by \a listener may be
  /// different from what is requested in \a event_mask, and to track this the
  /// actual event bits that are acquired get returned.
  ///
  /// @param[in] listener
  ///     The Listener object that wants to monitor the events that
  ///     get broadcast by this object.
  ///
  /// @param[in] event_mask
  ///     A bit mask that indicates which events the listener is
  ///     asking to monitor.
  ///
  /// @return
  ///     The actual event bits that were acquired by \a listener.
  //------------------------------------------------------------------
  uint32_t AddListener(const lldb::ListenerSP &listener_sp,
                       uint32_t event_mask) {
    return m_broadcaster_sp->AddListener(listener_sp, event_mask);
  }

  //------------------------------------------------------------------
  /// Get the NULL terminated C string name of this Broadcaster object.
  ///
  /// @return
  ///     The NULL terminated C string name of this Broadcaster.
  //------------------------------------------------------------------
  const ConstString &GetBroadcasterName() { return m_broadcaster_name; }

  //------------------------------------------------------------------
  /// Get the event name(s) for one or more event bits.
  ///
  /// @param[in] event_mask
  ///     A bit mask that indicates which events to get names for.
  ///
  /// @return
  ///     The NULL terminated C string name of this Broadcaster.
  //------------------------------------------------------------------
  bool GetEventNames(Stream &s, const uint32_t event_mask,
                     bool prefix_with_broadcaster_name) const {
    return m_broadcaster_sp->GetEventNames(s, event_mask,
                                           prefix_with_broadcaster_name);
  }

  //------------------------------------------------------------------
  /// Set the name for an event bit.
  ///
  /// @param[in] event_mask
  ///     A bit mask that indicates which events the listener is
  ///     asking to monitor.
  ///
  /// @return
  ///     The NULL terminated C string name of this Broadcaster.
  //------------------------------------------------------------------
  void SetEventName(uint32_t event_mask, const char *name) {
    m_broadcaster_sp->SetEventName(event_mask, name);
  }

  const char *GetEventName(uint32_t event_mask) const {
    return m_broadcaster_sp->GetEventName(event_mask);
  }

  bool EventTypeHasListeners(uint32_t event_type) {
    return m_broadcaster_sp->EventTypeHasListeners(event_type);
  }

  //------------------------------------------------------------------
  /// Removes a Listener from this broadcasters list and frees the event bits
  /// specified by \a event_mask that were previously acquired by \a listener
  /// (assuming \a listener was listening to this object) for other listener
  /// objects to use.
  ///
  /// @param[in] listener
  ///     A Listener object that previously called AddListener.
  ///
  /// @param[in] event_mask
  ///     The event bits \a listener wishes to relinquish.
  ///
  /// @return
  ///     \b True if the listener was listening to this broadcaster
  ///     and was removed, \b false otherwise.
  ///
  /// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t)
  //------------------------------------------------------------------
  bool RemoveListener(const lldb::ListenerSP &listener_sp,
                      uint32_t event_mask = UINT32_MAX) {
    return m_broadcaster_sp->RemoveListener(listener_sp, event_mask);
  }

  //------------------------------------------------------------------
  /// Provides a simple mechanism to temporarily redirect events from
  /// broadcaster.  When you call this function passing in a listener and
  /// event type mask, all events from the broadcaster matching the mask will
  /// now go to the hijacking listener. Only one hijack can occur at a time.
  /// If we need more than this we will have to implement a Listener stack.
  ///
  /// @param[in] listener
  ///     A Listener object.  You do not need to call StartListeningForEvents
  ///     for this broadcaster (that would fail anyway since the event bits
  ///     would most likely be taken by the listener(s) you are usurping.
  ///
  /// @param[in] event_mask
  ///     The event bits \a listener wishes to hijack.
  ///
  /// @return
  ///     \b True if the event mask could be hijacked, \b false otherwise.
  ///
  /// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t)
  //------------------------------------------------------------------
  bool HijackBroadcaster(const lldb::ListenerSP &listener_sp,
                         uint32_t event_mask = UINT32_MAX) {
    return m_broadcaster_sp->HijackBroadcaster(listener_sp, event_mask);
  }

  bool IsHijackedForEvent(uint32_t event_mask) {
    return m_broadcaster_sp->IsHijackedForEvent(event_mask);
  }

  //------------------------------------------------------------------
  /// Restore the state of the Broadcaster from a previous hijack attempt.
  ///
  //------------------------------------------------------------------
  void RestoreBroadcaster() { m_broadcaster_sp->RestoreBroadcaster(); }

  // This needs to be filled in if you are going to register the broadcaster
  // with the broadcaster manager and do broadcaster class matching.
  // FIXME: Probably should make a ManagedBroadcaster subclass with all the bits
  // needed to work
  // with the BroadcasterManager, so that it is clearer how to add one.
  virtual ConstString &GetBroadcasterClass() const;

  lldb::BroadcasterManagerSP GetManager();

protected:
  // BroadcasterImpl contains the actual Broadcaster implementation.  The
  // Broadcaster makes a BroadcasterImpl which lives as long as it does.  The
  // Listeners & the Events hold a weak pointer to the BroadcasterImpl, so that
  // they can survive if a Broadcaster they were listening to is destroyed w/o
  // their being able to unregister from it (which can happen if the
  // Broadcasters & Listeners are being destroyed on separate threads
  // simultaneously. The Broadcaster itself can't be shared out as a weak
  // pointer, because some things that are broadcasters (e.g. the Target and
  // the Process) are shared in their own right.
  //
  // For the most part, the Broadcaster functions dispatch to the
  // BroadcasterImpl, and are documented in the public Broadcaster API above.

  class BroadcasterImpl {
    friend class Listener;
    friend class Broadcaster;

  public:
    BroadcasterImpl(Broadcaster &broadcaster);

    ~BroadcasterImpl() = default;

    void BroadcastEvent(lldb::EventSP &event_sp);

    void BroadcastEventIfUnique(lldb::EventSP &event_sp);

    void BroadcastEvent(uint32_t event_type, EventData *event_data = nullptr);

    void BroadcastEvent(uint32_t event_type,
                        const lldb::EventDataSP &event_data_sp);

    void BroadcastEventIfUnique(uint32_t event_type,
                                EventData *event_data = nullptr);

    void Clear();

    uint32_t AddListener(const lldb::ListenerSP &listener_sp,
                         uint32_t event_mask);

    const char *GetBroadcasterName() const {
      return m_broadcaster.GetBroadcasterName().AsCString();
    }

    Broadcaster *GetBroadcaster();

    bool GetEventNames(Stream &s, const uint32_t event_mask,
                       bool prefix_with_broadcaster_name) const;

    void SetEventName(uint32_t event_mask, const char *name) {
      m_event_names[event_mask] = name;
    }

    const char *GetEventName(uint32_t event_mask) const {
      const auto pos = m_event_names.find(event_mask);
      if (pos != m_event_names.end())
        return pos->second.c_str();
      return nullptr;
    }

    bool EventTypeHasListeners(uint32_t event_type);

    bool RemoveListener(lldb_private::Listener *listener,
                        uint32_t event_mask = UINT32_MAX);

    bool RemoveListener(const lldb::ListenerSP &listener_sp,
                        uint32_t event_mask = UINT32_MAX);

    bool HijackBroadcaster(const lldb::ListenerSP &listener_sp,
                           uint32_t event_mask = UINT32_MAX);

    bool IsHijackedForEvent(uint32_t event_mask);

    void RestoreBroadcaster();

  protected:
    void PrivateBroadcastEvent(lldb::EventSP &event_sp, bool unique);

    const char *GetHijackingListenerName();

    //------------------------------------------------------------------
    //
    //------------------------------------------------------------------
    typedef llvm::SmallVector<std::pair<lldb::ListenerWP, uint32_t>, 4>
        collection;
    typedef std::map<uint32_t, std::string> event_names_map;

    llvm::SmallVector<std::pair<lldb::ListenerSP, uint32_t &>, 4>
    GetListeners();

    Broadcaster &m_broadcaster;    ///< The broadcaster that this implements
    event_names_map m_event_names; ///< Optionally define event names for
                                   ///readability and logging for each event bit
    collection m_listeners; ///< A list of Listener / event_mask pairs that are
                            ///listening to this broadcaster.
    std::recursive_mutex
        m_listeners_mutex; ///< A mutex that protects \a m_listeners.
    std::vector<lldb::ListenerSP> m_hijacking_listeners; // A simple mechanism
                                                         // to intercept events
                                                         // from a broadcaster
    std::vector<uint32_t> m_hijacking_masks; // At some point we may want to
                                             // have a stack or Listener
    // collections, but for now this is just for private hijacking.

  private:
    //------------------------------------------------------------------
    // For Broadcaster only
    //------------------------------------------------------------------
    DISALLOW_COPY_AND_ASSIGN(BroadcasterImpl);
  };

  typedef std::shared_ptr<BroadcasterImpl> BroadcasterImplSP;
  typedef std::weak_ptr<BroadcasterImpl> BroadcasterImplWP;

  BroadcasterImplSP GetBroadcasterImpl() { return m_broadcaster_sp; }

  const char *GetHijackingListenerName() {
    return m_broadcaster_sp->GetHijackingListenerName();
  }
  //------------------------------------------------------------------
  // Classes that inherit from Broadcaster can see and modify these
  //------------------------------------------------------------------

private:
  //------------------------------------------------------------------
  // For Broadcaster only
  //------------------------------------------------------------------
  BroadcasterImplSP m_broadcaster_sp;
  lldb::BroadcasterManagerSP m_manager_sp;
  const ConstString
      m_broadcaster_name; ///< The name of this broadcaster object.

  DISALLOW_COPY_AND_ASSIGN(Broadcaster);
};

} // namespace lldb_private

#endif // liblldb_Broadcaster_h_
