diff options
Diffstat (limited to 'net/base/network_config_watcher_mac.cc')
-rw-r--r-- | net/base/network_config_watcher_mac.cc | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/net/base/network_config_watcher_mac.cc b/net/base/network_config_watcher_mac.cc index 365859e..dd93067 100644 --- a/net/base/network_config_watcher_mac.cc +++ b/net/base/network_config_watcher_mac.cc @@ -8,12 +8,10 @@ #include <SystemConfiguration/SCSchemaDefinitions.h> #include <algorithm> +#include "base/compiler_specific.h" #include "base/thread.h" #include "base/mac/scoped_cftyperef.h" -// We only post tasks to a child thread we own, so we don't need refcounting. -DISABLE_RUNNABLE_METHOD_REFCOUNT(net::NetworkConfigWatcherMac); - namespace net { namespace { @@ -27,48 +25,59 @@ void DynamicStoreCallback(SCDynamicStoreRef /* store */, net_config_delegate->OnNetworkConfigChange(changed_keys); } -} // namespace +class NetworkConfigWatcherMacThread : public base::Thread { + public: + NetworkConfigWatcherMacThread(NetworkConfigWatcherMac::Delegate* delegate); + virtual ~NetworkConfigWatcherMacThread(); -NetworkConfigWatcherMac::NetworkConfigWatcherMac( - Delegate* delegate) - : notifier_thread_(new base::Thread("NetworkConfigWatcher")), - delegate_(delegate) { - // We create this notifier thread because the notification implementation - // needs a thread with a CFRunLoop, and there's no guarantee that - // MessageLoop::current() meets that criterion. - base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); - notifier_thread_->StartWithOptions(thread_options); + protected: + // base::Thread + virtual void Init(); + virtual void CleanUp(); + + private: + // The SystemConfiguration calls in this function can lead to contention early + // on, so we invoke this function later on in startup to keep it fast. + void InitNotifications(); + + base::mac::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source_; + NetworkConfigWatcherMac::Delegate* const delegate_; + ScopedRunnableMethodFactory<NetworkConfigWatcherMacThread> method_factory_; + + DISALLOW_COPY_AND_ASSIGN(NetworkConfigWatcherMacThread); +}; + +NetworkConfigWatcherMacThread::NetworkConfigWatcherMacThread( + NetworkConfigWatcherMac::Delegate* delegate) + : base::Thread("NetworkConfigWatcher"), + delegate_(delegate), + ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {} + +NetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() { + Stop(); +} + +void NetworkConfigWatcherMacThread::Init() { // TODO(willchan): Look to see if there's a better signal for when it's ok to // initialize this, rather than just delaying it by a fixed time. - const int kNotifierThreadInitializationDelayMS = 1000; - notifier_thread_->message_loop()->PostDelayedTask( + const int kInitializationDelayMS = 1000; + message_loop()->PostDelayedTask( FROM_HERE, - NewRunnableMethod(this, &NetworkConfigWatcherMac::Init), - kNotifierThreadInitializationDelayMS); -} - -NetworkConfigWatcherMac::~NetworkConfigWatcherMac() { - // We don't need to explicitly Stop(), but doing so allows us to sanity- - // check that the notifier thread shut down properly. - notifier_thread_->Stop(); - DCHECK(run_loop_source_ == NULL); + method_factory_.NewRunnableMethod( + &NetworkConfigWatcherMacThread::InitNotifications), + kInitializationDelayMS); } -void NetworkConfigWatcherMac::WillDestroyCurrentMessageLoop() { - DCHECK(notifier_thread_ != NULL); - // We can't check the notifier_thread_'s message_loop(), as it's now 0. - // DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current()); +void NetworkConfigWatcherMacThread::CleanUp() { + if (!run_loop_source_.get()) + return; - DCHECK(run_loop_source_ != NULL); CFRunLoopRemoveSource(CFRunLoopGetCurrent(), run_loop_source_.get(), kCFRunLoopCommonModes); run_loop_source_.reset(); } -void NetworkConfigWatcherMac::Init() { - DCHECK(notifier_thread_ != NULL); - DCHECK_EQ(notifier_thread_->message_loop(), MessageLoop::current()); - +void NetworkConfigWatcherMacThread::InitNotifications() { // Add a run loop source for a dynamic store to the current run loop. SCDynamicStoreContext context = { 0, // Version 0. @@ -86,8 +95,19 @@ void NetworkConfigWatcherMac::Init() { // Set up notifications for interface and IP address changes. delegate_->SetDynamicStoreNotificationKeys(store.get()); +} + +} // namespace - MessageLoop::current()->AddDestructionObserver(this); +NetworkConfigWatcherMac::NetworkConfigWatcherMac(Delegate* delegate) + : notifier_thread_(new NetworkConfigWatcherMacThread(delegate)) { + // We create this notifier thread because the notification implementation + // needs a thread with a CFRunLoop, and there's no guarantee that + // MessageLoop::current() meets that criterion. + base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); + notifier_thread_->StartWithOptions(thread_options); } +NetworkConfigWatcherMac::~NetworkConfigWatcherMac() {} + } // namespace net |