summaryrefslogtreecommitdiffstats
path: root/net/base/network_config_watcher_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/base/network_config_watcher_mac.cc')
-rw-r--r--net/base/network_config_watcher_mac.cc88
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