Home | History | Annotate | Download | only in Core
      1 //===-- Broadcaster.cpp -----------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/Core/Broadcaster.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 // Project includes
     16 #include "lldb/Core/Log.h"
     17 #include "lldb/Core/Event.h"
     18 #include "lldb/Core/StreamString.h"
     19 #include "lldb/lldb-private-log.h"
     20 
     21 using namespace lldb;
     22 using namespace lldb_private;
     23 
     24 Broadcaster::Broadcaster (BroadcasterManager *manager, const char *name) :
     25     m_broadcaster_name (name),
     26     m_listeners (),
     27     m_listeners_mutex (Mutex::eMutexTypeRecursive),
     28     m_hijacking_listeners(),
     29     m_hijacking_masks(),
     30     m_manager (manager)
     31 {
     32     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
     33     if (log)
     34         log->Printf ("%p Broadcaster::Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
     35 
     36 }
     37 
     38 Broadcaster::~Broadcaster()
     39 {
     40     Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
     41     if (log)
     42         log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")", this, m_broadcaster_name.AsCString());
     43 
     44     Clear();
     45 }
     46 
     47 void
     48 Broadcaster::CheckInWithManager ()
     49 {
     50     if (m_manager != NULL)
     51     {
     52         m_manager->SignUpListenersForBroadcaster(*this);
     53     }
     54 }
     55 
     56 void
     57 Broadcaster::Clear()
     58 {
     59     Mutex::Locker listeners_locker(m_listeners_mutex);
     60 
     61     // Make sure the listener forgets about this broadcaster. We do
     62     // this in the broadcaster in case the broadcaster object initiates
     63     // the removal.
     64 
     65     collection::iterator pos, end = m_listeners.end();
     66     for (pos = m_listeners.begin(); pos != end; ++pos)
     67         pos->first->BroadcasterWillDestruct (this);
     68 
     69     m_listeners.clear();
     70 }
     71 const ConstString &
     72 Broadcaster::GetBroadcasterName ()
     73 {
     74     return m_broadcaster_name;
     75 }
     76 
     77 bool
     78 Broadcaster::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const
     79 {
     80     uint32_t num_names_added = 0;
     81     if (event_mask && !m_event_names.empty())
     82     {
     83         event_names_map::const_iterator end = m_event_names.end();
     84         for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1)
     85         {
     86             if (mask & 1)
     87             {
     88                 event_names_map::const_iterator pos = m_event_names.find(bit);
     89                 if (pos != end)
     90                 {
     91                     if (num_names_added > 0)
     92                         s.PutCString(", ");
     93 
     94                     if (prefix_with_broadcaster_name)
     95                     {
     96                         s.PutCString (m_broadcaster_name.GetCString());
     97                         s.PutChar('.');
     98                     }
     99                     s.PutCString(pos->second.c_str());
    100                     ++num_names_added;
    101                 }
    102             }
    103         }
    104     }
    105     return num_names_added > 0;
    106 }
    107 
    108 void
    109 Broadcaster::AddInitialEventsToListener (Listener *listener, uint32_t requested_events)
    110 {
    111 
    112 }
    113 
    114 uint32_t
    115 Broadcaster::AddListener (Listener* listener, uint32_t event_mask)
    116 {
    117     if (listener == NULL)
    118         return 0;
    119 
    120     Mutex::Locker locker(m_listeners_mutex);
    121     collection::iterator pos, end = m_listeners.end();
    122 
    123     collection::iterator existing_pos = end;
    124     // See if we already have this listener, and if so, update its mask
    125     uint32_t taken_event_types = 0;
    126     for (pos = m_listeners.begin(); pos != end; ++pos)
    127     {
    128         if (pos->first == listener)
    129             existing_pos = pos;
    130     // For now don't descriminate on who gets what
    131     // FIXME: Implement "unique listener for this bit" mask
    132     //  taken_event_types |= pos->second;
    133     }
    134 
    135     // Each event bit in a Broadcaster object can only be used
    136     // by one listener
    137     uint32_t available_event_types = ~taken_event_types & event_mask;
    138 
    139     if (available_event_types)
    140     {
    141         // If we didn't find our listener, add it
    142         if (existing_pos == end)
    143         {
    144             // Grant a new listener the available event bits
    145             m_listeners.push_back(std::make_pair(listener, available_event_types));
    146         }
    147         else
    148         {
    149             // Grant the existing listener the available event bits
    150             existing_pos->second |= available_event_types;
    151         }
    152 
    153         // Individual broadcasters decide whether they have outstanding data when a
    154         // listener attaches, and insert it into the listener with this method.
    155 
    156         AddInitialEventsToListener (listener, available_event_types);
    157     }
    158 
    159     // Return the event bits that were granted to the listener
    160     return available_event_types;
    161 }
    162 
    163 bool
    164 Broadcaster::EventTypeHasListeners (uint32_t event_type)
    165 {
    166     Mutex::Locker locker (m_listeners_mutex);
    167 
    168     if (m_hijacking_listeners.size() > 0 && event_type & m_hijacking_masks.back())
    169         return true;
    170 
    171     if (m_listeners.empty())
    172         return false;
    173 
    174     collection::iterator pos, end = m_listeners.end();
    175     for (pos = m_listeners.begin(); pos != end; ++pos)
    176     {
    177         if (pos->second & event_type)
    178             return true;
    179     }
    180     return false;
    181 }
    182 
    183 bool
    184 Broadcaster::RemoveListener (Listener* listener, uint32_t event_mask)
    185 {
    186     Mutex::Locker locker(m_listeners_mutex);
    187     collection::iterator pos, end = m_listeners.end();
    188     // See if we already have this listener, and if so, update its mask
    189     for (pos = m_listeners.begin(); pos != end; ++pos)
    190     {
    191         if (pos->first == listener)
    192         {
    193             // Relinquish all event bits in "event_mask"
    194             pos->second &= ~event_mask;
    195             // If all bits have been relinquished then remove this listener
    196             if (pos->second == 0)
    197                 m_listeners.erase (pos);
    198             return true;
    199         }
    200     }
    201     return false;
    202 }
    203 
    204 void
    205 Broadcaster::BroadcastEvent (EventSP &event_sp)
    206 {
    207     return PrivateBroadcastEvent (event_sp, false);
    208 }
    209 
    210 void
    211 Broadcaster::BroadcastEventIfUnique (EventSP &event_sp)
    212 {
    213     return PrivateBroadcastEvent (event_sp, true);
    214 }
    215 
    216 void
    217 Broadcaster::PrivateBroadcastEvent (EventSP &event_sp, bool unique)
    218 {
    219     // Can't add a NULL event...
    220     if (event_sp.get() == NULL)
    221         return;
    222 
    223     // Update the broadcaster on this event
    224     event_sp->SetBroadcaster (this);
    225 
    226     const uint32_t event_type = event_sp->GetType();
    227 
    228     Mutex::Locker event_types_locker(m_listeners_mutex);
    229 
    230     Listener *hijacking_listener = NULL;
    231     if (!m_hijacking_listeners.empty())
    232     {
    233         assert (!m_hijacking_masks.empty());
    234         hijacking_listener = m_hijacking_listeners.back();
    235         if ((event_type & m_hijacking_masks.back()) == 0)
    236             hijacking_listener = NULL;
    237     }
    238 
    239     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
    240     if (log)
    241     {
    242         StreamString event_description;
    243         event_sp->Dump  (&event_description);
    244         log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p",
    245                      this,
    246                      m_broadcaster_name.AsCString(""),
    247                      event_description.GetData(),
    248                      unique,
    249                      hijacking_listener);
    250     }
    251 
    252     if (hijacking_listener)
    253     {
    254         if (unique && hijacking_listener->PeekAtNextEventForBroadcasterWithType (this, event_type))
    255             return;
    256         hijacking_listener->AddEvent (event_sp);
    257     }
    258     else
    259     {
    260         collection::iterator pos, end = m_listeners.end();
    261 
    262 
    263         // Iterate through all listener/mask pairs
    264         for (pos = m_listeners.begin(); pos != end; ++pos)
    265         {
    266             // If the listener's mask matches any bits that we just set, then
    267             // put the new event on its event queue.
    268             if (event_type & pos->second)
    269             {
    270                 if (unique && pos->first->PeekAtNextEventForBroadcasterWithType (this, event_type))
    271                     continue;
    272                 pos->first->AddEvent (event_sp);
    273             }
    274         }
    275     }
    276 }
    277 
    278 void
    279 Broadcaster::BroadcastEvent (uint32_t event_type, EventData *event_data)
    280 {
    281     EventSP event_sp (new Event (event_type, event_data));
    282     PrivateBroadcastEvent (event_sp, false);
    283 }
    284 
    285 void
    286 Broadcaster::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data)
    287 {
    288     EventSP event_sp (new Event (event_type, event_data));
    289     PrivateBroadcastEvent (event_sp, true);
    290 }
    291 
    292 bool
    293 Broadcaster::HijackBroadcaster (Listener *listener, uint32_t event_mask)
    294 {
    295     Mutex::Locker event_types_locker(m_listeners_mutex);
    296 
    297     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
    298     if (log)
    299     {
    300         log->Printf ("%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)",
    301                      this,
    302                      m_broadcaster_name.AsCString(""),
    303                      listener->m_name.c_str(),
    304                      listener);
    305     }
    306     m_hijacking_listeners.push_back(listener);
    307     m_hijacking_masks.push_back(event_mask);
    308     return true;
    309 }
    310 
    311 void
    312 Broadcaster::RestoreBroadcaster ()
    313 {
    314     Mutex::Locker event_types_locker(m_listeners_mutex);
    315 
    316     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS));
    317     if (log)
    318     {
    319         Listener *listener = m_hijacking_listeners.back();
    320         log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)",
    321                      this,
    322                      m_broadcaster_name.AsCString(""),
    323                      listener->m_name.c_str(),
    324                      listener);
    325     }
    326     m_hijacking_listeners.pop_back();
    327     m_hijacking_masks.pop_back();
    328 }
    329 
    330 ConstString &
    331 Broadcaster::GetBroadcasterClass() const
    332 {
    333     static ConstString class_name ("lldb.anonymous");
    334     return class_name;
    335 }
    336 
    337 BroadcastEventSpec::BroadcastEventSpec (const BroadcastEventSpec &rhs) :
    338     m_broadcaster_class (rhs.m_broadcaster_class),
    339     m_event_bits (rhs.m_event_bits)
    340 {
    341 }
    342 
    343 bool
    344 BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const
    345 {
    346     if (GetBroadcasterClass() == rhs.GetBroadcasterClass())
    347     {
    348         return GetEventBits() < rhs.GetEventBits();
    349     }
    350     else
    351     {
    352         return GetBroadcasterClass() < rhs.GetBroadcasterClass();
    353     }
    354 }
    355 
    356 const BroadcastEventSpec &
    357 BroadcastEventSpec::operator= (const BroadcastEventSpec &rhs)
    358 {
    359     m_broadcaster_class = rhs.m_broadcaster_class;
    360     m_event_bits = rhs.m_event_bits;
    361     return *this;
    362 }
    363 
    364 BroadcasterManager::BroadcasterManager() :
    365     m_manager_mutex(Mutex::eMutexTypeRecursive)
    366 {
    367 
    368 }
    369 
    370 uint32_t
    371 BroadcasterManager::RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
    372 {
    373     Mutex::Locker locker(m_manager_mutex);
    374 
    375     collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
    376     uint32_t available_bits = event_spec.GetEventBits();
    377 
    378     while (iter != end_iter
    379            && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter)
    380     {
    381         available_bits &= ~((*iter).first.GetEventBits());
    382         iter++;
    383     }
    384 
    385     if (available_bits != 0)
    386     {
    387         m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), &listener));
    388         m_listeners.insert(&listener);
    389     }
    390 
    391     return available_bits;
    392 }
    393 
    394 bool
    395 BroadcasterManager::UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec)
    396 {
    397     Mutex::Locker locker(m_manager_mutex);
    398     bool removed_some = false;
    399 
    400     if (m_listeners.erase(&listener) == 0)
    401         return false;
    402 
    403     ListenerMatchesAndSharedBits predicate (event_spec, listener);
    404     std::vector<BroadcastEventSpec> to_be_readded;
    405     uint32_t event_bits_to_remove = event_spec.GetEventBits();
    406 
    407     // Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add:
    408     while (1)
    409     {
    410         collection::iterator iter, end_iter = m_event_map.end();
    411         iter = find_if (m_event_map.begin(), end_iter, predicate);
    412         if (iter == end_iter)
    413         {
    414             break;
    415         }
    416         else
    417         {
    418             uint32_t iter_event_bits = (*iter).first.GetEventBits();
    419             removed_some = true;
    420 
    421             if (event_bits_to_remove != iter_event_bits)
    422             {
    423                 uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
    424                 to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits));
    425             }
    426             m_event_map.erase (iter);
    427         }
    428     }
    429 
    430     // Okay now add back the bits that weren't completely removed:
    431     for (size_t i = 0; i < to_be_readded.size(); i++)
    432     {
    433         m_event_map.insert (event_listener_key (to_be_readded[i], &listener));
    434     }
    435 
    436     return removed_some;
    437 }
    438 
    439 Listener *
    440 BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const
    441 {
    442     Mutex::Locker locker(*(const_cast<Mutex *> (&m_manager_mutex)));
    443 
    444     collection::const_iterator iter, end_iter = m_event_map.end();
    445     iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec));
    446     if (iter != end_iter)
    447         return (*iter).second;
    448     else
    449         return NULL;
    450 }
    451 
    452 void
    453 BroadcasterManager::RemoveListener (Listener &listener)
    454 {
    455     Mutex::Locker locker(m_manager_mutex);
    456     ListenerMatches predicate (listener);
    457 
    458 
    459     if (m_listeners.erase (&listener) == 0)
    460         return;
    461 
    462     while (1)
    463     {
    464         collection::iterator iter, end_iter = m_event_map.end();
    465         iter = find_if (m_event_map.begin(), end_iter, predicate);
    466         if (iter == end_iter)
    467             break;
    468         else
    469             m_event_map.erase(iter);
    470     }
    471 }
    472 
    473 void
    474 BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster)
    475 {
    476     Mutex::Locker locker(m_manager_mutex);
    477 
    478     collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
    479 
    480     while (iter != end_iter
    481            && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter)
    482     {
    483         (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits());
    484         iter++;
    485     }
    486 }
    487 
    488 void
    489 BroadcasterManager::Clear ()
    490 {
    491     Mutex::Locker locker(m_manager_mutex);
    492     listener_collection::iterator end_iter = m_listeners.end();
    493 
    494     for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++)
    495         (*iter)->BroadcasterManagerWillDestruct(this);
    496     m_listeners.clear();
    497     m_event_map.clear();
    498 
    499 }
    500