Permalink
Browse files

Message pump based on libuv

merge the default message pump with libuv's main loop;
hack the command line so libuv will be happy;
hack the node's Start method
  • Loading branch information...
1 parent 7527adf commit f76430020da1d621fe8b02463a490d5b78af5037 @rogerwang committed with unknown Mar 30, 2012
View
@@ -581,6 +581,7 @@
'../testing/gtest.gyp:gtest_prod',
'../third_party/modp_b64/modp_b64.gyp:modp_b64',
'third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../third_party/libuv/uv.gyp:uv',
],
# TODO(gregoryd): direct_dependent_settings should be shared with the
# 64-bit target, but it doesn't work due to a bug in gyp
@@ -773,6 +774,8 @@
'message_pump_mac.h',
'message_pump_mac.mm',
'message_pump_wayland.h',
+ 'message_pump_uv.h',
+ 'message_pump_uv.cc',
'metrics/field_trial.cc',
'metrics/field_trial.h',
'string16.cc',
View
@@ -209,6 +209,8 @@ CommandLine CommandLine::FromString(const std::wstring& command_line) {
void CommandLine::InitFromArgv(int argc,
const CommandLine::CharType* const* argv) {
+ _argc = argc;
+ _argv = argv;
StringVector new_argv;
for (int i = 0; i < argc; ++i)
new_argv.push_back(argv[i]);
View
@@ -86,6 +86,9 @@ class BASE_EXPORT CommandLine {
// Returns the original command line string as a vector of strings.
const StringVector& argv() const { return argv_; }
+ int argc() const { return _argc; }
+ char** argv_c() const { return (char**)_argv; }
+
// Get and Set the program part of the command line string (the first item).
FilePath GetProgram() const;
void SetProgram(const FilePath& program);
@@ -162,6 +165,9 @@ class BASE_EXPORT CommandLine {
// The index after the program and switches, any arguments start here.
size_t begin_args_;
+
+ int _argc;
+ const CharType* const* _argv;
};
#endif // BASE_COMMAND_LINE_H_
View
@@ -159,13 +159,17 @@ MessageLoop::MessageLoop(Type type)
#error Not implemented
#endif
+#define MESSAGE_PUMP_UV new base::MessagePumpUV()
+
if (type_ == TYPE_UI) {
if (message_pump_for_ui_factory_)
pump_ = message_pump_for_ui_factory_();
else
pump_ = MESSAGE_PUMP_UI;
} else if (type_ == TYPE_IO) {
pump_ = MESSAGE_PUMP_IO;
+ } else if (type_ == TYPE_NODE) {
+ pump_ = MESSAGE_PUMP_UV;
} else {
DCHECK_EQ(TYPE_DEFAULT, type_);
pump_ = new base::MessagePumpDefault();
View
@@ -42,6 +42,8 @@
#endif
#endif
+#include "base/message_pump_uv.h"
+
namespace base {
class Histogram;
}
@@ -101,10 +103,14 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate {
// This type of ML also supports asynchronous IO. See also
// MessageLoopForIO.
//
+ // TYPE_NODE
+ // For integration with NodeJS/libuv in the renderer thread
+
enum Type {
TYPE_DEFAULT,
TYPE_UI,
- TYPE_IO
+ TYPE_IO,
+ TYPE_NODE
};
// Normally, it is not necessary to instantiate a MessageLoop. Instead, it
@@ -670,4 +676,40 @@ class BASE_EXPORT MessageLoopForIO : public MessageLoop {
COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForIO),
MessageLoopForIO_should_not_have_extra_member_variables);
+
+//-----------------------------------------------------------------------------
+// MessageLoopForUV extends MessageLoop with methods that are particular to a
+// MessageLoop instantiated with TYPE_NODE.
+//
+// This class is typically used like so:
+// MessageLoopForUV::current()->...call some method...
+//
+
+class BASE_EXPORT MessageLoopForUV : public MessageLoop {
+ public:
+
+ MessageLoopForUV() : MessageLoop(TYPE_NODE) {
+ }
+
+ // Returns the MessageLoopForUV of the current thread.
+ static MessageLoopForUV* current() {
+ MessageLoop* loop = MessageLoop::current();
+ DCHECK_EQ(MessageLoop::TYPE_NODE, loop->type());
+ return static_cast<MessageLoopForUV*>(loop);
+ }
+
+ protected:
+ base::MessagePumpUV* pump_uv() {
+ return static_cast<base::MessagePumpUV*>(pump_.get());
+ }
+
+};
+
+// Do not add any member variables to MessageLoopForUV! This is important b/c
+// MessageLoopForUV is often allocated via MessageLoop(TYPE_IO). Any extra
+// data that you need should be stored on the MessageLoop's pump_ instance.
+COMPILE_ASSERT(sizeof(MessageLoop) == sizeof(MessageLoopForUV),
+ MessageLoopForUV_should_not_have_extra_member_variables);
+
+
#endif // BASE_MESSAGE_LOOP_H_
View
@@ -0,0 +1,114 @@
+// Copyright (c) 2006-2008 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 "base/message_pump_uv.h"
+
+#include "base/logging.h"
+#include "base/command_line.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif
+
+#include "third_party/libuv/include/uv.h"
+
+#include "third_party/node/src/node.h"
+
+namespace base {
+
+static void async_cb(uv_async_t* handle, int status) {
+}
+
+MessagePumpUV::MessagePumpUV()
+ : keep_running_(true),
+ uv_loop_(uv_default_loop()),
+ wake_up_event_(new uv_async_t){
+ uv_async_init(uv_loop_, wake_up_event_, async_cb);
+}
+
+MessagePumpUV::~MessagePumpUV()
+{
+ delete wake_up_event_;
+}
+
+static void timer_cb (uv_timer_t* timer, int status) {
+ uv_timer_stop(timer);
+}
+
+void MessagePumpUV::Run(Delegate* delegate) {
+ DCHECK(keep_running_) << "Quit must have been called outside of Run!";
+
+ uv_timer_t timer0;
+ int argc = CommandLine::ForCurrentProcess()->argc();
+ char** argv = CommandLine::ForCurrentProcess()->argv_c();
+
+ uv_timer_init(uv_loop_, &timer0);
+ node::Start0(argc, argv);
+ {
+ v8::HandleScope handle_scope;
+ node::Start(argc, argv);
+
+ for (;;) {
+#if defined(OS_MACOSX)
+ mac::ScopedNSAutoreleasePool autorelease_pool;
+#endif
+
+ bool did_work = delegate->DoWork();
+ if (!keep_running_)
+ break;
+
+ did_work |= delegate->DoDelayedWork(&delayed_work_time_);
+ if (!keep_running_)
+ break;
+
+ if (did_work)
+ continue;
+
+ did_work = delegate->DoIdleWork();
+ if (!keep_running_)
+ break;
+
+ if (did_work)
+ continue;
+
+ if (delayed_work_time_.is_null()) {
+ uv_run_once(uv_loop_);
+ } else {
+ TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
+ if (delay > TimeDelta()) {
+ uv_timer_start(&timer0, (uv_timer_cb) &timer_cb,
+ delay.InMilliseconds(), 0);
+ uv_run_once(uv_loop_);
+ } else {
+ // It looks like delayed_work_time_ indicates a time in the past, so we
+ // need to call DoDelayedWork now.
+ delayed_work_time_ = TimeTicks();
+ }
+ }
+ // Since event_ is auto-reset, we don't need to do anything special here
+ // other than service each delegate method.
+ }
+ }
+ keep_running_ = true;
+}
+
+void MessagePumpUV::Quit() {
+ keep_running_ = false;
+}
+
+void MessagePumpUV::ScheduleWork() {
+ // Since this can be called on any thread, we need to ensure that our Run
+ // loop wakes up.
+ uv_async_send(wake_up_event_);
+}
+
+void MessagePumpUV::ScheduleDelayedWork(
+ const TimeTicks& delayed_work_time) {
+ // We know that we can't be blocked on Wait right now since this method can
+ // only be called on the same thread as Run, so we only need to update our
+ // record of how long to sleep when we do sleep.
+ delayed_work_time_ = delayed_work_time;
+}
+
+} // namespace base
View
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef BASE_MESSAGE_PUMP_UV_H_
+#define BASE_MESSAGE_PUMP_UV_H_
+#pragma once
+
+#include "base/message_pump.h"
+#include "base/time.h"
+#include "base/base_export.h"
+
+struct uv_loop_s;
+struct uv_async_s;
+
+namespace base {
+
+class BASE_EXPORT MessagePumpUV : public MessagePump {
+ public:
+ MessagePumpUV();
+ virtual ~MessagePumpUV();
+
+ // MessagePump methods:
+ virtual void Run(Delegate* delegate) OVERRIDE;
+ virtual void Quit() OVERRIDE;
+ virtual void ScheduleWork() OVERRIDE;
+ virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE;
+
+ private:
+ // This flag is set to false when Run should return.
+ bool keep_running_;
+
+ struct uv_loop_s* uv_loop_;
+
+ struct uv_async_s* wake_up_event_;
+
+ // The time at which we should call DoDelayedWork.
+ TimeTicks delayed_work_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessagePumpUV);
+};
+
+} // namespace base
+
+#endif // BASE_MESSAGE_PUMP_UV_H_
View
@@ -30,7 +30,7 @@
'use_ash%': 0,
# Use OpenSSL instead of NSS. Under development: see http://crbug.com/62803
- 'use_openssl%': 0,
+ 'use_openssl%': 1,
# Disable Virtual keyboard support by default.
'use_virtual_keyboard%': 0,
View
@@ -98,7 +98,17 @@
{
'target_name': 'ssl',
'type': 'none',
+ 'toolsets': [ 'host', 'target'],
'conditions': [
+ ['_toolset=="host"', {
+ 'conditions': [
+ ['use_openssl==1', {
+ 'dependencies': [
+ '../../third_party/openssl/openssl.gyp:openssl',
+ ],
+ }],
+ ],
+ }],
['_toolset=="target"', {
'conditions': [
['use_openssl==1', {
@@ -487,7 +487,7 @@ class ContentMainRunnerImpl : public content::ContentMainRunner {
delegate->SandboxInitialized(process_type);
#if defined(OS_POSIX)
- SetProcessTitleFromCommandLine(argv);
+ // SetProcessTitleFromCommandLine(argv);
#endif
// Return -1 to indicate no early termination.
@@ -174,7 +174,7 @@ int RendererMain(const content::MainFunctionParams& parameters) {
// The main message loop of the renderer services doesn't have IO or UI tasks,
// unless in-process-plugins is used.
MessageLoop main_message_loop(RenderProcessImpl::InProcessPlugins() ?
- MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT);
+ MessageLoop::TYPE_UI : MessageLoop::TYPE_NODE);
#endif
main_message_loop.AddTaskObserver(&task_observer);
@@ -21,6 +21,7 @@
{
'target_name': 'zlib',
'type': 'static_library',
+ 'toolsets': [ 'host', 'target' ],
'sources': [
'contrib/minizip/ioapi.c',
'contrib/minizip/ioapi.h',
@@ -98,6 +99,7 @@
{
'target_name': 'zlib',
'type': 'static_library',
+ 'toolsets': [ 'host', 'target'],
'direct_dependent_settings': {
'defines': [
'USE_SYSTEM_ZLIB',

0 comments on commit f764300

Please sign in to comment.