Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Unified Diff: content/browser/device_orientation/provider_impl.cc

Issue 10835030: device_orientation::ProviderImpl to stop polling thread asynchronously (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/device_orientation/provider_impl.cc
===================================================================
--- content/browser/device_orientation/provider_impl.cc (revision 148849)
+++ content/browser/device_orientation/provider_impl.cc (working copy)
@@ -10,69 +10,87 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
+#include "base/threading/worker_pool.h"
#include "content/browser/device_orientation/orientation.h"
#include "content/browser/device_orientation/provider_impl.h"
-namespace device_orientation {
+namespace {
-ProviderImpl::ProviderImpl(const DataFetcherFactory factories[])
- : creator_loop_(MessageLoop::current()),
- ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
- for (const DataFetcherFactory* fp = factories; *fp; ++fp)
- factories_.push_back(*fp);
+bool IsElementSignificantlyDifferent(bool can_provide_element1,
+ bool can_provide_element2,
+ double element1,
+ double element2) {
+ const double kThreshold = 0.1;
+
+ if (can_provide_element1 != can_provide_element2)
+ return true;
+ if (can_provide_element1 &&
+ std::fabs(element1 - element2) >= kThreshold)
+ return true;
+ return false;
}
-ProviderImpl::~ProviderImpl() {
+void DeleteThread(base::Thread* thread) {
+ delete thread;
}
-void ProviderImpl::AddObserver(Observer* observer) {
- DCHECK(MessageLoop::current() == creator_loop_);
-
- observers_.insert(observer);
- if (observers_.size() == 1)
- Start();
- else
- observer->OnOrientationUpdate(last_notification_);
}
-void ProviderImpl::RemoveObserver(Observer* observer) {
- DCHECK(MessageLoop::current() == creator_loop_);
+namespace device_orientation {
- observers_.erase(observer);
- if (observers_.empty())
- Stop();
-}
+class ProviderImpl::PollingThread : public base::Thread {
+ public:
+ PollingThread(const char* name,
+ base::WeakPtr<ProviderImpl> provider,
+ MessageLoop* creator_loop);
+ virtual ~PollingThread();
-void ProviderImpl::Start() {
- DCHECK(MessageLoop::current() == creator_loop_);
- DCHECK(!polling_thread_.get());
+ // Method for finding a suitable DataFetcher and starting the polling.
+ void Initialize(const std::vector<DataFetcherFactory>& factories);
- polling_thread_.reset(new base::Thread("Device orientation polling thread"));
- if (!polling_thread_->Start()) {
- LOG(ERROR) << "Failed to start device orientation polling thread";
- polling_thread_.reset();
- return;
- }
- ScheduleInitializePollingThread();
-}
+ private:
+ // Method for polling a DataFetcher.
+ void DoPoll();
+ void ScheduleDoPoll();
-void ProviderImpl::Stop() {
- DCHECK(MessageLoop::current() == creator_loop_);
+ // Schedule a notification to the |provider_| which lives on a different
+ // thread (|creator_loop_| is its message loop).
+ void ScheduleDoNotify(const Orientation& orientation);
- // TODO(hans): Don't join the thread. See crbug.com/72286.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
+ static bool SignificantlyDifferent(const Orientation& orientation1,
+ const Orientation& orientation2);
- polling_thread_.reset();
- data_fetcher_.reset();
+ enum { kDesiredSamplingIntervalMs = 100 };
+ base::TimeDelta SamplingInterval() const;
+
+ // The Message Loop on which this object was created.
+ // Typically the I/O loop, but may be something else during testing.
+ MessageLoop* creator_loop_;
+
+ scoped_ptr<DataFetcher> data_fetcher_;
+ Orientation last_orientation_;
+
+ base::WeakPtr<ProviderImpl> provider_;
+};
+
+ProviderImpl::PollingThread::PollingThread(
+ const char* name,
+ base::WeakPtr<ProviderImpl> provider,
+ MessageLoop* creator_loop)
+ : base::Thread(name),
+ creator_loop_(creator_loop),
+ provider_(provider) {
}
-void ProviderImpl::DoInitializePollingThread(
+ProviderImpl::PollingThread::~PollingThread() {
+}
+
+void ProviderImpl::PollingThread::Initialize(
const std::vector<DataFetcherFactory>& factories) {
- DCHECK(MessageLoop::current() == polling_thread_->message_loop());
+ DCHECK(MessageLoop::current() == message_loop());
typedef std::vector<DataFetcherFactory>::const_iterator Iterator;
- for (Iterator i = factories_.begin(), e = factories_.end(); i != e; ++i) {
+ for (Iterator i = factories.begin(); i != factories.end(); ++i) {
DataFetcherFactory factory = *i;
scoped_ptr<DataFetcher> fetcher(factory());
Orientation orientation;
@@ -96,41 +114,16 @@
ScheduleDoNotify(Orientation::Empty());
}
-void ProviderImpl::ScheduleInitializePollingThread() {
- DCHECK(MessageLoop::current() == creator_loop_);
+void ProviderImpl::PollingThread::ScheduleDoNotify(
+ const Orientation& orientation) {
+ DCHECK(MessageLoop::current() == message_loop());
- MessageLoop* polling_loop = polling_thread_->message_loop();
- polling_loop->PostTask(FROM_HERE,
- base::Bind(&ProviderImpl::DoInitializePollingThread,
- this,
- factories_));
-}
-
-void ProviderImpl::DoNotify(const Orientation& orientation) {
- DCHECK(MessageLoop::current() == creator_loop_);
-
- last_notification_ = orientation;
-
- typedef std::set<Observer*>::const_iterator Iterator;
- for (Iterator i = observers_.begin(), e = observers_.end(); i != e; ++i)
- (*i)->OnOrientationUpdate(orientation);
-
- if (orientation.is_empty()) {
- // Notify observers about failure to provide data exactly once.
- observers_.clear();
- Stop();
- }
-}
-
-void ProviderImpl::ScheduleDoNotify(const Orientation& orientation) {
- DCHECK(MessageLoop::current() == polling_thread_->message_loop());
-
creator_loop_->PostTask(
- FROM_HERE, base::Bind(&ProviderImpl::DoNotify, this, orientation));
+ FROM_HERE, base::Bind(&ProviderImpl::DoNotify, provider_, orientation));
}
-void ProviderImpl::DoPoll() {
- DCHECK(MessageLoop::current() == polling_thread_->message_loop());
+void ProviderImpl::PollingThread::DoPoll() {
+ DCHECK(MessageLoop::current() == message_loop());
Orientation orientation;
if (!data_fetcher_->GetOrientation(&orientation)) {
@@ -149,37 +142,20 @@
ScheduleDoPoll();
}
-void ProviderImpl::ScheduleDoPoll() {
- DCHECK(MessageLoop::current() == polling_thread_->message_loop());
+void ProviderImpl::PollingThread::ScheduleDoPoll() {
+ DCHECK(MessageLoop::current() == message_loop());
- MessageLoop* polling_loop = polling_thread_->message_loop();
- polling_loop->PostDelayedTask(
+ message_loop()->PostDelayedTask(
FROM_HERE,
- base::Bind(&ProviderImpl::DoPoll, weak_factory_.GetWeakPtr()),
+ base::Bind(&PollingThread::DoPoll, base::Unretained(this)),
SamplingInterval());
}
-namespace {
-
-bool IsElementSignificantlyDifferent(bool can_provide_element1,
- bool can_provide_element2,
- double element1,
- double element2) {
- const double kThreshold = 0.1;
-
- if (can_provide_element1 != can_provide_element2)
- return true;
- if (can_provide_element1 &&
- std::fabs(element1 - element2) >= kThreshold)
- return true;
- return false;
-}
-} // namespace
-
// Returns true if two orientations are considered different enough that
// observers should be notified of the new orientation.
-bool ProviderImpl::SignificantlyDifferent(const Orientation& o1,
- const Orientation& o2) {
+bool ProviderImpl::PollingThread::SignificantlyDifferent(
+ const Orientation& o1,
+ const Orientation& o2) {
return IsElementSignificantlyDifferent(o1.can_provide_alpha(),
o2.can_provide_alpha(),
o1.alpha(),
@@ -196,8 +172,8 @@
o1.absolute() != o2.absolute());
}
-base::TimeDelta ProviderImpl::SamplingInterval() const {
- DCHECK(MessageLoop::current() == polling_thread_->message_loop());
+base::TimeDelta ProviderImpl::PollingThread::SamplingInterval() const {
+ DCHECK(MessageLoop::current() == message_loop());
DCHECK(data_fetcher_.get());
// TODO(erg): There used to be unused code here, that called a default
@@ -206,4 +182,91 @@
return base::TimeDelta::FromMilliseconds(kDesiredSamplingIntervalMs);
}
+ProviderImpl::ProviderImpl(const DataFetcherFactory factories[])
+ : creator_loop_(MessageLoop::current()),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+ polling_thread_(NULL) {
+ for (const DataFetcherFactory* fp = factories; *fp; ++fp)
+ factories_.push_back(*fp);
+}
+
+ProviderImpl::~ProviderImpl() {
+ Stop();
+}
+
+void ProviderImpl::AddObserver(Observer* observer) {
+ DCHECK(MessageLoop::current() == creator_loop_);
+
+ observers_.insert(observer);
+ if (observers_.size() == 1)
+ Start();
+ else
+ observer->OnOrientationUpdate(last_notification_);
+}
+
+void ProviderImpl::RemoveObserver(Observer* observer) {
+ DCHECK(MessageLoop::current() == creator_loop_);
+
+ observers_.erase(observer);
+ if (observers_.empty())
+ Stop();
+}
+
+void ProviderImpl::Start() {
+ DCHECK(MessageLoop::current() == creator_loop_);
+ DCHECK(!polling_thread_);
+
+ polling_thread_ = new PollingThread("Device orientation polling thread",
+ weak_factory_.GetWeakPtr(),
+ creator_loop_);
+ if (!polling_thread_->Start()) {
+ LOG(ERROR) << "Failed to start device orientation polling thread";
+ delete polling_thread_;
+ polling_thread_ = NULL;
+ return;
+ }
+ ScheduleInitializePollingThread();
+}
+
+void ProviderImpl::Stop() {
+ DCHECK(MessageLoop::current() == creator_loop_);
+
+ weak_factory_.InvalidateWeakPtrs();
+ if (polling_thread_) {
+ polling_thread_->StopSoon();
+ bool posted = base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&DeleteThread, base::Unretained(polling_thread_)),
+ true /* task is slow */);
+ DCHECK(posted);
+ polling_thread_ = NULL;
+ }
+}
+
+void ProviderImpl::ScheduleInitializePollingThread() {
+ DCHECK(MessageLoop::current() == creator_loop_);
+
+ MessageLoop* polling_loop = polling_thread_->message_loop();
+ polling_loop->PostTask(FROM_HERE,
+ base::Bind(&PollingThread::Initialize,
+ base::Unretained(polling_thread_),
+ factories_));
+}
+
+void ProviderImpl::DoNotify(const Orientation& orientation) {
+ DCHECK(MessageLoop::current() == creator_loop_);
+
+ last_notification_ = orientation;
+
+ typedef std::set<Observer*>::const_iterator Iterator;
+ for (Iterator i = observers_.begin(); i != observers_.end(); ++i)
+ (*i)->OnOrientationUpdate(orientation);
+
+ if (orientation.is_empty()) {
+ // Notify observers about failure to provide data exactly once.
+ observers_.clear();
+ Stop();
+ }
+}
+
} // namespace device_orientation
« no previous file with comments | « content/browser/device_orientation/provider_impl.h ('k') | content/browser/device_orientation/provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698