Index: mojo/service_manager/background_shell_service_loader.cc |
diff --git a/mojo/service_manager/background_service_loader.cc b/mojo/service_manager/background_shell_service_loader.cc |
similarity index 39% |
rename from mojo/service_manager/background_service_loader.cc |
rename to mojo/service_manager/background_shell_service_loader.cc |
index 8c60a2cc00696df313e989933dcf63d6875d480f..6d7a2582108628a29c9a728b9be3886ffe978b46 100644 |
--- a/mojo/service_manager/background_service_loader.cc |
+++ b/mojo/service_manager/background_shell_service_loader.cc |
@@ -2,14 +2,15 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "mojo/service_manager/background_service_loader.h" |
+#include "mojo/service_manager/background_shell_service_loader.h" |
#include "base/bind.h" |
+#include "base/run_loop.h" |
#include "mojo/service_manager/service_manager.h" |
namespace mojo { |
-class BackgroundServiceLoader::BackgroundLoader { |
+class BackgroundShellServiceLoader::BackgroundLoader { |
public: |
explicit BackgroundLoader(ServiceLoader* loader) : loader_(loader) {} |
~BackgroundLoader() {} |
@@ -25,81 +26,93 @@ class BackgroundServiceLoader::BackgroundLoader { |
} |
private: |
- base::MessageLoop::Type message_loop_type_; |
- ServiceLoader* loader_; // Owned by BackgroundServiceLoader |
+ ServiceLoader* loader_; // Owned by BackgroundShellServiceLoader |
DISALLOW_COPY_AND_ASSIGN(BackgroundLoader); |
}; |
-BackgroundServiceLoader::BackgroundServiceLoader( |
+BackgroundShellServiceLoader::BackgroundShellServiceLoader( |
scoped_ptr<ServiceLoader> real_loader, |
- const char* thread_name, |
+ const std::string& thread_name, |
base::MessageLoop::Type message_loop_type) |
- : loader_(real_loader.Pass()), |
- thread_(thread_name), |
+ : quit_on_shutdown_(false), |
+ loader_(real_loader.Pass()), |
message_loop_type_(message_loop_type), |
+ thread_name_(thread_name), |
+ message_loop_created_(true, false), |
background_loader_(NULL) { |
} |
-BackgroundServiceLoader::~BackgroundServiceLoader() { |
- if (thread_.IsRunning()) { |
- thread_.message_loop()->PostTask( |
- FROM_HERE, |
- base::Bind(&BackgroundServiceLoader::ShutdownOnBackgroundThread, |
- base::Unretained(this))); |
+BackgroundShellServiceLoader::~BackgroundShellServiceLoader() { |
+ if (thread_) { |
+ if (quit_on_shutdown_) |
+ task_runner_->PostTask(FROM_HERE, quit_closure_); |
+ thread_->Join(); |
} |
- thread_.Stop(); |
} |
-void BackgroundServiceLoader::LoadService( |
+void BackgroundShellServiceLoader::LoadService( |
ServiceManager* manager, |
const GURL& url, |
ScopedMessagePipeHandle shell_handle) { |
- const int kDefaultStackSize = 0; |
- if (!thread_.IsRunning()) { |
- thread_.StartWithOptions( |
- base::Thread::Options(message_loop_type_, kDefaultStackSize)); |
+ if (!thread_) { |
+ // TODO(tim): It'd be nice if we could just have each LoadService call |
+ // result in a new thread like DynamicService{Loader, Runner}. But some |
+ // loaders are creating multiple ApplicationImpls (NetworkServiceLoader) |
+ // sharing a delegate (etc). So we have to keep it single threaded, wait |
+ // for the thread to initialize, and post to the TaskRunner for subsequent |
+ // LoadService calls for now. |
+ thread_.reset(new base::DelegateSimpleThread(this, thread_name_)); |
+ thread_->Start(); |
+ message_loop_created_.Wait(); |
+ DCHECK(task_runner_); |
} |
- thread_.message_loop()->PostTask( |
- FROM_HERE, |
- base::Bind(&BackgroundServiceLoader::LoadServiceOnBackgroundThread, |
+ |
+ task_runner_->PostTask(FROM_HERE, |
+ base::Bind(&BackgroundShellServiceLoader::LoadServiceOnBackgroundThread, |
base::Unretained(this), manager, url, |
base::Owned( |
new ScopedMessagePipeHandle(shell_handle.Pass())))); |
} |
-void BackgroundServiceLoader::OnServiceError(ServiceManager* manager, |
- const GURL& url) { |
- if (!thread_.IsRunning()) |
- thread_.Start(); |
- thread_.message_loop()->PostTask( |
- FROM_HERE, |
- base::Bind(&BackgroundServiceLoader::OnServiceErrorOnBackgroundThread, |
- base::Unretained(this), manager, url)); |
+void BackgroundShellServiceLoader::OnServiceError( |
+ ServiceManager* manager, const GURL& url) { |
+ task_runner_->PostTask(FROM_HERE, |
+ base::Bind( |
+ &BackgroundShellServiceLoader::OnServiceErrorOnBackgroundThread, |
+ base::Unretained(this), manager, url)); |
} |
-void BackgroundServiceLoader::LoadServiceOnBackgroundThread( |
- ServiceManager* manager, |
- const GURL& url, |
- ScopedMessagePipeHandle* shell_handle) { |
+void BackgroundShellServiceLoader::Run() { |
+ base::MessageLoop message_loop(message_loop_type_); |
+ base::RunLoop loop; |
+ task_runner_ = message_loop.task_runner(); |
+ quit_closure_ = loop.QuitClosure(); |
+ message_loop_created_.Signal(); |
+ loop.Run(); |
+ |
+ delete background_loader_; |
+ background_loader_ = NULL; |
+ // Destroy |loader_| on the thread it's actually used on. |
+ loader_.reset(); |
+} |
+ |
+void BackgroundShellServiceLoader::LoadServiceOnBackgroundThread( |
+ ServiceManager* manager, |
+ const GURL& url, |
+ ScopedMessagePipeHandle* shell_handle) { |
+ DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
if (!background_loader_) |
background_loader_ = new BackgroundLoader(loader_.get()); |
- background_loader_->LoadService( |
- manager, url, shell_handle->Pass()); |
+ background_loader_->LoadService(manager, url, shell_handle->Pass()); |
} |
-void BackgroundServiceLoader::OnServiceErrorOnBackgroundThread( |
- ServiceManager* manager, |
- const GURL& url) { |
+void BackgroundShellServiceLoader::OnServiceErrorOnBackgroundThread( |
+ ServiceManager* manager, const GURL& url) { |
+ DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
if (!background_loader_) |
background_loader_ = new BackgroundLoader(loader_.get()); |
background_loader_->OnServiceError(manager, url); |
} |
-void BackgroundServiceLoader::ShutdownOnBackgroundThread() { |
- delete background_loader_; |
- // Destroy |loader_| on the thread it's actually used on. |
- loader_.reset(); |
-} |
- |
} // namespace mojo |