Skip to content

Commit

Permalink
Revert 119200 - Revert 119198 - First pass at implementing the Messag…
Browse files Browse the repository at this point in the history
…eLoop interface. This includes a simple

example and a helper class. The current example just asserts due to thread
checks we have in there now, but this should provide a good starting point.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/9097006

TBR=brettw@chromium.org
Review URL: https://chromiumcodereview.appspot.com/9290040

TBR=brettw@chromium.org
Review URL: https://chromiumcodereview.appspot.com/9234068

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119268 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
brettw@chromium.org committed Jan 26, 2012
1 parent d6d971b commit 15b1224
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ppapi/ppapi_proxy.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@
'proxy/ppb_image_data_proxy.h',
'proxy/ppb_instance_proxy.cc',
'proxy/ppb_instance_proxy.h',
'proxy/ppb_message_loop_proxy.cc',
'proxy/ppb_message_loop_proxy.h',
'proxy/ppb_pdf_proxy.cc',
'proxy/ppb_pdf_proxy.h',
'proxy/ppb_tcp_socket_private_proxy.cc',
Expand Down
1 change: 1 addition & 0 deletions ppapi/ppapi_shared.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
'thunk/ppb_instance_thunk.cc',
'thunk/ppb_layer_compositor_api.h',
'thunk/ppb_layer_compositor_thunk.cc',
'thunk/ppb_message_loop_api.h',
'thunk/ppb_messaging_thunk.cc',
'thunk/ppb_mouse_lock_thunk.cc',
'thunk/ppb_pdf_api.h',
Expand Down
2 changes: 2 additions & 0 deletions ppapi/ppapi_sources.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@
'utility/graphics/paint_aggregator.h',
'utility/graphics/paint_manager.cc',
'utility/graphics/paint_manager.h',
'utility/threading/simple_thread.cc',
'utility/threading/simple_thread.h',
],
#
# Common Testing source for trusted and untrusted (NaCl) pugins.
Expand Down
4 changes: 4 additions & 0 deletions ppapi/proxy/interface_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
#include "ppapi/c/dev/ppb_ime_input_event_dev.h"
#include "ppapi/c/dev/ppb_memory_dev.h"
#include "ppapi/c/dev/ppb_message_loop_dev.h"
#include "ppapi/c/dev/ppb_resource_array_dev.h"
#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/c/dev/ppb_text_input_dev.h"
Expand Down Expand Up @@ -80,6 +81,7 @@
#include "ppapi/proxy/ppb_graphics_3d_proxy.h"
#include "ppapi/proxy/ppb_image_data_proxy.h"
#include "ppapi/proxy/ppb_instance_proxy.h"
#include "ppapi/proxy/ppb_message_loop_proxy.h"
#include "ppapi/proxy/ppb_pdf_proxy.h"
#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h"
#include "ppapi/proxy/ppb_testing_proxy.h"
Expand Down Expand Up @@ -169,6 +171,8 @@ InterfaceList::InterfaceList() {
AddProxy(API_ID_PPP_CLASS, &PPP_Class_Proxy::Create);
AddPPB(PPB_CORE_INTERFACE_1_0, API_ID_PPB_CORE,
PPB_Core_Proxy::GetPPB_Core_Interface());
AddPPB(PPB_MESSAGELOOP_DEV_INTERFACE_0_1, API_ID_NONE,
PPB_MessageLoop_Proxy::GetInterface());
AddPPB(PPB_OPENGLES2_INTERFACE_1_0, API_ID_NONE,
PPB_OpenGLES2_Shared::GetInterface());
AddPPB(PPB_VAR_INTERFACE_1_1, API_ID_NONE,
Expand Down
287 changes: 287 additions & 0 deletions ppapi/proxy/ppb_message_loop_proxy.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
// Copyright (c) 2012 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 "ppapi/proxy/ppb_message_loop_proxy.h"

#include <vector>

#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/message_loop.h"
#include "base/threading/thread_local_storage.h"
#include "ppapi/c/dev/ppb_message_loop_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/proxy/plugin_dispatcher.h"
#include "ppapi/shared_impl/resource.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_message_loop_api.h"

using ppapi::thunk::PPB_MessageLoop_API;

namespace ppapi {
namespace proxy {

namespace {

typedef thunk::EnterResource<PPB_MessageLoop_API> EnterMessageLoop;

static base::ThreadLocalStorage::Slot tls_slot(base::LINKER_INITIALIZED);

class MessageLoopResource : public Resource, public PPB_MessageLoop_API {
public:
MessageLoopResource(PP_Instance instance);
virtual ~MessageLoopResource();

// Resource overrides.
virtual PPB_MessageLoop_API* AsPPB_MessageLoop_API() OVERRIDE;

// PPB_MessageLoop_API implementation.
virtual int32_t AttachToCurrentThread() OVERRIDE;
virtual int32_t Run() OVERRIDE;
virtual int32_t PostWork(PP_CompletionCallback callback,
int64_t delay_ms) OVERRIDE;
virtual int32_t PostQuit(PP_Bool should_destroy) OVERRIDE;

void DetachFromThread();

private:
struct TaskInfo {
tracked_objects::Location from_here;
base::Closure closure;
int64 delay_ms;
};

// Returns true if the object is associated with the current thread.
bool IsCurrent() const;

// Handles posting to the message loop if there is one, or the pending queue
// if there isn't.
void PostClosure(const tracked_objects::Location& from_here,
const base::Closure& closure,
int64 delay_ms);

// TLS destructor function.
static void ReleaseMessageLoop(void* value);

// Created when we attach to the current thread, since MessageLoop assumes
// that it's created on the thread it will run on.
scoped_ptr<MessageLoop> loop_;

// Number of invocations of Run currently on the stack.
int nested_invocations_;

// Set to true when the message loop is destroyed to prevent forther
// posting of work.
bool destroyed_;

// Set to true if all message loop invocations should exit and that the
// loop should be destroyed once it reaches the outermost Run invocation.
bool should_destroy_;

// Since we allow tasks to be posted before the message loop is actually
// created (when it's associated with a thread), we keep tasks posted here
// until that happens. Once the loop_ is created, this is unused.
std::vector<TaskInfo> pending_tasks_;

DISALLOW_COPY_AND_ASSIGN(MessageLoopResource);
};

MessageLoopResource::MessageLoopResource(PP_Instance instance)
: Resource(HostResource::MakeInstanceOnly(instance)),
nested_invocations_(0),
destroyed_(false),
should_destroy_(false) {
}

MessageLoopResource::~MessageLoopResource() {
}

PPB_MessageLoop_API* MessageLoopResource::AsPPB_MessageLoop_API() {
return this;
}

int32_t MessageLoopResource::AttachToCurrentThread() {
if (tls_slot.initialized())
return PP_ERROR_INPROGRESS;
// TODO(brettw) check that the current thread can support a message loop.

// Take a ref to the MessageLoop on behalf of the TLS. Note that this is an
// internal ref and not a plugin ref so the plugin can't accidentally
// release it. This is released by ReleaseMessageLoop().
AddRef();
tls_slot.Initialize(&ReleaseMessageLoop);
tls_slot.Set(this);

loop_.reset(new MessageLoop(MessageLoop::TYPE_DEFAULT));

// Post all pending work to the message loop.
for (size_t i = 0; i < pending_tasks_.size(); i++) {
const TaskInfo& info = pending_tasks_[i];
PostClosure(info.from_here, info.closure, info.delay_ms);
}
pending_tasks_.clear();

return PP_OK;
}

int32_t MessageLoopResource::Run() {
if (!IsCurrent())
return PP_ERROR_WRONG_THREAD;
// TODO(brettw) prevent this from happening on the main thread & return
// PP_ERROR_BLOCKS_MAIN_THREAD. Maybe have a special constructor for that
// one?

// TODO(brettw) figure out how to release the lock. Can't run the message
// loop while holding the lock.
nested_invocations_++;
loop_->Run();
nested_invocations_--;

if (should_destroy_ && nested_invocations_ == 0) {
loop_.reset();
destroyed_ = true;
}
return PP_OK;
}

int32_t MessageLoopResource::PostWork(PP_CompletionCallback callback,
int64_t delay_ms) {
if (!callback.func)
return PP_ERROR_BADARGUMENT;
if (destroyed_)
return PP_ERROR_FAILED;
PostClosure(FROM_HERE,
base::Bind(callback.func, callback.user_data,
static_cast<int32_t>(PP_OK)),
delay_ms);
return PP_OK;
}

int32_t MessageLoopResource::PostQuit(PP_Bool should_destroy) {
if (PP_ToBool(should_destroy))
should_destroy_ = true;

if (IsCurrent())
loop_->Quit();
else
PostClosure(FROM_HERE, MessageLoop::QuitClosure(), 0);
return PP_OK;
}

void MessageLoopResource::DetachFromThread() {
// Note that the message loop must be destroyed on the thread is was created
// on.
loop_.reset();

// Cancel out the AddRef in AttachToCurrentThread().
Release();
// DANGER: may delete this.
}

bool MessageLoopResource::IsCurrent() const {
if (!tls_slot.initialized())
return false; // Can't be current if there's nothing in the slot.
return static_cast<const void*>(tls_slot.Get()) ==
static_cast<const void*>(this);
}

void MessageLoopResource::PostClosure(
const tracked_objects::Location& from_here,
const base::Closure& closure,
int64 delay_ms) {
if (loop_.get()) {
loop_->PostDelayedTask(from_here, closure, delay_ms);
} else {
TaskInfo info;
info.from_here = FROM_HERE;
info.closure = closure;
info.delay_ms = delay_ms;
pending_tasks_.push_back(info);
}
}

// static
void MessageLoopResource::ReleaseMessageLoop(void* value) {
static_cast<MessageLoopResource*>(value)->DetachFromThread();
}

// -----------------------------------------------------------------------------

PP_Resource Create(PP_Instance instance) {
// Validate the instance.
PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
if (!dispatcher)
return 0;
return (new MessageLoopResource(instance))->GetReference();
}

PP_Resource GetForMainThread() {
// TODO(brettw).
return 0;
}

PP_Resource GetCurrent() {
if (!tls_slot.initialized())
return 0;
MessageLoopResource* loop = reinterpret_cast<MessageLoopResource*>(
tls_slot.Get());
return loop->GetReference();
}

int32_t AttachToCurrentThread(PP_Resource message_loop) {
EnterMessageLoop enter(message_loop, true);
if (enter.succeeded())
return enter.object()->AttachToCurrentThread();
return PP_ERROR_BADRESOURCE;
}

int32_t Run(PP_Resource message_loop) {
EnterMessageLoop enter(message_loop, true);
if (enter.succeeded())
return enter.object()->Run();
return PP_ERROR_BADRESOURCE;
}

int32_t PostWork(PP_Resource message_loop,
PP_CompletionCallback callback,
int64_t delay_ms) {
EnterMessageLoop enter(message_loop, true);
if (enter.succeeded())
return enter.object()->PostWork(callback, delay_ms);
return PP_ERROR_BADRESOURCE;
}

int32_t PostQuit(PP_Resource message_loop, PP_Bool should_destroy) {
EnterMessageLoop enter(message_loop, true);
if (enter.succeeded())
return enter.object()->PostQuit(should_destroy);
return PP_ERROR_BADRESOURCE;
}

const PPB_MessageLoop_Dev_0_1 ppb_message_loop_interface = {
&Create,
&GetForMainThread,
&GetCurrent,
&AttachToCurrentThread,
&Run,
&PostWork,
&PostQuit
};

} // namespace

PPB_MessageLoop_Proxy::PPB_MessageLoop_Proxy(Dispatcher* dispatcher)
: InterfaceProxy(dispatcher) {
}

PPB_MessageLoop_Proxy::~PPB_MessageLoop_Proxy() {
}

// static
const PPB_MessageLoop_Dev_0_1* PPB_MessageLoop_Proxy::GetInterface() {
return &ppb_message_loop_interface;
}

} // namespace proxy
} // namespace ppapi
30 changes: 30 additions & 0 deletions ppapi/proxy/ppb_message_loop_proxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2012 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.

#ifndef PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_
#define PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_

#include "base/basictypes.h"
#include "ppapi/proxy/interface_proxy.h"

struct PPB_MessageLoop_Dev_0_1;

namespace ppapi {
namespace proxy {

class PPB_MessageLoop_Proxy : public InterfaceProxy {
public:
PPB_MessageLoop_Proxy(Dispatcher* dispatcher);
virtual ~PPB_MessageLoop_Proxy();

static const PPB_MessageLoop_Dev_0_1* GetInterface();

private:
DISALLOW_COPY_AND_ASSIGN(PPB_MessageLoop_Proxy);
};

} // namespace proxy
} // namespace ppapi

#endif // PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_
1 change: 1 addition & 0 deletions ppapi/shared_impl/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
F(PPB_ImageData_API) \
F(PPB_InputEvent_API) \
F(PPB_LayerCompositor_API) \
F(PPB_MessageLoop_API) \
F(PPB_PDFFont_API) \
F(PPB_ResourceArray_API) \
F(PPB_Scrollbar_API) \
Expand Down
Loading

0 comments on commit 15b1224

Please sign in to comment.