Commit d55d3ce8 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Add DebugMessageDispatchHandler

A callback on the debugger thread when a message is received. Allows the 
embedding application to wake up the main thread in order to handle the 
message. Useful when the embedding application is idle and sitting in a 
select() call.

Patch by Ryan Dahl <coldredlemur@gmail.com>

Review URL: http://codereview.chromium.org/395013


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3326 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d5c355e3
......@@ -188,6 +188,11 @@ class EXPORT Debug {
*/
typedef void (*HostDispatchHandler)();
/**
* Callback function for the host to ensure debug messages are processed.
*/
typedef void (*DebugMessageDispatchHandler)();
// Set a C debug event listener.
static bool SetDebugEventListener(EventCallback that,
Handle<Value> data = Handle<Value>());
......@@ -211,6 +216,18 @@ class EXPORT Debug {
static void SetHostDispatchHandler(HostDispatchHandler handler,
int period = 100);
/**
* Register a callback function to be called when a debug message has been
* received and is ready to be processed. For the debug messages to be
* processed V8 needs to be entered, and in certain embedding scenarios this
* callback can be used to make sure V8 is entered for the debug message to
* be processed. Note that debug messages will only be processed if there is
* a V8 break. This can happen automatically by using the option
* --debugger-auto-break.
*/
static void SetDebugMessageDispatchHandler(
DebugMessageDispatchHandler handler);
/**
* Run a JavaScript function in the debugger.
* \param fun the function to call
......
......@@ -3734,6 +3734,14 @@ void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
}
void Debug::SetDebugMessageDispatchHandler(
DebugMessageDispatchHandler handler) {
EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
ENTER_V8;
i::Debugger::SetDebugMessageDispatchHandler(handler);
}
Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
v8::Handle<v8::Value> data) {
if (!i::V8::IsRunning()) return Local<Value>();
......
......@@ -1759,6 +1759,8 @@ bool Debugger::never_unload_debugger_ = false;
v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL;
bool Debugger::debugger_unload_pending_ = false;
v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
v8::Debug::DebugMessageDispatchHandler
Debugger::debug_message_dispatch_handler_ = NULL;
int Debugger::host_dispatch_micros_ = 100 * 1000;
DebuggerAgent* Debugger::agent_ = NULL;
LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize);
......@@ -2399,6 +2401,12 @@ void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
}
void Debugger::SetDebugMessageDispatchHandler(
v8::Debug::DebugMessageDispatchHandler handler) {
debug_message_dispatch_handler_ = handler;
}
// Calls the registered debug message handler. This callback is part of the
// public API.
void Debugger::InvokeMessageHandler(MessageImpl message) {
......@@ -2429,6 +2437,10 @@ void Debugger::ProcessCommand(Vector<const uint16_t> command,
if (!Debug::InDebugger()) {
StackGuard::DebugCommand();
}
if (Debugger::debug_message_dispatch_handler_ != NULL) {
Debugger::debug_message_dispatch_handler_();
}
}
......
......@@ -629,6 +629,8 @@ class Debugger {
static void SetMessageHandler(v8::Debug::MessageHandler2 handler);
static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
int period);
static void SetDebugMessageDispatchHandler(
v8::Debug::DebugMessageDispatchHandler handler);
// Invoke the message handler function.
static void InvokeMessageHandler(MessageImpl message);
......@@ -689,6 +691,7 @@ class Debugger {
static v8::Debug::MessageHandler2 message_handler_;
static bool debugger_unload_pending_; // Was message handler cleared?
static v8::Debug::HostDispatchHandler host_dispatch_handler_;
static v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
static int host_dispatch_micros_;
static DebuggerAgent* agent_;
......
......@@ -4691,6 +4691,71 @@ TEST(DebuggerHostDispatch) {
}
/* Test DebugMessageDispatch */
/* In this test, the V8 thread waits for a message from the debug thread.
* The DebugMessageDispatchHandler is executed from the debugger thread
* which signals the V8 thread to wake up.
*/
class DebugMessageDispatchV8Thread : public v8::internal::Thread {
public:
void Run();
};
class DebugMessageDispatchDebuggerThread : public v8::internal::Thread {
public:
void Run();
};
Barriers* debug_message_dispatch_barriers;
static void DebugMessageHandler() {
debug_message_dispatch_barriers->semaphore_1->Signal();
}
void DebugMessageDispatchV8Thread::Run() {
v8::HandleScope scope;
DebugLocalContext env;
// Setup debug message dispatch handler.
v8::Debug::SetDebugMessageDispatchHandler(DebugMessageHandler);
CompileRun("var y = 1 + 2;\n");
debug_message_dispatch_barriers->barrier_1.Wait();
debug_message_dispatch_barriers->semaphore_1->Wait();
debug_message_dispatch_barriers->barrier_2.Wait();
}
void DebugMessageDispatchDebuggerThread::Run() {
debug_message_dispatch_barriers->barrier_1.Wait();
SendContinueCommand();
debug_message_dispatch_barriers->barrier_2.Wait();
}
DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread;
DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread;
TEST(DebuggerDebugMessageDispatch) {
i::FLAG_debugger_auto_break = true;
// Create a V8 environment
Barriers stack_allocated_debug_message_dispatch_barriers;
stack_allocated_debug_message_dispatch_barriers.Initialize();
debug_message_dispatch_barriers =
&stack_allocated_debug_message_dispatch_barriers;
debug_message_dispatch_v8_thread.Start();
debug_message_dispatch_debugger_thread.Start();
debug_message_dispatch_v8_thread.Join();
debug_message_dispatch_debugger_thread.Join();
}
TEST(DebuggerAgent) {
// Make sure these ports is not used by other tests to allow tests to run in
// parallel.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment