Add a general mechanism to wait on the debugger for Broadcasters of a given class/event bit set.

Use this to allow the lldb Driver to emit notifications for breakpoint modifications.
<rdar://problem/10619974>

llvm-svn: 150665
This commit is contained in:
Jim Ingham 2012-02-16 06:50:00 +00:00
parent 924f9a671d
commit 4bddaeb5ab
41 changed files with 763 additions and 28 deletions

View File

@ -50,6 +50,9 @@ public:
lldb::SBBroadcaster
GetBroadcaster ();
static const char *
GetBroadcasterClass ();
bool
HasCommands ();

View File

@ -39,6 +39,8 @@ public:
lldb::SBBroadcaster
GetBroadcaster ();
static const char *GetBroadcasterClass();
lldb::ConnectionStatus
AdoptFileDesriptor (int fd, bool owns_fd);

View File

@ -277,6 +277,7 @@ private:
friend class SBProcess;
friend class SBSourceManager;
friend class SBTarget;
friend class SBListener;
lldb::SBTarget
FindTargetWithLLDBProcess (const lldb::ProcessSP &processSP);

View File

@ -47,6 +47,9 @@ public:
lldb::SBBroadcaster
GetBroadcaster () const;
const char *
GetBroadcasterClass () const;
bool
BroadcasterMatchesPtr (const lldb::SBBroadcaster *broadcaster);

View File

@ -37,6 +37,16 @@ public:
bool
IsValid () const;
uint32_t
StartListeningForEventClass (SBDebugger &debugger,
const char *broadcaster_class,
uint32_t event_mask);
bool
StopListeningForEventClass (SBDebugger &debugger,
const char *broadcaster_class,
uint32_t event_mask);
uint32_t
StartListeningForEvents (const lldb::SBBroadcaster& broadcaster,
uint32_t event_mask);

View File

@ -42,6 +42,9 @@ public:
~SBProcess();
static const char *
GetBroadcasterClassName ();
void
Clear ();
@ -178,6 +181,9 @@ public:
lldb::SBBroadcaster
GetBroadcaster () const;
static const char *
GetBroadcasterClass ();
bool
GetDescription (lldb::SBStream &description);

View File

@ -52,6 +52,9 @@ public:
bool
IsValid() const;
static const char *
GetBroadcasterClassName ();
lldb::SBProcess
GetProcess ();

View File

@ -20,10 +20,191 @@
// Project includes
#include "lldb/lldb-private.h"
//#include "lldb/Core/Flags.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Listener.h"
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() {}
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;
const BroadcastEventSpec &operator= (const BroadcastEventSpec &rhs);
private:
ConstString m_broadcaster_class;
uint32_t m_event_bits;
};
class BroadcasterManager
{
public:
BroadcasterManager ();
~BroadcasterManager () {};
uint32_t
RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec);
bool
UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec);
Listener *
GetListenerForEventSpec (BroadcastEventSpec event_spec) const;
void
SignUpListenersForBroadcaster (Broadcaster &broadcaster);
void
RemoveListener (Listener &Listener);
protected:
void Clear();
private:
typedef std::pair<BroadcastEventSpec, Listener *> event_listener_key;
typedef std::map<BroadcastEventSpec, Listener *> collection;
typedef std::set<Listener *> listener_collection;
collection m_event_map;
listener_collection m_listeners;
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 () {}
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 () {}
bool operator() (const event_listener_key input) const
{
return (input.first.IsContainedIn (m_broadcaster_spec));
}
private:
BroadcastEventSpec m_broadcaster_spec;
};
class ListenerMatchesAndSharedBits
{
public:
ListenerMatchesAndSharedBits (BroadcastEventSpec broadcaster_spec,
const Listener &listener) :
m_broadcaster_spec (broadcaster_spec),
m_listener (&listener)
{
}
~ListenerMatchesAndSharedBits () {}
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);
}
private:
BroadcastEventSpec m_broadcaster_spec;
const Listener *m_listener;
};
class ListenerMatches
{
public:
ListenerMatches (const Listener &in_listener) :
m_listener (&in_listener)
{
}
~ListenerMatches() {}
bool operator () (const event_listener_key input) const
{
if (input.second == m_listener)
return true;
else
return false;
}
private:
const Listener *m_listener;
};
};
//----------------------------------------------------------------------
/// @class Broadcaster Broadcaster.h "lldb/Core/Broadcaster.h"
/// @brief An event broadcasting class.
@ -66,7 +247,7 @@ public:
/// A NULL terminated C string that contains the name of the
/// broadcaster object.
//------------------------------------------------------------------
Broadcaster (const char *name);
Broadcaster (BroadcasterManager *manager, const char *name);
//------------------------------------------------------------------
/// Destructor.
@ -76,6 +257,9 @@ public:
virtual
~Broadcaster();
void
CheckInWithManager ();
//------------------------------------------------------------------
/// Broadcast an event which has no associated data.
///
@ -245,6 +429,10 @@ public:
//------------------------------------------------------------------
void
RestoreBroadcaster ();
virtual ConstString &GetBroadcasterClass() const;
BroadcasterManager *GetManager();
protected:
@ -266,6 +454,7 @@ protected:
std::vector<Listener *> 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.
BroadcasterManager *m_manager;
private:
//------------------------------------------------------------------

View File

@ -332,6 +332,13 @@ public:
m_close_on_eof = b;
}
static ConstString &GetStaticBroadcasterClass ();
virtual ConstString &GetBroadcasterClass() const
{
return GetStaticBroadcasterClass();
}
private:
//------------------------------------------------------------------
// For Communication only

View File

@ -18,6 +18,7 @@
#include <stack>
#include "lldb/lldb-public.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/FormatManager.h"
#include "lldb/Core/InputReaderStack.h"
@ -253,7 +254,8 @@ private:
class Debugger :
public std::tr1::enable_shared_from_this<Debugger>,
public UserID,
public DebuggerInstanceSettings
public DebuggerInstanceSettings,
public BroadcasterManager
{
friend class SourceManager; // For GetSourceFileCache.

View File

@ -16,6 +16,7 @@
#include <map>
#include <set>
#include <string>
#include <vector>
// Other libraries and framework includes
@ -32,6 +33,7 @@ public:
typedef bool (*HandleBroadcastCallback) (lldb::EventSP &event_sp, void *baton);
friend class Broadcaster;
friend class BroadcasterManager;
//------------------------------------------------------------------
// Constructors and Destructors
@ -53,9 +55,17 @@ public:
}
uint32_t
StartListeningForEvents (Broadcaster* broadcaster,
StartListeningForEventSpec (BroadcasterManager &manager,
const BroadcastEventSpec &event_spec);
bool
StopListeningForEventSpec (BroadcasterManager &manager,
const BroadcastEventSpec &event_spec);
uint32_t
StartListeningForEvents (Broadcaster* broadcaster,
uint32_t event_mask);
uint32_t
StartListeningForEvents (Broadcaster* broadcaster,
uint32_t event_mask,
@ -128,6 +138,7 @@ protected:
typedef std::multimap<Broadcaster*, BroadcasterInfo> broadcaster_collection;
typedef std::list<lldb::EventSP> event_collection;
typedef std::vector<BroadcasterManager *> broadcaster_manager_collection;
bool
FindNextEventInternal (Broadcaster *broadcaster, // NULL for any broadcaster
@ -158,9 +169,14 @@ protected:
event_collection m_events;
Mutex m_events_mutex; // Protects m_broadcasters and m_events
Predicate<bool> m_cond_wait;
broadcaster_manager_collection m_broadcaster_managers;
void
BroadcasterWillDestruct (Broadcaster *);
void
BroadcasterManagerWillDestruct (BroadcasterManager *manager);
private:
// broadcaster_collection::iterator

View File

@ -55,6 +55,15 @@ public:
eCommandTypesAllThem = 0xFFFF // all commands
};
// These two functions fill out the Broadcaster interface:
static ConstString &GetStaticBroadcasterClass ();
virtual ConstString &GetBroadcasterClass() const
{
return GetStaticBroadcasterClass();
}
void
SourceInitFile (bool in_cwd,
CommandReturnObject &result);
@ -437,7 +446,7 @@ public:
{
return "*** Some of your variables have more members than the debugger will show by default. To show all of them, you can either use the --show-all-children option to %s or raise the limit by changing the target.max-children-count setting.\n";
}
protected:
friend class Debugger;
@ -468,6 +477,7 @@ private:
char m_repeat_char;
bool m_batch_command_mode;
ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated children and whether the user has been told
};

View File

@ -1296,7 +1296,16 @@ public:
eBroadcastInternalStateControlPause = (1<<1),
eBroadcastInternalStateControlResume = (1<<2)
};
// These two functions fill out the Broadcaster interface:
static ConstString &GetStaticBroadcasterClass ();
virtual ConstString &GetBroadcasterClass() const
{
return GetStaticBroadcasterClass();
}
//------------------------------------------------------------------
/// A notification structure that can be used by clients to listen
/// for changes in a process's lifetime.

View File

@ -278,6 +278,52 @@ public:
eBroadcastBitModulesUnloaded = (1 << 2)
};
// These two functions fill out the Broadcaster interface:
static ConstString &GetStaticBroadcasterClass ();
virtual ConstString &GetBroadcasterClass() const
{
return GetStaticBroadcasterClass();
}
// This event data class is for use by the TargetList to broadcast new target notifications.
class TargetEventData : public EventData
{
public:
static const ConstString &
GetFlavorString ();
virtual const ConstString &
GetFlavor () const;
TargetEventData (const lldb::TargetSP &new_target_sp);
lldb::TargetSP &
GetTarget()
{
return m_target_sp;
}
virtual
~TargetEventData();
virtual void
Dump (Stream *s) const;
static const lldb::TargetSP
GetTargetFromEvent (const lldb::EventSP &event_sp);
static const TargetEventData *
GetEventDataFromEvent (const Event *event_sp);
private:
lldb::TargetSP m_target_sp;
DISALLOW_COPY_AND_ASSIGN (TargetEventData);
};
static void
SettingsInitialize ();

View File

@ -34,7 +34,7 @@ private:
///
/// @see static TargetList& lldb_private::Debugger::GetTargetList().
//------------------------------------------------------------------
TargetList();
TargetList(Debugger &debugger);
public:
@ -47,7 +47,16 @@ public:
};
~TargetList();
// These two functions fill out the Broadcaster interface:
static ConstString &GetStaticBroadcasterClass ();
virtual ConstString &GetBroadcasterClass() const
{
return GetStaticBroadcasterClass();
}
virtual ~TargetList();
//------------------------------------------------------------------
/// Create a new Target.

View File

@ -41,7 +41,9 @@ class BreakpointOptions;
class BreakpointResolver;
class BreakpointSite;
class BreakpointSiteList;
class BroadcastEventSpec;
class Broadcaster;
class BroadcasterManager;
class CPPLanguageRuntime;
class ClangASTContext;
class ClangASTImporter;

View File

@ -87,6 +87,9 @@ public:
lldb::SBBroadcaster
GetBroadcaster ();
static const char *
GetBroadcasterClass ();
bool
HasCommands ();

View File

@ -34,6 +34,8 @@ public:
lldb::SBBroadcaster
GetBroadcaster ();
static const char *GetBroadcasterClass();
lldb::ConnectionStatus
AdoptFileDesriptor (int fd, bool owns_fd);

View File

@ -134,6 +134,9 @@ public:
lldb::SBBroadcaster
GetBroadcaster () const;
const char *
GetBroadcasterClass () const;
bool
BroadcasterMatchesRef (const lldb::SBBroadcaster &broadcaster);

View File

@ -34,6 +34,16 @@ public:
bool
IsValid () const;
uint32_t
StartListeningForEventClass (SBDebugger &debugger,
const char *broadcaster_class,
uint32_t event_mask);
uint32_t
StopListeningForEventClass (SBDebugger &debugger,
const char *broadcaster_class,
uint32_t event_mask);
uint32_t
StartListeningForEvents (const lldb::SBBroadcaster& broadcaster,
uint32_t event_mask);

View File

@ -52,6 +52,9 @@ public:
~SBProcess();
static const char *
GetBroadcasterClassName ();
void
Clear ();

View File

@ -72,6 +72,9 @@ public:
//------------------------------------------------------------------
~SBTarget();
static const char *
GetBroadcasterClassName ();
bool
IsValid() const;

View File

@ -25,7 +25,7 @@ SBBroadcaster::SBBroadcaster () :
}
SBBroadcaster::SBBroadcaster (const char *name) :
m_opaque_sp (new Broadcaster (name)),
m_opaque_sp (new Broadcaster (NULL, name)),
m_opaque_ptr (NULL)
{
m_opaque_ptr = m_opaque_sp.get();

View File

@ -292,6 +292,12 @@ SBCommandInterpreter::GetBroadcaster ()
return broadcaster;
}
const char *
SBCommandInterpreter::GetBroadcasterClass ()
{
return Communication::GetStaticBroadcasterClass().AsCString();
}
const char *
SBCommandInterpreter::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type)
{

View File

@ -255,6 +255,11 @@ SBCommunication::GetBroadcaster ()
return broadcaster;
}
const char *
SBCommunication::GetBroadcasterClass ()
{
return Communication::GetStaticBroadcasterClass().AsCString();
}
//
//void

View File

@ -109,6 +109,16 @@ SBEvent::GetBroadcaster () const
return broadcaster;
}
const char *
SBEvent::GetBroadcasterClass () const
{
const Event *lldb_event = get();
if (lldb_event)
return lldb_event->GetBroadcaster()->GetBroadcasterClass().AsCString();
else
return "unknown class";
}
bool
SBEvent::BroadcasterMatchesPtr (const SBBroadcaster *broadcaster)
{

View File

@ -9,9 +9,11 @@
#include "lldb/API/SBListener.h"
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Listener.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
@ -90,6 +92,40 @@ SBListener::Clear ()
m_opaque_ptr->Clear ();
}
uint32_t
SBListener::StartListeningForEventClass (SBDebugger &debugger,
const char *broadcaster_class,
uint32_t event_mask)
{
if (m_opaque_ptr)
{
Debugger *lldb_debugger = debugger.get();
if (!lldb_debugger)
return 0;
BroadcastEventSpec event_spec (ConstString (broadcaster_class), event_mask);
return m_opaque_ptr->StartListeningForEventSpec (*lldb_debugger, event_spec);
}
else
return 0;
}
bool
SBListener::StopListeningForEventClass (SBDebugger &debugger,
const char *broadcaster_class,
uint32_t event_mask)
{
if (m_opaque_ptr)
{
Debugger *lldb_debugger = debugger.get();
if (!lldb_debugger)
return false;
BroadcastEventSpec event_spec (ConstString (broadcaster_class), event_mask);
return m_opaque_ptr->StopListeningForEventSpec (*lldb_debugger, event_spec);
}
else
return false;
}
uint32_t
SBListener::StartListeningForEvents (const SBBroadcaster& broadcaster, uint32_t event_mask)
{

View File

@ -74,6 +74,12 @@ SBProcess::~SBProcess()
{
}
const char *
SBProcess::GetBroadcasterClassName ()
{
return Process::GetStaticBroadcasterClass().AsCString();
}
lldb::ProcessSP
SBProcess::GetSP() const
{
@ -743,7 +749,7 @@ SBProcess::GetProcessFromEvent (const SBEvent &event)
bool
SBProcess::EventIsProcessEvent (const SBEvent &event)
{
return Process::ProcessEventData::GetEventDataFromEvent(event.get()) != NULL;
return strcmp (event.GetBroadcasterClass(), SBProcess::GetBroadcasterClass()) == 0;
}
SBBroadcaster
@ -762,6 +768,12 @@ SBProcess::GetBroadcaster () const
return broadcaster;
}
const char *
SBProcess::GetBroadcasterClass ()
{
return Process::GetStaticBroadcasterClass().AsCString();
}
size_t
SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error)
{

View File

@ -87,6 +87,12 @@ SBTarget::~SBTarget()
{
}
const char *
SBTarget::GetBroadcasterClassName ()
{
return Target::GetStaticBroadcasterClass().AsCString();
}
bool
SBTarget::IsValid () const
{
@ -1235,7 +1241,6 @@ SBTarget::GetBroadcaster () const
return broadcaster;
}
bool
SBTarget::GetDescription (SBStream &description, lldb::DescriptionLevel description_level)
{

View File

@ -30,7 +30,7 @@ using namespace lldb_private;
//-------------------------------------------------------------------------
// CommandObjectProcessLaunch
//-------------------------------------------------------------------------
#pragma mark CommandObjectProjectLaunch
#pragma mark CommandObjectProcessLaunch
class CommandObjectProcessLaunch : public CommandObject
{
public:

View File

@ -21,12 +21,13 @@
using namespace lldb;
using namespace lldb_private;
Broadcaster::Broadcaster (const char *name) :
Broadcaster::Broadcaster (BroadcasterManager *manager, const char *name) :
m_broadcaster_name (name),
m_listeners (),
m_listeners_mutex (Mutex::eMutexTypeRecursive),
m_hijacking_listeners(),
m_hijacking_masks()
m_hijacking_masks(),
m_manager (manager)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
@ -43,6 +44,15 @@ Broadcaster::~Broadcaster()
Clear();
}
void
Broadcaster::CheckInWithManager ()
{
if (m_manager != NULL)
{
m_manager->SignUpListenersForBroadcaster(*this);
}
}
void
Broadcaster::Clear()
{
@ -297,3 +307,173 @@ Broadcaster::RestoreBroadcaster ()
m_hijacking_masks.pop_back();
}
ConstString &
Broadcaster::GetBroadcasterClass() const
{
static ConstString class_name ("lldb.anonymous");
return class_name;
}
BroadcastEventSpec::BroadcastEventSpec (const BroadcastEventSpec &rhs) :
m_broadcaster_class (rhs.m_broadcaster_class),
m_event_bits (rhs.m_event_bits)
{
}
bool
BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const
{
if (GetBroadcasterClass() == rhs.GetBroadcasterClass())
{
return GetEventBits() < rhs.GetEventBits();
}
else
{
return GetBroadcasterClass() < rhs.GetBroadcasterClass();
}
}
const BroadcastEventSpec &
BroadcastEventSpec::operator= (const BroadcastEventSpec &rhs)
{
m_broadcaster_class = rhs.m_broadcaster_class;
m_event_bits = rhs.m_event_bits;
return *this;
}
BroadcasterManager::BroadcasterManager() :
m_manager_mutex(Mutex::eMutexTypeRecursive)
{
}
uint32_t
BroadcasterManager::RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
{
Mutex::Locker locker(m_manager_mutex);
collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
uint32_t available_bits = event_spec.GetEventBits();
while (iter != end_iter
&& (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter)
{
available_bits &= ~((*iter).first.GetEventBits());
iter++;
}
if (available_bits != 0)
{
m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), &listener));
m_listeners.insert(&listener);
}
return available_bits;
}
bool
BroadcasterManager::UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
{
Mutex::Locker locker(m_manager_mutex);
bool removed_some = false;
if (m_listeners.erase(&listener) == 0)
return false;
ListenerMatchesAndSharedBits predicate (event_spec, listener);
std::vector<BroadcastEventSpec> to_be_readded;
uint32_t event_bits_to_remove = event_spec.GetEventBits();
// Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add:
while (1)
{
collection::iterator iter, end_iter = m_event_map.end();
iter = find_if (m_event_map.begin(), end_iter, predicate);
if (iter == end_iter)
{
break;
}
else
{
uint32_t iter_event_bits = (*iter).first.GetEventBits();
removed_some = true;
if (event_bits_to_remove != iter_event_bits)
{
uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits));
}
m_event_map.erase (iter);
}
}
// Okay now add back the bits that weren't completely removed:
for (size_t i = 0; i < to_be_readded.size(); i++)
{
m_event_map.insert (event_listener_key (to_be_readded[i], &listener));
}
return removed_some;
}
Listener *
BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const
{
Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex)));
collection::const_iterator iter, end_iter = m_event_map.end();
iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec));
if (iter != end_iter)
return (*iter).second;
else
return NULL;
}
void
BroadcasterManager::RemoveListener (Listener &listener)
{
Mutex::Locker locker(m_manager_mutex);
ListenerMatches predicate (listener);
if (m_listeners.erase (&listener) == 0)
return;
while (1)
{
collection::iterator iter, end_iter = m_event_map.end();
iter = find_if (m_event_map.begin(), end_iter, predicate);
if (iter == end_iter)
break;
else
m_event_map.erase(iter);
}
}
void
BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster)
{
Mutex::Locker locker(m_manager_mutex);
collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
while (iter != end_iter
&& (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter)
{
(*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits());
iter++;
}
}
void
BroadcasterManager::Clear ()
{
Mutex::Locker locker(m_manager_mutex);
listener_collection::iterator end_iter = m_listeners.end();
for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++)
(*iter)->BroadcasterManagerWillDestruct(this);
m_listeners.clear();
m_event_map.clear();
}

View File

@ -23,11 +23,18 @@
using namespace lldb;
using namespace lldb_private;
ConstString &
Communication::GetStaticBroadcasterClass ()
{
static ConstString class_name ("lldb.communication");
return class_name;
}
//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
Communication::Communication(const char *name) :
Broadcaster (name),
Broadcaster (NULL, name),
m_connection_sp (),
m_read_thread (LLDB_INVALID_HOST_THREAD),
m_read_thread_enabled (false),
@ -48,6 +55,8 @@ Communication::Communication(const char *name) :
SetEventName (eBroadcastBitReadThreadDidExit, "read thread did exit");
SetEventName (eBroadcastBitReadThreadShouldExit, "read thread should exit");
SetEventName (eBroadcastBitPacketAvailable, "packet available");
CheckInWithManager();
}
//----------------------------------------------------------------------

View File

@ -333,7 +333,7 @@ Debugger::Debugger () :
m_input_file (),
m_output_file (),
m_error_file (),
m_target_list (),
m_target_list (*this),
m_platform_list (),
m_listener ("lldb.Debugger"),
m_source_manager(*this),
@ -374,6 +374,7 @@ Debugger::Clear()
target_sp->Destroy();
}
}
BroadcasterManager::Clear ();
DisconnectInput();
}

View File

@ -40,6 +40,13 @@ Listener::Listener(const char *name) :
Listener::~Listener()
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
Mutex::Locker locker (m_broadcasters_mutex);
size_t num_managers = m_broadcaster_managers.size();
for (int i = 0; i < num_managers; i++)
m_broadcaster_managers[i]->RemoveListener(*this);
if (log)
log->Printf ("%p Listener::~Listener('%s')", this, m_name.c_str());
Clear();
@ -163,6 +170,16 @@ Listener::BroadcasterWillDestruct (Broadcaster *broadcaster)
}
}
void
Listener::BroadcasterManagerWillDestruct (BroadcasterManager *manager)
{
// Just need to remove this broadcast manager from the list of managers:
broadcaster_manager_collection::iterator iter, end_iter = m_broadcaster_managers.end();
iter = find(m_broadcaster_managers.begin(), end_iter, manager);
if (iter != end_iter)
m_broadcaster_managers.erase (iter);
}
void
Listener::AddEvent (EventSP &event_sp)
{
@ -483,3 +500,27 @@ Listener::HandleBroadcastEvent (EventSP &event_sp)
}
return num_handled;
}
uint32_t
Listener::StartListeningForEventSpec (BroadcasterManager &manager,
const BroadcastEventSpec &event_spec)
{
Mutex::Locker locker(m_broadcasters_mutex);
uint32_t bits_acquired = manager.RegisterListenerForEvents(*this, event_spec);
if (bits_acquired)
m_broadcaster_managers.push_back(&manager);
return bits_acquired;
}
bool
Listener::StopListeningForEventSpec (BroadcasterManager &manager,
const BroadcastEventSpec &event_spec)
{
Mutex::Locker locker(m_broadcasters_mutex);
return manager.UnregisterListenerForEvents (*this, event_spec);
}

View File

@ -59,13 +59,20 @@
using namespace lldb;
using namespace lldb_private;
ConstString &
CommandInterpreter::GetStaticBroadcasterClass ()
{
static ConstString class_name ("lldb.commandInterpreter");
return class_name;
}
CommandInterpreter::CommandInterpreter
(
Debugger &debugger,
ScriptLanguage script_language,
bool synchronous_execution
) :
Broadcaster ("lldb.command-interpreter"),
Broadcaster (&debugger, "lldb.command-interpreter"),
m_debugger (debugger),
m_synchronous_execution (synchronous_execution),
m_skip_lldbinit_files (false),
@ -86,6 +93,8 @@ CommandInterpreter::CommandInterpreter
SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
SetEventName (eBroadcastBitQuitCommandReceived, "quit");
CheckInWithManager ();
}
void

View File

@ -89,7 +89,7 @@ ProcessKDP::CanDebug(Target &target, bool plugin_specified_by_name)
ProcessKDP::ProcessKDP(Target& target, Listener &listener) :
Process (target, listener),
m_comm("lldb.process.kdp-remote.communication"),
m_async_broadcaster ("lldb.process.kdp-remote.async-broadcaster"),
m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"),
m_async_thread (LLDB_INVALID_HOST_THREAD)
{
// m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");

View File

@ -146,7 +146,7 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_last_stop_packet (),
m_last_stop_packet_mutex (Mutex::eMutexTypeNormal),
m_register_info (),
m_async_broadcaster ("lldb.process.gdb-remote.async-broadcaster"),
m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"),
m_async_thread (LLDB_INVALID_HOST_THREAD),
m_continue_c_tids (),
m_continue_C_tids (),

View File

@ -743,19 +743,25 @@ Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener
return process_sp;
}
ConstString &
Process::GetStaticBroadcasterClass ()
{
static ConstString class_name ("lldb.process");
return class_name;
}
//----------------------------------------------------------------------
// Process constructor
//----------------------------------------------------------------------
Process::Process(Target &target, Listener &listener) :
UserID (LLDB_INVALID_PROCESS_ID),
Broadcaster ("lldb.process"),
Broadcaster (&(target.GetDebugger()), "lldb.process"),
ProcessInstanceSettings (GetSettingsController()),
m_target (target),
m_public_state (eStateUnloaded),
m_private_state (eStateUnloaded),
m_private_state_broadcaster ("lldb.process.internal_state_broadcaster"),
m_private_state_control_broadcaster ("lldb.process.internal_state_control_broadcaster"),
m_private_state_broadcaster (NULL, "lldb.process.internal_state_broadcaster"),
m_private_state_control_broadcaster (NULL, "lldb.process.internal_state_control_broadcaster"),
m_private_state_listener ("lldb.process.internal_state_listener"),
m_private_state_control_wait(),
m_private_state_thread (LLDB_INVALID_HOST_THREAD),
@ -783,6 +789,8 @@ Process::Process(Target &target, Listener &listener) :
m_can_jit(eCanJITDontKnow)
{
UpdateInstanceName();
CheckInWithManager ();
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)

View File

@ -41,11 +41,18 @@
using namespace lldb;
using namespace lldb_private;
ConstString &
Target::GetStaticBroadcasterClass ()
{
static ConstString class_name ("lldb.target");
return class_name;
}
//----------------------------------------------------------------------
// Target constructor
//----------------------------------------------------------------------
Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::PlatformSP &platform_sp) :
Broadcaster ("lldb.target"),
Broadcaster (&debugger, "lldb.target"),
ExecutionContextScope (),
TargetInstanceSettings (GetSettingsController()),
m_debugger (debugger),
@ -72,6 +79,8 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch, const lldb::Plat
SetEventName (eBroadcastBitBreakpointChanged, "breakpoint-changed");
SetEventName (eBroadcastBitModulesLoaded, "modules-loaded");
SetEventName (eBroadcastBitModulesUnloaded, "modules-unloaded");
CheckInWithManager();
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log)
@ -2773,3 +2782,58 @@ Target::SettingsController::instance_settings_table[] =
{ TSC_DISABLE_STDIO , eSetVarTypeBoolean, "false" , NULL, false, false, "Disable stdin/stdout for process (e.g. for a GUI application)" },
{ NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL }
};
const ConstString &
Target::TargetEventData::GetFlavorString ()
{
static ConstString g_flavor ("Target::TargetEventData");
return g_flavor;
}
const ConstString &
Target::TargetEventData::GetFlavor () const
{
return TargetEventData::GetFlavorString ();
}
Target::TargetEventData::TargetEventData (const lldb::TargetSP &new_target_sp) :
EventData(),
m_target_sp (new_target_sp)
{
}
Target::TargetEventData::~TargetEventData()
{
}
void
Target::TargetEventData::Dump (Stream *s) const
{
}
const TargetSP
Target::TargetEventData::GetTargetFromEvent (const lldb::EventSP &event_sp)
{
TargetSP target_sp;
const TargetEventData *data = GetEventDataFromEvent (event_sp.get());
if (data)
target_sp = data->m_target_sp;
return target_sp;
}
const Target::TargetEventData *
Target::TargetEventData::GetEventDataFromEvent (const Event *event_ptr)
{
if (event_ptr)
{
const EventData *event_data = event_ptr->GetData();
if (event_data && event_data->GetFlavor() == TargetEventData::GetFlavorString())
return static_cast <const TargetEventData *> (event_ptr->GetData());
}
return NULL;
}

View File

@ -25,16 +25,23 @@
using namespace lldb;
using namespace lldb_private;
ConstString &
TargetList::GetStaticBroadcasterClass ()
{
static ConstString class_name ("lldb.targetList");
return class_name;
}
//----------------------------------------------------------------------
// TargetList constructor
//----------------------------------------------------------------------
TargetList::TargetList() :
Broadcaster("TargetList"),
TargetList::TargetList(Debugger &debugger) :
Broadcaster(&debugger, "TargetList"),
m_target_list(),
m_target_list_mutex (Mutex::eMutexTypeRecursive),
m_selected_target_idx (0)
{
CheckInWithManager();
}
//----------------------------------------------------------------------
@ -176,9 +183,6 @@ TargetList::CreateTarget
Mutex::Locker locker(m_target_list_mutex);
m_selected_target_idx = m_target_list.size();
m_target_list.push_back(target_sp);
// Now sign the Debugger up to listen to target events for this target:
debugger.GetListener().StartListeningForEvents(target_sp.get(), Target::eBroadcastBitBreakpointChanged);
}
return error;

View File

@ -1233,6 +1233,9 @@ Driver::MainLoop ()
m_debugger.PushInputReader (m_editline_reader);
SBListener listener(m_debugger.GetListener());
listener.StartListeningForEventClass(m_debugger,
SBTarget::GetBroadcasterClassName(),
SBTarget::eBroadcastBitBreakpointChanged);
if (listener.IsValid())
{