summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/Broadcaster.h47
-rw-r--r--lldb/include/lldb/Core/Event.h60
-rw-r--r--lldb/include/lldb/Core/Listener.h7
-rw-r--r--lldb/include/lldb/Target/Process.h1
-rw-r--r--lldb/include/lldb/lldb-forward.h2
-rw-r--r--lldb/source/Core/Broadcaster.cpp190
-rw-r--r--lldb/source/Core/Event.cpp33
-rw-r--r--lldb/source/Core/Listener.cpp113
-rw-r--r--lldb/source/Host/posix/HostThreadPosix.cpp18
-rw-r--r--lldb/source/Target/Process.cpp68
10 files changed, 323 insertions, 216 deletions
diff --git a/lldb/include/lldb/Core/Broadcaster.h b/lldb/include/lldb/Core/Broadcaster.h
index 8a61432ee8e..11dfe44be74 100644
--- a/lldb/include/lldb/Core/Broadcaster.h
+++ b/lldb/include/lldb/Core/Broadcaster.h
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <functional>
+#include <list>
#include <map>
#include <string>
#include <vector>
@@ -99,10 +101,10 @@ public:
~BroadcasterManager() = default;
uint32_t
- RegisterListenerForEvents (lldb::ListenerSP listener_sp, BroadcastEventSpec event_spec);
+ RegisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec);
bool
- UnregisterListenerForEvents (lldb::ListenerSP listener_sp, BroadcastEventSpec event_spec);
+ UnregisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec);
lldb::ListenerSP
GetListenerForEventSpec (BroadcastEventSpec event_spec) const;
@@ -111,7 +113,7 @@ public:
SignUpListenersForBroadcaster (Broadcaster &broadcaster);
void
- RemoveListener (lldb::ListenerSP listener_sp);
+ RemoveListener (const lldb::ListenerSP &listener_sp);
void
RemoveListener (Listener *listener);
@@ -170,8 +172,7 @@ private:
class ListenerMatchesAndSharedBits
{
public:
- ListenerMatchesAndSharedBits (BroadcastEventSpec broadcaster_spec,
- const lldb::ListenerSP listener_sp) :
+ explicit ListenerMatchesAndSharedBits (BroadcastEventSpec broadcaster_spec, const lldb::ListenerSP listener_sp) :
m_broadcaster_spec (broadcaster_spec),
m_listener_sp (listener_sp)
{
@@ -194,7 +195,7 @@ private:
class ListenerMatches
{
public:
- ListenerMatches (const lldb::ListenerSP in_listener_sp) :
+ explicit ListenerMatches (const lldb::ListenerSP in_listener_sp) :
m_listener_sp (in_listener_sp)
{
}
@@ -331,6 +332,12 @@ public:
}
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);
@@ -349,7 +356,7 @@ public:
}
virtual void
- AddInitialEventsToListener (lldb::ListenerSP listener_sp, uint32_t requested_events);
+ AddInitialEventsToListener (const lldb::ListenerSP &listener_sp, uint32_t requested_events);
//------------------------------------------------------------------
/// Listen for any events specified by \a event_mask.
@@ -374,7 +381,7 @@ public:
/// The actual event bits that were acquired by \a listener.
//------------------------------------------------------------------
uint32_t
- AddListener (lldb::ListenerSP listener_sp, uint32_t event_mask)
+ AddListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
{
return m_broadcaster_sp->AddListener(listener_sp, event_mask);
}
@@ -454,7 +461,7 @@ public:
/// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t)
//------------------------------------------------------------------
bool
- RemoveListener (lldb::ListenerSP listener_sp, uint32_t event_mask = UINT32_MAX)
+ RemoveListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask = UINT32_MAX)
{
return m_broadcaster_sp->RemoveListener(listener_sp, event_mask);
}
@@ -481,7 +488,7 @@ public:
/// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t)
//------------------------------------------------------------------
bool
- HijackBroadcaster (lldb::ListenerSP listener_sp, uint32_t event_mask = UINT32_MAX)
+ HijackBroadcaster (const lldb::ListenerSP &listener_sp, uint32_t event_mask = UINT32_MAX)
{
return m_broadcaster_sp->HijackBroadcaster(listener_sp, event_mask);
}
@@ -542,13 +549,16 @@ protected:
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 (lldb::ListenerSP listener_sp, uint32_t event_mask);
+ AddListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask);
const char *
GetBroadcasterName () const
@@ -581,10 +591,13 @@ protected:
EventTypeHasListeners (uint32_t event_type);
bool
- RemoveListener (lldb::ListenerSP listener_sp, uint32_t event_mask = UINT32_MAX);
+ 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 (lldb::ListenerSP listener_sp, uint32_t event_mask = UINT32_MAX);
+ HijackBroadcaster (const lldb::ListenerSP &listener_sp, uint32_t event_mask = UINT32_MAX);
bool
IsHijackedForEvent (uint32_t event_mask);
@@ -602,9 +615,13 @@ protected:
//------------------------------------------------------------------
//
//------------------------------------------------------------------
- typedef std::vector< std::pair<lldb::ListenerSP,uint32_t> > collection;
+ typedef std::list< std::pair<lldb::ListenerWP,uint32_t> > collection;
typedef std::map<uint32_t, std::string> event_names_map;
-
+
+ void
+ ListenerIterator (std::function <bool (const lldb::ListenerSP &listener_sp, uint32_t &event_mask)> const &callback);
+
+
Broadcaster &m_broadcaster; ///< The broadcsater 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.
diff --git a/lldb/include/lldb/Core/Event.h b/lldb/include/lldb/Core/Event.h
index 05f8d7e0e1f..1ae0fc83b27 100644
--- a/lldb/include/lldb/Core/Event.h
+++ b/lldb/include/lldb/Core/Event.h
@@ -114,6 +114,48 @@ private:
DISALLOW_COPY_AND_ASSIGN (EventDataBytes);
};
+class EventDataReceipt : public EventData
+{
+public:
+ EventDataReceipt() :
+ EventData(),
+ m_predicate(false)
+ {
+ }
+
+ ~EventDataReceipt() override
+ {
+ }
+
+ static const ConstString &
+ GetFlavorString ()
+ {
+ static ConstString g_flavor("Process::ProcessEventData");
+ return g_flavor;
+ }
+
+ const ConstString &
+ GetFlavor () const override
+ {
+ return GetFlavorString();
+ }
+
+ bool
+ WaitForEventReceived (const TimeValue *abstime = nullptr, bool *timed_out = nullptr)
+ {
+ return m_predicate.WaitForValueEqualTo(true, abstime, timed_out);
+ }
+
+private:
+ Predicate<bool> m_predicate;
+
+ void
+ DoOnRemoval (Event *event_ptr) override
+ {
+ m_predicate.SetValue(true, eBroadcastAlways);
+ }
+};
+
//----------------------------------------------------------------------
// lldb::Event
//----------------------------------------------------------------------
@@ -126,8 +168,12 @@ class Event
public:
Event(Broadcaster *broadcaster, uint32_t event_type, EventData *data = nullptr);
+ Event(Broadcaster *broadcaster, uint32_t event_type, const lldb::EventDataSP &event_data_sp);
+
Event(uint32_t event_type, EventData *data = nullptr);
+ Event(uint32_t event_type, const lldb::EventDataSP &event_data_sp);
+
~Event ();
void
@@ -136,19 +182,19 @@ public:
EventData *
GetData ()
{
- return m_data_ap.get();
+ return m_data_sp.get();
}
const EventData *
GetData () const
{
- return m_data_ap.get();
+ return m_data_sp.get();
}
void
SetData (EventData *new_data)
{
- m_data_ap.reset (new_data);
+ m_data_sp.reset (new_data);
}
uint32_t
@@ -186,7 +232,7 @@ public:
void
Clear()
{
- m_data_ap.reset();
+ m_data_sp.reset();
}
private:
@@ -206,9 +252,9 @@ private:
m_broadcaster_wp = broadcaster->GetBroadcasterImpl();
}
- Broadcaster::BroadcasterImplWP m_broadcaster_wp; // The broadcaster that sent this event
- uint32_t m_type; // The bit describing this event
- std::unique_ptr<EventData> m_data_ap; // User specific data for this event
+ Broadcaster::BroadcasterImplWP m_broadcaster_wp; // The broadcaster that sent this event
+ uint32_t m_type; // The bit describing this event
+ lldb::EventDataSP m_data_sp; // User specific data for this event
DISALLOW_COPY_AND_ASSIGN (Event);
diff --git a/lldb/include/lldb/Core/Listener.h b/lldb/include/lldb/Core/Listener.h
index 2e050c674ff..2e7f7f5269b 100644
--- a/lldb/include/lldb/Core/Listener.h
+++ b/lldb/include/lldb/Core/Listener.h
@@ -20,8 +20,8 @@
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Core/Broadcaster.h"
+#include "lldb/Host/Condition.h"
#include "lldb/Core/Event.h"
namespace lldb_private {
@@ -150,7 +150,8 @@ private:
typedef std::vector<lldb::BroadcasterManagerWP> broadcaster_manager_collection;
bool
- FindNextEventInternal(Broadcaster *broadcaster, // nullptr for any broadcaster
+ FindNextEventInternal(Mutex::Locker& lock,
+ Broadcaster *broadcaster, // nullptr for any broadcaster
const ConstString *sources, // nullptr for any event
uint32_t num_sources,
uint32_t event_type_mask,
@@ -177,7 +178,7 @@ private:
Mutex m_broadcasters_mutex; // Protects m_broadcasters
event_collection m_events;
Mutex m_events_mutex; // Protects m_broadcasters and m_events
- Predicate<bool> m_cond_wait;
+ Condition m_events_condition;
broadcaster_manager_collection m_broadcaster_managers;
void
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index d00d07b8337..3239dae629e 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -3344,7 +3344,6 @@ protected:
Broadcaster m_private_state_broadcaster; // This broadcaster feeds state changed events into the private state thread's listener.
Broadcaster m_private_state_control_broadcaster; // This is the control broadcaster, used to pause, resume & stop the private state thread.
lldb::ListenerSP m_private_state_listener_sp; // This is the listener for the private state thread.
- Predicate<bool> m_private_state_control_wait; /// This Predicate is used to signal that a control operation is complete.
HostThread m_private_state_thread; ///< Thread ID for the thread that watches internal state events
ProcessModID m_mod_id; ///< Tracks the state of the process over stops and other alterations.
uint32_t m_process_unique_id; ///< Each lldb_private::Process class that is created gets a unique integer ID that increments with each new instance
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index e9137b3b648..0bbd008496b 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -332,6 +332,7 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::DynamicLoader> DynamicLoaderSP;
typedef std::unique_ptr<lldb_private::DynamicLoader> DynamicLoaderUP;
typedef std::shared_ptr<lldb_private::Event> EventSP;
+ typedef std::shared_ptr<lldb_private::EventData> EventDataSP;
typedef std::shared_ptr<lldb_private::ExecutionContextRef> ExecutionContextRefSP;
typedef std::shared_ptr<lldb_private::ExpressionVariable> ExpressionVariableSP;
typedef std::shared_ptr<lldb_private::File> FileSP;
@@ -352,6 +353,7 @@ namespace lldb {
typedef std::unique_ptr<lldb_private::SystemRuntime> SystemRuntimeUP;
typedef std::shared_ptr<lldb_private::LineTable> LineTableSP;
typedef std::shared_ptr<lldb_private::Listener> ListenerSP;
+ typedef std::weak_ptr<lldb_private::Listener> ListenerWP;
typedef std::shared_ptr<lldb_private::LogChannel> LogChannelSP;
typedef std::shared_ptr<lldb_private::MemoryHistory> MemoryHistorySP;
typedef std::shared_ptr<lldb_private::Module> ModuleSP;
diff --git a/lldb/source/Core/Broadcaster.cpp b/lldb/source/Core/Broadcaster.cpp
index 3f125183d0b..ec91f8d8a7f 100644
--- a/lldb/source/Core/Broadcaster.cpp
+++ b/lldb/source/Core/Broadcaster.cpp
@@ -61,6 +61,33 @@ Broadcaster::CheckInWithManager ()
}
void
+Broadcaster::BroadcasterImpl::ListenerIterator (std::function <bool (const lldb::ListenerSP &listener_sp, uint32_t &event_mask)> const &callback)
+{
+ // Private iterator that should be used by everyone except BroadcasterImpl::RemoveListener().
+ // We have weak pointers to our listeners which means that at any point the listener can
+ // expire which means we will need to take it out of our list. To take care of this, we
+ // iterate and check that the weak pointer can be made into a valid shared pointer before
+ // we call the callback. If the weak pointer has expired, we remove it from our list.
+ collection::iterator pos = m_listeners.begin();
+ while (pos != m_listeners.end())
+ {
+ lldb::ListenerSP curr_listener_sp(pos->first.lock());
+ if (curr_listener_sp)
+ {
+ if (callback(curr_listener_sp, pos->second))
+ ++pos; // Keep iterating
+ else
+ return; // Done iterating
+ }
+ else
+ {
+ // The listener has been expired. Remove this entry.
+ pos = m_listeners.erase(pos);
+ }
+ }
+}
+
+void
Broadcaster::BroadcasterImpl::Clear()
{
Mutex::Locker listeners_locker(m_listeners_mutex);
@@ -68,10 +95,11 @@ Broadcaster::BroadcasterImpl::Clear()
// Make sure the listener forgets about this broadcaster. We do
// this in the broadcaster in case the broadcaster object initiates
// the removal.
-
- collection::iterator pos, end = m_listeners.end();
- for (pos = m_listeners.begin(); pos != end; ++pos)
- pos->first->BroadcasterWillDestruct (&m_broadcaster);
+
+ ListenerIterator([this](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
+ curr_listener_sp->BroadcasterWillDestruct (&m_broadcaster);
+ return true; // Keep iterating
+ });
m_listeners.clear();
}
@@ -114,57 +142,45 @@ Broadcaster::BroadcasterImpl::GetEventNames (Stream &s, uint32_t event_mask, boo
}
void
-Broadcaster::AddInitialEventsToListener (lldb::ListenerSP listener_sp, uint32_t requested_events)
+Broadcaster::AddInitialEventsToListener (const lldb::ListenerSP &listener_sp, uint32_t requested_events)
{
}
uint32_t
-Broadcaster::BroadcasterImpl::AddListener (lldb::ListenerSP listener_sp, uint32_t event_mask)
+Broadcaster::BroadcasterImpl::AddListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
{
if (!listener_sp)
return 0;
Mutex::Locker locker(m_listeners_mutex);
- collection::iterator pos, end = m_listeners.end();
- collection::iterator existing_pos = end;
// See if we already have this listener, and if so, update its mask
- uint32_t taken_event_types = 0;
- for (pos = m_listeners.begin(); pos != end; ++pos)
- {
- if (pos->first == listener_sp)
- existing_pos = pos;
- // For now don't descriminate on who gets what
- // FIXME: Implement "unique listener for this bit" mask
- // taken_event_types |= pos->second;
- }
- // Each event bit in a Broadcaster object can only be used
- // by one listener
- uint32_t available_event_types = ~taken_event_types & event_mask;
+ bool handled = false;
- if (available_event_types)
- {
- // If we didn't find our listener, add it
- if (existing_pos == end)
+ ListenerIterator([this, &listener_sp, &handled, event_mask](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
+ if (curr_listener_sp == listener_sp)
{
- // Grant a new listener the available event bits
- m_listeners.push_back(std::make_pair(listener_sp, available_event_types));
- }
- else
- {
- // Grant the existing listener the available event bits
- existing_pos->second |= available_event_types;
+ handled = true;
+ curr_event_mask |= event_mask;
+ m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask);
+ return false; // Stop iterating
}
+ return true; // Keep iterating
+ });
+
+ if (!handled)
+ {
+ // Grant a new listener the available event bits
+ m_listeners.push_back(std::make_pair(lldb::ListenerWP(listener_sp), event_mask));
// Individual broadcasters decide whether they have outstanding data when a
// listener attaches, and insert it into the listener with this method.
-
- m_broadcaster.AddInitialEventsToListener (listener_sp, available_event_types);
+ m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask);
}
// Return the event bits that were granted to the listener
- return available_event_types;
+ return event_mask;
}
bool
@@ -178,36 +194,63 @@ Broadcaster::BroadcasterImpl::EventTypeHasListeners (uint32_t event_type)
if (m_listeners.empty())
return false;
- collection::iterator pos, end = m_listeners.end();
- for (pos = m_listeners.begin(); pos != end; ++pos)
- {
- if (pos->second & event_type)
- return true;
- }
- return false;
+ bool result = false;
+ ListenerIterator([this, event_type, &result](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
+
+ if (curr_event_mask & event_type)
+ {
+ result = true;
+ return false; // Stop iterating
+ }
+ else
+ {
+ return true; // Keep iterating
+ }
+ });
+ return result;
}
bool
-Broadcaster::BroadcasterImpl::RemoveListener (lldb::ListenerSP listener_sp, uint32_t event_mask)
+Broadcaster::BroadcasterImpl::RemoveListener (lldb_private::Listener *listener, uint32_t event_mask)
{
- Mutex::Locker locker(m_listeners_mutex);
- collection::iterator pos, end = m_listeners.end();
- // See if we already have this listener, and if so, update its mask
- for (pos = m_listeners.begin(); pos != end; ++pos)
+ if (listener)
{
- if (pos->first == listener_sp)
+ Mutex::Locker locker(m_listeners_mutex);
+ collection::iterator pos = m_listeners.begin();
+ // See if we already have this listener, and if so, update its mask
+ while (pos != m_listeners.end())
{
- // Relinquish all event bits in "event_mask"
- pos->second &= ~event_mask;
- // If all bits have been relinquished then remove this listener
- if (pos->second == 0)
- m_listeners.erase (pos);
- return true;
+ lldb::ListenerSP curr_listener_sp(pos->first.lock());
+ if (curr_listener_sp)
+ {
+ if (curr_listener_sp.get() == listener)
+ {
+ // Relinquish all event bits in "event_mask"
+ pos->second &= ~event_mask;
+ // If all bits have been relinquished then remove this listener
+ if (pos->second == 0)
+ m_listeners.erase (pos);
+ return true;
+ }
+ ++pos;
+ }
+ else
+ {
+ // The listener has been destroyed since we couldn't turn the std::weak_ptr
+ // into a valid shared pointer, so we can remove it.
+ pos = m_listeners.erase (pos);
+ }
}
}
return false;
}
+bool
+Broadcaster::BroadcasterImpl::RemoveListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
+{
+ return RemoveListener (listener_sp.get(), event_mask);
+}
+
void
Broadcaster::BroadcasterImpl::BroadcastEvent (EventSP &event_sp)
{
@@ -232,7 +275,7 @@ Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool uni
const uint32_t event_type = event_sp->GetType();
- Mutex::Locker event_types_locker(m_listeners_mutex);
+ Mutex::Locker locker(m_listeners_mutex);
ListenerSP hijacking_listener_sp;
@@ -263,20 +306,16 @@ Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool uni
}
else
{
- collection::iterator pos, end = m_listeners.end();
- // Iterate through all listener/mask pairs
- for (pos = m_listeners.begin(); pos != end; ++pos)
- {
- // If the listener's mask matches any bits that we just set, then
- // put the new event on its event queue.
- if (event_type & pos->second)
+ ListenerIterator([this, unique, event_type, &event_sp](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool {
+
+ if (event_type & curr_event_mask)
{
- if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type))
- continue;
- pos->first->AddEvent (event_sp);
+ if (!unique || curr_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type) == nullptr)
+ curr_listener_sp->AddEvent (event_sp);
}
- }
+ return true; // Keep iterating
+ });
}
}
@@ -288,6 +327,13 @@ Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, EventData *ev
}
void
+Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, const lldb::EventDataSP &event_data_sp)
+{
+ EventSP event_sp (new Event (event_type, event_data_sp));
+ PrivateBroadcastEvent (event_sp, false);
+}
+
+void
Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
{
EventSP event_sp (new Event (event_type, event_data));
@@ -295,9 +341,9 @@ Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, Event
}
bool
-Broadcaster::BroadcasterImpl::HijackBroadcaster (ListenerSP listener_sp, uint32_t event_mask)
+Broadcaster::BroadcasterImpl::HijackBroadcaster (const lldb::ListenerSP &listener_sp, uint32_t event_mask)
{
- Mutex::Locker event_types_locker(m_listeners_mutex);
+ Mutex::Locker locker(m_listeners_mutex);
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
if (log)
@@ -312,7 +358,7 @@ Broadcaster::BroadcasterImpl::HijackBroadcaster (ListenerSP listener_sp, uint32_
bool
Broadcaster::BroadcasterImpl::IsHijackedForEvent (uint32_t event_mask)
{
- Mutex::Locker event_types_locker(m_listeners_mutex);
+ Mutex::Locker locker(m_listeners_mutex);
if (!m_hijacking_listeners.empty())
return (event_mask & m_hijacking_masks.back()) != 0;
@@ -335,7 +381,7 @@ Broadcaster::BroadcasterImpl::GetHijackingListenerName()
void
Broadcaster::BroadcasterImpl::RestoreBroadcaster ()
{
- Mutex::Locker event_types_locker(m_listeners_mutex);
+ Mutex::Locker locker(m_listeners_mutex);
if (!m_hijacking_listeners.empty())
{
@@ -391,7 +437,7 @@ BroadcasterManager::MakeBroadcasterManager()
}
uint32_t
-BroadcasterManager::RegisterListenerForEvents (ListenerSP listener_sp, BroadcastEventSpec event_spec)
+BroadcasterManager::RegisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec)
{
Mutex::Locker locker(m_manager_mutex);
@@ -415,7 +461,7 @@ BroadcasterManager::RegisterListenerForEvents (ListenerSP listener_sp, Broadcast
}
bool
-BroadcasterManager::UnregisterListenerForEvents (ListenerSP listener_sp, BroadcastEventSpec event_spec)
+BroadcasterManager::UnregisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec)
{
Mutex::Locker locker(m_manager_mutex);
bool removed_some = false;
@@ -495,7 +541,7 @@ BroadcasterManager::RemoveListener(Listener *listener)
}
void
-BroadcasterManager::RemoveListener (ListenerSP listener_sp)
+BroadcasterManager::RemoveListener (const lldb::ListenerSP &listener_sp)
{
Mutex::Locker locker(m_manager_mutex);
ListenerMatches predicate (listener_sp);
diff --git a/lldb/source/Core/Event.cpp b/lldb/source/Core/Event.cpp
index a8063bfb34d..6b07e4d9198 100644
--- a/lldb/source/Core/Event.cpp
+++ b/lldb/source/Core/Event.cpp
@@ -26,15 +26,30 @@ using namespace lldb;
using namespace lldb_private;
Event::Event (Broadcaster *broadcaster, uint32_t event_type, EventData *data) :
- m_broadcaster_wp (broadcaster->GetBroadcasterImpl()),
- m_type (event_type),
- m_data_ap (data)
+ m_broadcaster_wp(broadcaster->GetBroadcasterImpl()),
+ m_type(event_type),
+ m_data_sp(data)
+{
+}
+
+Event::Event (Broadcaster *broadcaster, uint32_t event_type, const EventDataSP &event_data_sp) :
+ m_broadcaster_wp(broadcaster->GetBroadcasterImpl()),
+ m_type(event_type),
+ m_data_sp(event_data_sp)
{
}
Event::Event(uint32_t event_type, EventData *data) :
- m_type (event_type),
- m_data_ap (data)
+ m_broadcaster_wp(),
+ m_type(event_type),
+ m_data_sp(data)
+{
+}
+
+Event::Event(uint32_t event_type, const EventDataSP &event_data_sp) :
+ m_broadcaster_wp(),
+ m_type(event_type),
+ m_data_sp(event_data_sp)
{
}
@@ -69,10 +84,10 @@ Event::Dump (Stream *s) const
s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ",
static_cast<const void*>(this), m_type);
- if (m_data_ap)
+ if (m_data_sp)
{
s->PutChar('{');
- m_data_ap->Dump (s);
+ m_data_sp->Dump (s);
s->PutChar('}');
}
else
@@ -82,8 +97,8 @@ Event::Dump (Stream *s) const
void
Event::DoOnRemoval ()
{
- if (m_data_ap)
- m_data_ap->DoOnRemoval (this);
+ if (m_data_sp)
+ m_data_sp->DoOnRemoval (this);
}
EventData::EventData() = default;
diff --git a/lldb/source/Core/Listener.cpp b/lldb/source/Core/Listener.cpp
index e8cf39e0676..32ca1f0cebb 100644
--- a/lldb/source/Core/Listener.cpp
+++ b/lldb/source/Core/Listener.cpp
@@ -45,8 +45,7 @@ Listener::Listener(const char *name) :
m_broadcasters(),
m_broadcasters_mutex (Mutex::eMutexTypeRecursive),
m_events (),
- m_events_mutex (Mutex::eMutexTypeRecursive),
- m_cond_wait()
+ m_events_mutex (Mutex::eMutexTypeNormal)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
if (log != nullptr)
@@ -74,11 +73,10 @@ Listener::Clear()
{
Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock());
if (broadcaster_sp)
- broadcaster_sp->RemoveListener (this->shared_from_this(), pos->second.event_mask);
+ broadcaster_sp->RemoveListener (this, pos->second.event_mask);
}
m_broadcasters.clear();
- m_cond_wait.SetValue (false, eBroadcastNever);
- m_broadcasters.clear();
+
Mutex::Locker event_locker(m_events_mutex);
m_events.clear();
size_t num_managers = m_broadcaster_managers.size();
@@ -193,9 +191,6 @@ Listener::BroadcasterWillDestruct (Broadcaster *broadcaster)
else
++pos;
}
-
- if (m_events.empty())
- m_cond_wait.SetValue (false, eBroadcastNever);
}
}
@@ -221,12 +216,9 @@ Listener::AddEvent (EventSP &event_sp)
static_cast<void*>(this), m_name.c_str(),
static_cast<void*>(event_sp.get()));
- // Scope for "locker"
- {
- Mutex::Locker locker(m_events_mutex);
- m_events.push_back (event_sp);
- }
- m_cond_wait.SetValue (true, eBroadcastAlways);
+ Mutex::Locker locker(m_events_mutex);
+ m_events.push_back (event_sp);
+ m_events_condition.Broadcast();
}
class EventBroadcasterMatches
@@ -293,6 +285,7 @@ private:
bool
Listener::FindNextEventInternal
(
+ Mutex::Locker& lock,
Broadcaster *broadcaster, // nullptr for any broadcaster
const ConstString *broadcaster_names, // nullptr for any event
uint32_t num_broadcaster_names,
@@ -300,10 +293,10 @@ Listener::FindNextEventInternal
EventSP &event_sp,
bool remove)
{
+ // NOTE: callers of this function must lock m_events_mutex using a Mutex::Locker
+ // and pass the locker as the first argument. m_events_mutex is no longer recursive.
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
- Mutex::Locker lock(m_events_mutex);
-
if (m_events.empty())
return false;
@@ -333,20 +326,12 @@ Listener::FindNextEventInternal
if (remove)
{
m_events.erase(pos);
-
- if (m_events.empty())
- m_cond_wait.SetValue (false, eBroadcastNever);
- }
-
- // Unlock the event queue here. We've removed this event and are about to return
- // it so it should be okay to get the next event off the queue here - and it might
- // be useful to do that in the "DoOnRemoval".
- lock.Unlock();
-
- // Don't call DoOnRemoval if you aren't removing the event...
- if (remove)
+ // Unlock the event queue here. We've removed this event and are about to return
+ // it so it should be okay to get the next event off the queue here - and it might
+ // be useful to do that in the "DoOnRemoval".
+ lock.Unlock();
event_sp->DoOnRemoval();
-
+ }
return true;
}
@@ -357,8 +342,9 @@ Listener::FindNextEventInternal
Event *
Listener::PeekAtNextEvent ()
{
+ Mutex::Locker lock(m_events_mutex);
EventSP event_sp;
- if (FindNextEventInternal(nullptr, nullptr, 0, 0, event_sp, false))
+ if (FindNextEventInternal(lock, nullptr, nullptr, 0, 0, event_sp, false))
return event_sp.get();
return nullptr;
}
@@ -366,8 +352,9 @@ Listener::PeekAtNextEvent ()
Event *
Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster)
{
+ Mutex::Locker lock(m_events_mutex);
EventSP event_sp;
- if (FindNextEventInternal(broadcaster, nullptr, 0, 0, event_sp, false))
+ if (FindNextEventInternal(lock, broadcaster, nullptr, 0, 0, event_sp, false))
return event_sp.get();
return nullptr;
}
@@ -375,8 +362,9 @@ Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster)
Event *
Listener::PeekAtNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask)
{
+ Mutex::Locker lock(m_events_mutex);
EventSP event_sp;
- if (FindNextEventInternal(broadcaster, nullptr, 0, event_type_mask, event_sp, false))
+ if (FindNextEventInternal(lock, broadcaster, nullptr, 0, event_type_mask, event_sp, false))
return event_sp.get();
return nullptr;
}
@@ -388,7 +376,8 @@ Listener::GetNextEventInternal(Broadcaster *broadcaster, // nullptr
uint32_t event_type_mask,
EventSP &event_sp)
{
- return FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true);
+ Mutex::Locker lock(m_events_mutex);
+ return FindNextEventInternal (lock, broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true);
}
bool
@@ -418,52 +407,40 @@ Listener::WaitForEventsInternal(const TimeValue *timeout,
EventSP &event_sp)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS));
- bool timed_out = false;
-
if (log != nullptr)
log->Printf ("%p Listener::WaitForEventsInternal (timeout = { %p }) for %s",
static_cast<void*>(this), static_cast<const void*>(timeout),
m_name.c_str());
+ Mutex::Locker lock(m_events_mutex);
+
while (true)
{
- // Note, we don't want to lock the m_events_mutex in the call to GetNextEventInternal, since the DoOnRemoval
- // code might require that new events be serviced. For instance, the Breakpoint Command's
- if (GetNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp))
- return true;
-
- {
- // Reset condition value to false, so we can wait for new events to be
- // added that might meet our current filter
- // But first poll for any new event that might satisfy our condition, and if so consume it,
- // otherwise wait.
-
- Mutex::Locker event_locker(m_events_mutex);
- const bool remove = false;
- if (FindNextEventInternal (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, remove))
- continue;
- else
- m_cond_wait.SetValue (false, eBroadcastNever);
- }
-
- if (m_cond_wait.WaitForValueEqualTo (true, timeout, &timed_out))
- continue;
-
- else if (timed_out)
+ if (FindNextEventInternal (lock, broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true))
{
- log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
- if (log != nullptr)
- log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s",
- static_cast<void*>(this), m_name.c_str());
- break;
+ return true;
}
else
{
- log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
- if (log != nullptr)
- log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s",
- static_cast<void*>(this), m_name.c_str());
- break;
+ bool timed_out = false;
+ if (m_events_condition.Wait(m_events_mutex, timeout, &timed_out) != 0)
+ {
+ if (timed_out)
+ {
+ log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
+ if (log != nullptr)
+ log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s",
+ static_cast<void*>(this), m_name.c_str());
+ }
+ else
+ {
+ log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS);
+ if (log != nullptr)
+ log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s",
+ static_cast<void*>(this), m_name.c_str());
+ }
+ return false;
+ }
}
}
diff --git a/lldb/source/Host/posix/HostThreadPosix.cpp b/lldb/source/Host/posix/HostThreadPosix.cpp
index 9c489243193..3ac83ac07b1 100644
--- a/lldb/source/Host/posix/HostThreadPosix.cpp
+++ b/lldb/source/Host/posix/HostThreadPosix.cpp
@@ -53,13 +53,16 @@ Error
HostThreadPosix::Cancel()
{
Error error;
+ if (IsJoinable())
+ {
#ifndef __ANDROID__
- int err = ::pthread_cancel(m_thread);
- error.SetError(err, eErrorTypePOSIX);
+ assert(false && "someone is calling HostThread::Cancel()");
+ int err = ::pthread_cancel(m_thread);
+ error.SetError(err, eErrorTypePOSIX);
#else
- error.SetErrorString("HostThreadPosix::Cancel() not supported on Android");
+ error.SetErrorString("HostThreadPosix::Cancel() not supported on Android");
#endif
-
+ }
return error;
}
@@ -67,8 +70,11 @@ Error
HostThreadPosix::Detach()
{
Error error;
- int err = ::pthread_detach(m_thread);
- error.SetError(err, eErrorTypePOSIX);
+ if (IsJoinable())
+ {
+ int err = ::pthread_detach(m_thread);
+ error.SetError(err, eErrorTypePOSIX);
+ }
Reset();
return error;
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index f156d086d28..a880782663a 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -726,7 +726,6 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, const UnixSig
m_private_state_broadcaster(nullptr, "lldb.process.internal_state_broadcaster"),
m_private_state_control_broadcaster(nullptr, "lldb.process.internal_state_control_broadcaster"),
m_private_state_listener_sp (Listener::MakeListener("lldb.process.internal_state_listener")),
- m_private_state_control_wait(),
m_mod_id (),
m_process_unique_id(0),
m_thread_index_id (0),
@@ -4109,44 +4108,46 @@ Process::ControlPrivateStateThread (uint32_t signal)
// Signal the private state thread. First we should copy this is case the
// thread starts exiting since the private state thread will NULL this out
// when it exits
- HostThread private_state_thread(m_private_state_thread);
- if (private_state_thread.IsJoinable())
{
- TimeValue timeout_time;
- bool timed_out;
-
- m_private_state_control_broadcaster.BroadcastEvent(signal, nullptr);
-
- timeout_time = TimeValue::Now();
- timeout_time.OffsetWithSeconds(2);
- if (log)
- log->Printf ("Sending control event of type: %d.", signal);
- m_private_state_control_wait.WaitForValueEqualTo (true, &timeout_time, &timed_out);
- m_private_state_control_wait.SetValue (false, eBroadcastNever);
-
- if (signal == eBroadcastInternalStateControlStop)
+ HostThread private_state_thread(m_private_state_thread);
+ if (private_state_thread.IsJoinable())
{
- if (timed_out)
+ if (log)
+ log->Printf ("Sending control event of type: %d.", signal);
+ // Send the control event and wait for the receipt or for the private state
+ // thread to exit
+ std::shared_ptr<EventDataReceipt> event_receipt_sp(new EventDataReceipt());
+ m_private_state_control_broadcaster.BroadcastEvent(signal, event_receipt_sp);
+
+ bool receipt_received = false;
+ while (!receipt_received)
{
- Error error = private_state_thread.Cancel();
- if (log)
- log->Printf ("Timed out responding to the control event, cancel got error: \"%s\".", error.AsCString());
+ bool timed_out = false;
+ TimeValue timeout_time;
+ timeout_time = TimeValue::Now();
+ timeout_time.OffsetWithSeconds(2);
+ // Check for a receipt for 2 seconds and then check if the private state
+ // thread is still around.
+ receipt_received = event_receipt_sp->WaitForEventReceived (&timeout_time, &timed_out);
+ if (!receipt_received)
+ {
+ // Check if the private state thread is still around. If it isn't then we are done waiting
+ if (!m_private_state_thread.IsJoinable())
+ break; // Private state thread exited, we are done
+ }
}
- else
+
+ if (signal == eBroadcastInternalStateControlStop)
{
- if (log)
- log->Printf ("The control event killed the private state thread without having to cancel.");
+ thread_result_t result = NULL;
+ private_state_thread.Join(&result);
}
-
- thread_result_t result = NULL;
- private_state_thread.Join(&result);
- m_private_state_thread.Reset();
}
- }
- else
- {
- if (log)
- log->Printf ("Private state thread already dead, no need to signal it to stop.");
+ else
+ {
+ if (log)
+ log->Printf ("Private state thread already dead, no need to signal it to stop.");
+ }
}
}
@@ -4311,7 +4312,6 @@ thread_result_t
Process::RunPrivateStateThread (bool is_secondary_thread)
{
bool control_only = true;
- m_private_state_control_wait.SetValue (false, eBroadcastNever);
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
if (log)
@@ -4346,7 +4346,6 @@ Process::RunPrivateStateThread (bool is_secondary_thread)
break;
}
- m_private_state_control_wait.SetValue (true, eBroadcastAlways);
continue;
}
else if (event_sp->GetType() == eBroadcastBitInterrupt)
@@ -4442,7 +4441,6 @@ Process::RunPrivateStateThread (bool is_secondary_thread)
// try to change it on the way out.
if (!is_secondary_thread)
m_public_run_lock.SetStopped();
- m_private_state_control_wait.SetValue (true, eBroadcastAlways);
m_private_state_thread.Reset();
return NULL;
}
OpenPOWER on IntegriCloud