Listener.cpp revision 360784
1238106Sdes//===-- Listener.cpp --------------------------------------------*- C++ -*-===// 2238106Sdes// 3238106Sdes// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4238106Sdes// See https://llvm.org/LICENSE.txt for license information. 5238106Sdes// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6238106Sdes// 7238106Sdes//===----------------------------------------------------------------------===// 8238106Sdes 9238106Sdes#include "lldb/Utility/Listener.h" 10238106Sdes 11238106Sdes#include "lldb/Utility/Broadcaster.h" 12238106Sdes#include "lldb/Utility/ConstString.h" 13238106Sdes#include "lldb/Utility/Event.h" 14238106Sdes#include "lldb/Utility/Log.h" 15238106Sdes#include "lldb/Utility/Logging.h" 16238106Sdes 17238106Sdes#include "llvm/ADT/Optional.h" 18238106Sdes 19238106Sdes#include <algorithm> 20238106Sdes#include <memory> 21238106Sdes#include <utility> 22238106Sdes 23238106Sdesusing namespace lldb; 24269257Sdesusing namespace lldb_private; 25269257Sdes 26269257Sdesnamespace { 27269257Sdesclass BroadcasterManagerWPMatcher { 28269257Sdespublic: 29269257Sdes BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp) 30269257Sdes : m_manager_sp(std::move(manager_sp)) {} 31269257Sdes bool operator()(const BroadcasterManagerWP &input_wp) const { 32269257Sdes BroadcasterManagerSP input_sp = input_wp.lock(); 33269257Sdes return (input_sp && input_sp == m_manager_sp); 34238106Sdes } 35238106Sdes 36238106Sdes BroadcasterManagerSP m_manager_sp; 37238106Sdes}; 38238106Sdes} // anonymous namespace 39238106Sdes 40238106SdesListener::Listener(const char *name) 41238106Sdes : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(), 42238106Sdes m_events_mutex() { 43238106Sdes Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 44238106Sdes if (log != nullptr) 45238106Sdes LLDB_LOGF(log, "%p Listener::Listener('%s')", static_cast<void *>(this), 46238106Sdes m_name.c_str()); 47238106Sdes} 48238106Sdes 49238106SdesListener::~Listener() { 50238106Sdes Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 51238106Sdes 52238106Sdes Clear(); 53238106Sdes 54269257Sdes LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this), 55238106Sdes __FUNCTION__, m_name.c_str()); 56238106Sdes} 57238106Sdes 58238106Sdesvoid Listener::Clear() { 59238106Sdes Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 60238106Sdes std::lock_guard<std::recursive_mutex> broadcasters_guard( 61238106Sdes m_broadcasters_mutex); 62238106Sdes broadcaster_collection::iterator pos, end = m_broadcasters.end(); 63238106Sdes for (pos = m_broadcasters.begin(); pos != end; ++pos) { 64238106Sdes Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock()); 65238106Sdes if (broadcaster_sp) 66238106Sdes broadcaster_sp->RemoveListener(this, pos->second.event_mask); 67238106Sdes } 68238106Sdes m_broadcasters.clear(); 69238106Sdes 70238106Sdes std::lock_guard<std::mutex> events_guard(m_events_mutex); 71238106Sdes m_events.clear(); 72238106Sdes size_t num_managers = m_broadcaster_managers.size(); 73238106Sdes 74238106Sdes for (size_t i = 0; i < num_managers; i++) { 75238106Sdes BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock()); 76238106Sdes if (manager_sp) 77238106Sdes manager_sp->RemoveListener(this); 78238106Sdes } 79238106Sdes 80238106Sdes LLDB_LOGF(log, "%p Listener::%s('%s')", static_cast<void *>(this), 81238106Sdes __FUNCTION__, m_name.c_str()); 82238106Sdes} 83238106Sdes 84238106Sdesuint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, 85238106Sdes uint32_t event_mask) { 86238106Sdes if (broadcaster) { 87238106Sdes // Scope for "locker" 88238106Sdes // Tell the broadcaster to add this object as a listener 89238106Sdes { 90238106Sdes std::lock_guard<std::recursive_mutex> broadcasters_guard( 91238106Sdes m_broadcasters_mutex); 92238106Sdes Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); 93238106Sdes m_broadcasters.insert( 94238106Sdes std::make_pair(impl_wp, BroadcasterInfo(event_mask))); 95238106Sdes } 96238106Sdes 97238106Sdes uint32_t acquired_mask = 98238106Sdes broadcaster->AddListener(this->shared_from_this(), event_mask); 99238106Sdes 100238106Sdes Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 101238106Sdes if (log != nullptr) 102238106Sdes LLDB_LOGF(log, 103238106Sdes "%p Listener::StartListeningForEvents (broadcaster = %p, " 104238106Sdes "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", 105238106Sdes static_cast<void *>(this), static_cast<void *>(broadcaster), 106238106Sdes event_mask, acquired_mask, m_name.c_str()); 107238106Sdes 108238106Sdes return acquired_mask; 109238106Sdes } 110238106Sdes return 0; 111238106Sdes} 112238106Sdes 113238106Sdesuint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, 114238106Sdes uint32_t event_mask, 115238106Sdes HandleBroadcastCallback callback, 116238106Sdes void *callback_user_data) { 117238106Sdes if (broadcaster) { 118238106Sdes // Scope for "locker" 119238106Sdes // Tell the broadcaster to add this object as a listener 120238106Sdes { 121238106Sdes std::lock_guard<std::recursive_mutex> broadcasters_guard( 122238106Sdes m_broadcasters_mutex); 123238106Sdes Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); 124238106Sdes m_broadcasters.insert(std::make_pair( 125238106Sdes impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data))); 126238106Sdes } 127238106Sdes 128238106Sdes uint32_t acquired_mask = 129269257Sdes broadcaster->AddListener(this->shared_from_this(), event_mask); 130238106Sdes 131238106Sdes Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 132238106Sdes if (log != nullptr) { 133238106Sdes void **pointer = reinterpret_cast<void **>(&callback); 134238106Sdes LLDB_LOGF(log, 135238106Sdes "%p Listener::StartListeningForEvents (broadcaster = %p, " 136238106Sdes "mask = 0x%8.8x, callback = %p, user_data = %p) " 137238106Sdes "acquired_mask = 0x%8.8x for %s", 138238106Sdes static_cast<void *>(this), static_cast<void *>(broadcaster), 139238106Sdes event_mask, *pointer, static_cast<void *>(callback_user_data), 140238106Sdes acquired_mask, m_name.c_str()); 141238106Sdes } 142238106Sdes 143238106Sdes return acquired_mask; 144238106Sdes } 145238106Sdes return 0; 146238106Sdes} 147238106Sdes 148238106Sdesbool Listener::StopListeningForEvents(Broadcaster *broadcaster, 149238106Sdes uint32_t event_mask) { 150238106Sdes if (broadcaster) { 151238106Sdes // Scope for "locker" 152238106Sdes { 153238106Sdes std::lock_guard<std::recursive_mutex> broadcasters_guard( 154238106Sdes m_broadcasters_mutex); 155238106Sdes m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); 156238106Sdes } 157238106Sdes // Remove the broadcaster from our set of broadcasters 158238106Sdes return broadcaster->RemoveListener(this->shared_from_this(), event_mask); 159238106Sdes } 160238106Sdes 161238106Sdes return false; 162238106Sdes} 163238106Sdes 164238106Sdes// Called when a Broadcaster is in its destructor. We need to remove all 165238106Sdes// knowledge of this broadcaster and any events that it may have queued up 166238106Sdesvoid Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) { 167238106Sdes // Scope for "broadcasters_locker" 168238106Sdes { 169238106Sdes std::lock_guard<std::recursive_mutex> broadcasters_guard( 170238106Sdes m_broadcasters_mutex); 171238106Sdes m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); 172238106Sdes } 173238106Sdes 174238106Sdes // Scope for "event_locker" 175238106Sdes { 176238106Sdes std::lock_guard<std::mutex> events_guard(m_events_mutex); 177238106Sdes // Remove all events for this broadcaster object. 178238106Sdes event_collection::iterator pos = m_events.begin(); 179238106Sdes while (pos != m_events.end()) { 180238106Sdes if ((*pos)->GetBroadcaster() == broadcaster) 181238106Sdes pos = m_events.erase(pos); 182238106Sdes else 183238106Sdes ++pos; 184238106Sdes } 185238106Sdes } 186238106Sdes} 187238106Sdes 188238106Sdesvoid Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { 189238106Sdes // Just need to remove this broadcast manager from the list of managers: 190238106Sdes broadcaster_manager_collection::iterator iter, 191238106Sdes end_iter = m_broadcaster_managers.end(); 192238106Sdes BroadcasterManagerWP manager_wp; 193238106Sdes 194238106Sdes BroadcasterManagerWPMatcher matcher(std::move(manager_sp)); 195238106Sdes iter = std::find_if<broadcaster_manager_collection::iterator, 196238106Sdes BroadcasterManagerWPMatcher>( 197238106Sdes m_broadcaster_managers.begin(), end_iter, matcher); 198238106Sdes if (iter != end_iter) 199238106Sdes m_broadcaster_managers.erase(iter); 200238106Sdes} 201238106Sdes 202238106Sdesvoid Listener::AddEvent(EventSP &event_sp) { 203238106Sdes Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 204238106Sdes if (log != nullptr) 205238106Sdes LLDB_LOGF(log, "%p Listener('%s')::AddEvent (event_sp = {%p})", 206238106Sdes static_cast<void *>(this), m_name.c_str(), 207238106Sdes static_cast<void *>(event_sp.get())); 208238106Sdes 209238106Sdes std::lock_guard<std::mutex> guard(m_events_mutex); 210238106Sdes m_events.push_back(event_sp); 211238106Sdes m_events_condition.notify_all(); 212238106Sdes} 213238106Sdes 214238106Sdesclass EventBroadcasterMatches { 215238106Sdespublic: 216238106Sdes EventBroadcasterMatches(Broadcaster *broadcaster) 217238106Sdes : m_broadcaster(broadcaster) {} 218238106Sdes 219238106Sdes bool operator()(const EventSP &event_sp) const { 220238106Sdes return event_sp->BroadcasterIs(m_broadcaster); 221238106Sdes } 222238106Sdes 223269257Sdesprivate: 224238106Sdes Broadcaster *m_broadcaster; 225238106Sdes}; 226238106Sdes 227238106Sdesclass EventMatcher { 228238106Sdespublic: 229238106Sdes EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names, 230238106Sdes uint32_t num_broadcaster_names, uint32_t event_type_mask) 231238106Sdes : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names), 232238106Sdes m_num_broadcaster_names(num_broadcaster_names), 233238106Sdes m_event_type_mask(event_type_mask) {} 234238106Sdes 235238106Sdes bool operator()(const EventSP &event_sp) const { 236238106Sdes if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster)) 237238106Sdes return false; 238238106Sdes 239269257Sdes if (m_broadcaster_names) { 240238106Sdes bool found_source = false; 241238106Sdes ConstString event_broadcaster_name = 242238106Sdes event_sp->GetBroadcaster()->GetBroadcasterName(); 243238106Sdes for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) { 244238106Sdes if (m_broadcaster_names[i] == event_broadcaster_name) { 245238106Sdes found_source = true; 246238106Sdes break; 247238106Sdes } 248238106Sdes } 249238106Sdes if (!found_source) 250238106Sdes return false; 251238106Sdes } 252238106Sdes 253238106Sdes return m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType(); 254238106Sdes } 255238106Sdes 256238106Sdesprivate: 257238106Sdes Broadcaster *m_broadcaster; 258238106Sdes const ConstString *m_broadcaster_names; 259238106Sdes const uint32_t m_num_broadcaster_names; 260238106Sdes const uint32_t m_event_type_mask; 261238106Sdes}; 262238106Sdes 263238106Sdesbool Listener::FindNextEventInternal( 264238106Sdes std::unique_lock<std::mutex> &lock, 265238106Sdes Broadcaster *broadcaster, // nullptr for any broadcaster 266238106Sdes const ConstString *broadcaster_names, // nullptr for any event 267238106Sdes uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp, 268238106Sdes bool remove) { 269238106Sdes // NOTE: callers of this function must lock m_events_mutex using a 270238106Sdes // Mutex::Locker 271238106Sdes // and pass the locker as the first argument. m_events_mutex is no longer 272238106Sdes // recursive. 273238106Sdes Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 274238106Sdes 275238106Sdes if (m_events.empty()) 276238106Sdes return false; 277238106Sdes 278238106Sdes Listener::event_collection::iterator pos = m_events.end(); 279238106Sdes 280238106Sdes if (broadcaster == nullptr && broadcaster_names == nullptr && 281238106Sdes event_type_mask == 0) { 282238106Sdes pos = m_events.begin(); 283238106Sdes } else { 284238106Sdes pos = std::find_if(m_events.begin(), m_events.end(), 285238106Sdes EventMatcher(broadcaster, broadcaster_names, 286238106Sdes num_broadcaster_names, event_type_mask)); 287238106Sdes } 288238106Sdes 289238106Sdes if (pos != m_events.end()) { 290238106Sdes event_sp = *pos; 291238106Sdes 292238106Sdes if (log != nullptr) 293238106Sdes LLDB_LOGF(log, 294238106Sdes "%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " 295238106Sdes "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " 296238106Sdes "remove=%i) event %p", 297238106Sdes static_cast<void *>(this), GetName(), 298269257Sdes static_cast<void *>(broadcaster), 299238106Sdes static_cast<const void *>(broadcaster_names), 300238106Sdes num_broadcaster_names, event_type_mask, remove, 301238106Sdes static_cast<void *>(event_sp.get())); 302238106Sdes 303238106Sdes if (remove) { 304238106Sdes m_events.erase(pos); 305238106Sdes // Unlock the event queue here. We've removed this event and are about 306238106Sdes // to return it so it should be okay to get the next event off the queue 307238106Sdes // here - and it might be useful to do that in the "DoOnRemoval". 308238106Sdes lock.unlock(); 309238106Sdes event_sp->DoOnRemoval(); 310238106Sdes } 311269257Sdes return true; 312238106Sdes } 313238106Sdes 314238106Sdes event_sp.reset(); 315238106Sdes return false; 316238106Sdes} 317238106Sdes 318238106SdesEvent *Listener::PeekAtNextEvent() { 319238106Sdes std::unique_lock<std::mutex> guard(m_events_mutex); 320238106Sdes EventSP event_sp; 321238106Sdes if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false)) 322238106Sdes return event_sp.get(); 323238106Sdes return nullptr; 324238106Sdes} 325238106Sdes 326238106SdesEvent *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) { 327238106Sdes std::unique_lock<std::mutex> guard(m_events_mutex); 328238106Sdes EventSP event_sp; 329238106Sdes if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false)) 330238106Sdes return event_sp.get(); 331238106Sdes return nullptr; 332238106Sdes} 333238106Sdes 334238106SdesEvent * 335238106SdesListener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, 336238106Sdes uint32_t event_type_mask) { 337238106Sdes std::unique_lock<std::mutex> guard(m_events_mutex); 338238106Sdes EventSP event_sp; 339238106Sdes if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask, 340238106Sdes event_sp, false)) 341238106Sdes return event_sp.get(); 342238106Sdes return nullptr; 343238106Sdes} 344238106Sdes 345238106Sdesbool Listener::GetEventInternal( 346238106Sdes const Timeout<std::micro> &timeout, 347238106Sdes Broadcaster *broadcaster, // nullptr for any broadcaster 348238106Sdes const ConstString *broadcaster_names, // nullptr for any event 349238106Sdes uint32_t num_broadcaster_names, uint32_t event_type_mask, 350238106Sdes EventSP &event_sp) { 351238106Sdes Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); 352238106Sdes LLDB_LOG(log, "this = {0}, timeout = {1} for {2}", this, timeout, m_name); 353238106Sdes 354238106Sdes std::unique_lock<std::mutex> lock(m_events_mutex); 355238106Sdes 356285206Sdes while (true) { 357238106Sdes if (FindNextEventInternal(lock, broadcaster, broadcaster_names, 358238106Sdes num_broadcaster_names, event_type_mask, event_sp, 359238106Sdes true)) { 360238106Sdes return true; 361238106Sdes } else { 362285206Sdes std::cv_status result = std::cv_status::no_timeout; 363238106Sdes if (!timeout) 364238106Sdes m_events_condition.wait(lock); 365238106Sdes else 366238106Sdes result = m_events_condition.wait_for(lock, *timeout); 367238106Sdes 368238106Sdes if (result == std::cv_status::timeout) { 369238106Sdes log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); 370238106Sdes LLDB_LOGF(log, "%p Listener::GetEventInternal() timed out for %s", 371238106Sdes static_cast<void *>(this), m_name.c_str()); 372238106Sdes return false; 373238106Sdes } else if (result != std::cv_status::no_timeout) { 374238106Sdes log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); 375238106Sdes LLDB_LOGF(log, "%p Listener::GetEventInternal() unknown error for %s", 376238106Sdes static_cast<void *>(this), m_name.c_str()); 377238106Sdes return false; 378238106Sdes } 379238106Sdes } 380238106Sdes } 381238106Sdes 382238106Sdes return false; 383238106Sdes} 384238106Sdes 385238106Sdesbool Listener::GetEventForBroadcasterWithType( 386238106Sdes Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp, 387238106Sdes const Timeout<std::micro> &timeout) { 388238106Sdes return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask, 389238106Sdes event_sp); 390238106Sdes} 391238106Sdes 392238106Sdesbool Listener::GetEventForBroadcaster(Broadcaster *broadcaster, 393238106Sdes EventSP &event_sp, 394238106Sdes const Timeout<std::micro> &timeout) { 395238106Sdes return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp); 396238106Sdes} 397238106Sdes 398238106Sdesbool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) { 399238106Sdes return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp); 400238106Sdes} 401238106Sdes 402238106Sdessize_t Listener::HandleBroadcastEvent(EventSP &event_sp) { 403238106Sdes size_t num_handled = 0; 404238106Sdes std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 405238106Sdes Broadcaster *broadcaster = event_sp->GetBroadcaster(); 406238106Sdes if (!broadcaster) 407238106Sdes return 0; 408238106Sdes broadcaster_collection::iterator pos; 409238106Sdes broadcaster_collection::iterator end = m_broadcasters.end(); 410285206Sdes Broadcaster::BroadcasterImplSP broadcaster_impl_sp( 411285206Sdes broadcaster->GetBroadcasterImpl()); 412238106Sdes for (pos = m_broadcasters.find(broadcaster_impl_sp); 413238106Sdes pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) { 414238106Sdes BroadcasterInfo info = pos->second; 415285206Sdes if (event_sp->GetType() & info.event_mask) { 416238106Sdes if (info.callback != nullptr) { 417238106Sdes info.callback(event_sp, info.callback_user_data); 418238106Sdes ++num_handled; 419238106Sdes } 420238106Sdes } 421238106Sdes } 422238106Sdes return num_handled; 423238106Sdes} 424238106Sdes 425238106Sdesuint32_t 426238106SdesListener::StartListeningForEventSpec(const BroadcasterManagerSP &manager_sp, 427238106Sdes const BroadcastEventSpec &event_spec) { 428238106Sdes if (!manager_sp) 429238106Sdes return 0; 430238106Sdes 431238106Sdes // The BroadcasterManager mutex must be locked before m_broadcasters_mutex to 432238106Sdes // avoid violating the lock hierarchy (manager before broadcasters). 433238106Sdes std::lock_guard<std::recursive_mutex> manager_guard( 434238106Sdes manager_sp->m_manager_mutex); 435238106Sdes std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 436238106Sdes 437238106Sdes uint32_t bits_acquired = manager_sp->RegisterListenerForEvents( 438285206Sdes this->shared_from_this(), event_spec); 439238106Sdes if (bits_acquired) { 440238106Sdes broadcaster_manager_collection::iterator iter, 441238106Sdes end_iter = m_broadcaster_managers.end(); 442285206Sdes BroadcasterManagerWP manager_wp(manager_sp); 443238106Sdes BroadcasterManagerWPMatcher matcher(manager_sp); 444238106Sdes iter = std::find_if<broadcaster_manager_collection::iterator, 445238106Sdes BroadcasterManagerWPMatcher>( 446238106Sdes m_broadcaster_managers.begin(), end_iter, matcher); 447238106Sdes if (iter == end_iter) 448238106Sdes m_broadcaster_managers.push_back(manager_wp); 449238106Sdes } 450238106Sdes 451238106Sdes return bits_acquired; 452238106Sdes} 453238106Sdes 454238106Sdesbool Listener::StopListeningForEventSpec(const BroadcasterManagerSP &manager_sp, 455238106Sdes const BroadcastEventSpec &event_spec) { 456238106Sdes if (!manager_sp) 457238106Sdes return false; 458238106Sdes 459238106Sdes std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); 460238106Sdes return manager_sp->UnregisterListenerForEvents(this->shared_from_this(), 461238106Sdes event_spec); 462238106Sdes} 463238106Sdes 464238106SdesListenerSP Listener::MakeListener(const char *name) { 465238106Sdes return ListenerSP(new Listener(name)); 466238106Sdes} 467238106Sdes