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

Unified Diff: content/renderer/indexed_db_message_filter.cc

Issue 8747002: Dispatch IndexedDB IPC messages to worker threads (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: inject thread ids into ipcs Created 9 years, 1 month 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/renderer/indexed_db_message_filter.cc
diff --git a/content/renderer/indexed_db_message_filter.cc b/content/renderer/indexed_db_message_filter.cc
new file mode 100644
index 0000000000000000000000000000000000000000..87013ab037769d85ac44e09c5db6e24df4e62578
--- /dev/null
+++ b/content/renderer/indexed_db_message_filter.cc
@@ -0,0 +1,175 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/indexed_db_message_filter.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "content/common/indexed_db_messages.h"
+#include "content/common/worker_task_runner.h"
+#include "content/renderer/indexed_db_dispatcher.h"
+#include "content/renderer/render_thread_impl.h"
+
+IndexedDBMessageFilter::IndexedDBMessageFilter() :
+ main_thread_loop_proxy_(base::MessageLoopProxy::current()) {
+ // This is called on the main thread.
+}
+
+IndexedDBMessageFilter::~IndexedDBMessageFilter() {
+ // This seems to never be called.
+}
+
+WorkerTaskRunner* worker_task_runner() {
+ return ChildThread::current()->worker_task_runner();
+}
+
+void IndexedDBMessageFilter::onLoopRegistered() {
+}
+
+void IndexedDBMessageFilter::onLoopUnregistered() {
+ if (idb_dispatcher_tls_.Get())
+ delete idb_dispatcher_tls_.Get();
+}
+
+int IndexedDBMessageFilter::current() {
+ return ChildThread::current()->worker_task_runner()->CurrentWorkerId();
+}
+
+int IndexedDBMessageFilter::current_worker_id() {
+ return ChildThread::current()->worker_task_runner()->CurrentWorkerId();
+}
+
+int ExtractThreadID(int callback_id) {
+ return (callback_id & 0xFF000000) >> 24;
+}
+
+int IndexedDBMessageFilter::InjectThreadID(int response_id) {
+ int32 thread_id = current();
+ DCHECK(thread_id <= 0xFF);
michaeln 2011/12/01 21:42:05 (stashing this value in the high nibble :) it loo
dgrogan 2011/12/01 22:49:00 High byte, but yeah.
michaeln 2011/12/02 00:15:03 Seems like it'd be fairly mechanical and limited t
+ DCHECK(response_id <= 0x00FFFFFF);
+ return response_id | (thread_id << 24);
+}
+
+int IndexedDBMessageFilter::GetUniqueID() {
+ base::AutoLock locker(id_lock_);
+ int id = ++unique_id_;
michaeln 2011/12/01 21:42:05 take a look at AtomicSequenceNumber
dgrogan 2011/12/01 22:49:00 Ah nice, thanks for the pointer.
+ return InjectThreadID(id);
+}
+
+int ExtractCallbackID(const IPC::Message& msg) {
+ return IPC::MessageIterator(msg).NextInt();
+}
+
+bool IndexedDBMessageFilter::OnMessageReceived(const IPC::Message& msg) {
+ if (IPC_MESSAGE_CLASS(msg) != IndexedDBMsgStart)
+ return false;
+ int callback_id = ExtractCallbackID(msg);
+// Forward to worker task runner
+ switch(msg.type()) {
+ case IndexedDBMsg_TransactionCallbacksAbort::ID:
+ case IndexedDBMsg_TransactionCallbacksComplete::ID:
+ ForwardToThread(msg, callback_id, transaction_id_to_run_loop_);
+ break;
+ case IndexedDBMsg_DatabaseCallbacksVersionChange::ID:
+ ForwardToThread(msg, callback_id, database_id_to_run_loop_);
+ break;
+ default:
+ ForwardToThread(msg, ExtractThreadID(callback_id));
+ }
+ return true;
+}
+
+void IndexedDBMessageFilter::ForwardToMainThread(const IPC::Message& msg) {
+ main_thread_loop_proxy_->PostTask(FROM_HERE,
+ base::Bind(&IndexedDBMessageFilter::DispatchMessage, this, msg));
+}
+
+void IndexedDBMessageFilter::DispatchMessage(const IPC::Message& msg) {
+ thread_specific_idb_dispatcher()->OnMessageReceived(msg);
+}
+
+class MsgForwarderTask : public WebKit::WebWorkerRunLoop::Task {
+ public:
+ MsgForwarderTask(const IPC::Message& msg, IndexedDBMessageFilter* filter) :
+ msg_(msg),
+ filter_(filter) {
+ }
+ virtual ~MsgForwarderTask() { }
+ virtual void Run() {
+ IndexedDBDispatcher* dispatcher = filter_->thread_specific_idb_dispatcher();
+ dispatcher->OnMessageReceived(msg_);
+ }
+ private:
+ const IPC::Message msg_;
+ IndexedDBMessageFilter* filter_;
+};
+
+void IndexedDBMessageFilter::ForwardToThread(const IPC::Message& msg,
+ int thread_id) {
+ if (!thread_id) {
+ ForwardToMainThread(msg);
+ return;
+ }
+ MsgForwarderTask* task = new MsgForwarderTask(msg, this);
+ worker_task_runner()->PostTask(thread_id, task);
+}
+void IndexedDBMessageFilter::ForwardToThread(const IPC::Message& msg, int32 id,
+ const IDToRunLoopMap& map) {
+ base::AutoLock map_locker(map_lock_);
+ IDToRunLoopMap::const_iterator iter = map.find(id);
+ if (iter == map.end()) {
+ ForwardToMainThread(msg);
+ return;
+ }
+ ForwardToThread(msg, iter->second);
+}
+
+IndexedDBDispatcher* IndexedDBMessageFilter::thread_specific_idb_dispatcher() {
+ if (idb_dispatcher_tls_.Get())
+ return idb_dispatcher_tls_.Get();
+
+ IndexedDBDispatcher* dispatcher = new IndexedDBDispatcher(this);
+ idb_dispatcher_tls_.Set(dispatcher);
+ return dispatcher;
+}
+
+void IndexedDBMessageFilter::RemoveForType(int32 id, WebKit::WebIDBCallbacks*) {
+}
+
+void IndexedDBMessageFilter::RemoveForType(
+ int32 id,
+ WebKit::WebIDBDatabaseCallbacks*) {
+ RemoveFromMap(id, &database_id_to_run_loop_);
+}
+
+void IndexedDBMessageFilter::RemoveForType(
+ int32 id,
+ WebKit::WebIDBTransactionCallbacks*) {
+ RemoveFromMap(id, &transaction_id_to_run_loop_);
+}
+
+void IndexedDBMessageFilter::RemoveFromMap(int32 id, IDToRunLoopMap* map) {
+ // We don't store ids that are associated with the main thread.
+ if (!current())
+ return;
+ base::AutoLock map_locker(map_lock_);
+ int num_erased = map->erase(id);
+ DCHECK_EQ(num_erased, 1);
+}
+
+void IndexedDBMessageFilter::NotifyAddWithIDForType(
+ int32 id, WebKit::WebIDBTransactionCallbacks* callbacks) {
+ if (current()) {
+ base::AutoLock map_locker(map_lock_);
+ transaction_id_to_run_loop_[id] = current();
+ }
+}
+
+void IndexedDBMessageFilter::NotifyAddWithIDForType(int32 id,
+ WebKit::WebIDBDatabaseCallbacks* callbacks) {
+ if (current()) {
+ base::AutoLock map_locker(map_lock_);
+ database_id_to_run_loop_[id] = current();
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698