Batch of ev -> uv changes
This commit is contained in:
parent
207901e7de
commit
9cec08e490
135
src/node.cc
135
src/node.cc
@ -27,6 +27,7 @@
|
|||||||
#include <node_dtrace.h>
|
#include <node_dtrace.h>
|
||||||
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
@ -119,9 +120,9 @@ static uv_handle_t tick_spinner;
|
|||||||
static bool need_tick_cb;
|
static bool need_tick_cb;
|
||||||
static Persistent<String> tick_callback_sym;
|
static Persistent<String> tick_callback_sym;
|
||||||
|
|
||||||
static ev_async eio_want_poll_notifier;
|
static uv_handle_t eio_want_poll_notifier;
|
||||||
static ev_async eio_done_poll_notifier;
|
static uv_handle_t eio_done_poll_notifier;
|
||||||
static ev_idle eio_poller;
|
static uv_handle_t eio_poller;
|
||||||
|
|
||||||
// Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
|
// Buffer for getpwnam_r(), getgrpam_r() and other misc callers; keep this
|
||||||
// scoped at file-level rather than method-level to avoid excess stack usage.
|
// scoped at file-level rather than method-level to avoid excess stack usage.
|
||||||
@ -134,9 +135,9 @@ static char getbuf[PATH_MAX + 1];
|
|||||||
//
|
//
|
||||||
// A rather convoluted algorithm has been devised to determine when Node is
|
// A rather convoluted algorithm has been devised to determine when Node is
|
||||||
// idle. You'll have to figure it out for yourself.
|
// idle. You'll have to figure it out for yourself.
|
||||||
static ev_check gc_check;
|
static uv_handle_t gc_check;
|
||||||
static ev_idle gc_idle;
|
static uv_handle_t gc_idle;
|
||||||
static ev_timer gc_timer;
|
static uv_handle_t gc_timer;
|
||||||
bool need_gc;
|
bool need_gc;
|
||||||
|
|
||||||
|
|
||||||
@ -144,42 +145,40 @@ bool need_gc;
|
|||||||
#define GC_WAIT_TIME 5.
|
#define GC_WAIT_TIME 5.
|
||||||
#define RPM_SAMPLES 100
|
#define RPM_SAMPLES 100
|
||||||
#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
|
#define TICK_TIME(n) tick_times[(tick_time_head - (n)) % RPM_SAMPLES]
|
||||||
static ev_tstamp tick_times[RPM_SAMPLES];
|
static int64_t tick_times[RPM_SAMPLES];
|
||||||
static int tick_time_head;
|
static int tick_time_head;
|
||||||
|
|
||||||
|
static void CheckStatus(uv_handle_t* watcher, int status);
|
||||||
|
|
||||||
static void StartGCTimer () {
|
static void StartGCTimer () {
|
||||||
if (!ev_is_active(&gc_timer)) {
|
if (!uv_is_active(&gc_timer)) {
|
||||||
ev_timer_start(EV_DEFAULT_UC_ &gc_timer);
|
uv_timer_start(&node::gc_timer, node::CheckStatus, 5., 5.);
|
||||||
ev_unref(EV_DEFAULT_UC);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void StopGCTimer () {
|
static void StopGCTimer () {
|
||||||
if (ev_is_active(&gc_timer)) {
|
if (uv_is_active(&gc_timer)) {
|
||||||
ev_ref(EV_DEFAULT_UC);
|
uv_timer_stop(&gc_timer);
|
||||||
ev_timer_stop(EV_DEFAULT_UC_ &gc_timer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Idle(EV_P_ ev_idle *watcher, int revents) {
|
static void Idle(uv_handle_t* watcher, int status) {
|
||||||
assert(watcher == &gc_idle);
|
assert(watcher == &gc_idle);
|
||||||
assert(revents == EV_IDLE);
|
|
||||||
|
|
||||||
//fprintf(stderr, "idle\n");
|
//fprintf(stderr, "idle\n");
|
||||||
|
|
||||||
if (V8::IdleNotification()) {
|
if (V8::IdleNotification()) {
|
||||||
ev_idle_stop(EV_A_ watcher);
|
uv_idle_stop(watcher);
|
||||||
StopGCTimer();
|
StopGCTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Called directly after every call to select() (or epoll, or whatever)
|
// Called directly after every call to select() (or epoll, or whatever)
|
||||||
static void Check(EV_P_ ev_check *watcher, int revents) {
|
static void Check(uv_handle_t* watcher, int status) {
|
||||||
assert(watcher == &gc_check);
|
assert(watcher == &gc_check);
|
||||||
assert(revents == EV_CHECK);
|
|
||||||
|
|
||||||
tick_times[tick_time_head] = ev_now(EV_DEFAULT_UC);
|
tick_times[tick_time_head] = uv_now();
|
||||||
tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
|
tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;
|
||||||
|
|
||||||
StartGCTimer();
|
StartGCTimer();
|
||||||
@ -198,7 +197,7 @@ static void Check(EV_P_ ev_check *watcher, int revents) {
|
|||||||
// Otherwise start the gc!
|
// Otherwise start the gc!
|
||||||
|
|
||||||
//fprintf(stderr, "start idle 2\n");
|
//fprintf(stderr, "start idle 2\n");
|
||||||
ev_idle_start(EV_A_ &gc_idle);
|
uv_idle_start(&node::gc_idle, node::Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -270,42 +269,42 @@ static void CheckTick(uv_handle_t* handle, int status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void DoPoll(EV_P_ ev_idle *watcher, int revents) {
|
static void DoPoll(uv_handle_t* watcher, int status) {
|
||||||
assert(watcher == &eio_poller);
|
assert(watcher == &eio_poller);
|
||||||
assert(revents == EV_IDLE);
|
|
||||||
|
|
||||||
//printf("eio_poller\n");
|
//printf("eio_poller\n");
|
||||||
|
|
||||||
if (eio_poll() != -1) {
|
if (eio_poll() != -1 && uv_is_active(&eio_poller)) {
|
||||||
//printf("eio_poller stop\n");
|
//printf("eio_poller stop\n");
|
||||||
ev_idle_stop(EV_DEFAULT_UC_ watcher);
|
uv_idle_stop(watcher);
|
||||||
|
uv_unref();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Called from the main thread.
|
// Called from the main thread.
|
||||||
static void WantPollNotifier(EV_P_ ev_async *watcher, int revents) {
|
static void WantPollNotifier(uv_handle_t* watcher, int status) {
|
||||||
assert(watcher == &eio_want_poll_notifier);
|
assert(watcher == &eio_want_poll_notifier);
|
||||||
assert(revents == EV_ASYNC);
|
|
||||||
|
|
||||||
//printf("want poll notifier\n");
|
//printf("want poll notifier\n");
|
||||||
|
|
||||||
if (eio_poll() == -1) {
|
if (eio_poll() == -1 && !uv_is_active(&eio_poller)) {
|
||||||
//printf("eio_poller start\n");
|
//printf("eio_poller start\n");
|
||||||
ev_idle_start(EV_DEFAULT_UC_ &eio_poller);
|
uv_idle_start(&eio_poller, node::DoPoll);
|
||||||
|
uv_ref();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void DonePollNotifier(EV_P_ ev_async *watcher, int revents) {
|
static void DonePollNotifier(uv_handle_t* watcher, int revents) {
|
||||||
assert(watcher == &eio_done_poll_notifier);
|
assert(watcher == &eio_done_poll_notifier);
|
||||||
assert(revents == EV_ASYNC);
|
|
||||||
|
|
||||||
//printf("done poll notifier\n");
|
//printf("done poll notifier\n");
|
||||||
|
|
||||||
if (eio_poll() != -1) {
|
if (eio_poll() != -1 && uv_is_active(&eio_poller)) {
|
||||||
//printf("eio_poller stop\n");
|
//printf("eio_poller stop\n");
|
||||||
ev_idle_stop(EV_DEFAULT_UC_ &eio_poller);
|
uv_idle_stop(&eio_poller);
|
||||||
|
uv_unref();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,14 +313,14 @@ static void DonePollNotifier(EV_P_ ev_async *watcher, int revents) {
|
|||||||
// request (that is, one of the node.fs.* functions) has completed.
|
// request (that is, one of the node.fs.* functions) has completed.
|
||||||
static void EIOWantPoll(void) {
|
static void EIOWantPoll(void) {
|
||||||
// Signal the main thread that eio_poll need to be processed.
|
// Signal the main thread that eio_poll need to be processed.
|
||||||
ev_async_send(EV_DEFAULT_UC_ &eio_want_poll_notifier);
|
uv_async_send(&eio_want_poll_notifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void EIODonePoll(void) {
|
static void EIODonePoll(void) {
|
||||||
// Signal the main thread that we should stop calling eio_poll().
|
// Signal the main thread that we should stop calling eio_poll().
|
||||||
// from the idle watcher.
|
// from the idle watcher.
|
||||||
ev_async_send(EV_DEFAULT_UC_ &eio_done_poll_notifier);
|
uv_async_send(&eio_done_poll_notifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1508,28 +1507,27 @@ v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void CheckStatus(EV_P_ ev_timer *watcher, int revents) {
|
static void CheckStatus(uv_handle_t* watcher, int status) {
|
||||||
assert(watcher == &gc_timer);
|
assert(watcher == &gc_timer);
|
||||||
assert(revents == EV_TIMEOUT);
|
|
||||||
|
|
||||||
// check memory
|
// check memory
|
||||||
if (!ev_is_active(&gc_idle)) {
|
if (!uv_is_active(&gc_idle)) {
|
||||||
HeapStatistics stats;
|
HeapStatistics stats;
|
||||||
V8::GetHeapStatistics(&stats);
|
V8::GetHeapStatistics(&stats);
|
||||||
if (stats.total_heap_size() > 1024 * 1024 * 128) {
|
if (stats.total_heap_size() > 1024 * 1024 * 128) {
|
||||||
// larger than 128 megs, just start the idle watcher
|
// larger than 128 megs, just start the idle watcher
|
||||||
ev_idle_start(EV_A_ &gc_idle);
|
uv_idle_start(&node::gc_idle, node::Idle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double d = ev_now(EV_DEFAULT_UC) - TICK_TIME(3);
|
double d = uv_now() - TICK_TIME(3);
|
||||||
|
|
||||||
//printfb("timer d = %f\n", d);
|
//printfb("timer d = %f\n", d);
|
||||||
|
|
||||||
if (d >= GC_WAIT_TIME - 1.) {
|
if (d >= GC_WAIT_TIME - 1.) {
|
||||||
//fprintf(stderr, "start idle\n");
|
//fprintf(stderr, "start idle\n");
|
||||||
ev_idle_start(EV_A_ &gc_idle);
|
uv_idle_start(&node::gc_idle, node::Idle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1784,12 +1782,11 @@ void FatalException(TryCatch &try_catch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ev_async debug_watcher;
|
static uv_handle_t debug_watcher;
|
||||||
|
|
||||||
static void DebugMessageCallback(EV_P_ ev_async *watcher, int revents) {
|
static void DebugMessageCallback(uv_handle_t* watcher, int status) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
assert(watcher == &debug_watcher);
|
assert(watcher == &debug_watcher);
|
||||||
assert(revents == EV_ASYNC);
|
|
||||||
Debug::ProcessDebugMessages();
|
Debug::ProcessDebugMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1799,7 +1796,7 @@ static void DebugMessageDispatch(void) {
|
|||||||
|
|
||||||
// Send a signal to our main thread saying that it should enter V8 to
|
// Send a signal to our main thread saying that it should enter V8 to
|
||||||
// handle the message.
|
// handle the message.
|
||||||
ev_async_send(EV_DEFAULT_UC_ &debug_watcher);
|
uv_async_send(&debug_watcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DebugBreakMessageHandler(const Debug::Message& message) {
|
static void DebugBreakMessageHandler(const Debug::Message& message) {
|
||||||
@ -1989,8 +1986,8 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
|
|||||||
versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
|
versions->Set(String::NewSymbol("node"), String::New(NODE_VERSION+1));
|
||||||
versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
|
versions->Set(String::NewSymbol("v8"), String::New(V8::GetVersion()));
|
||||||
versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
|
versions->Set(String::NewSymbol("ares"), String::New(ARES_VERSION_STR));
|
||||||
snprintf(buf, 20, "%d.%d", ev_version_major(), ev_version_minor());
|
snprintf(buf, 20, "%d.%d", UV_VERSION_MAJOR, UV_VERSION_MINOR);
|
||||||
versions->Set(String::NewSymbol("ev"), String::New(buf));
|
versions->Set(String::NewSymbol("uv"), String::New(buf));
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
// Stupid code to slice out the version string.
|
// Stupid code to slice out the version string.
|
||||||
int c, l = strlen(OPENSSL_VERSION_TEXT);
|
int c, l = strlen(OPENSSL_VERSION_TEXT);
|
||||||
@ -2365,28 +2362,26 @@ char** Init(int argc, char *argv[]) {
|
|||||||
uv_idle_init(&node::tick_spinner, NULL, NULL);
|
uv_idle_init(&node::tick_spinner, NULL, NULL);
|
||||||
uv_unref();
|
uv_unref();
|
||||||
|
|
||||||
ev_check_init(&node::gc_check, node::Check);
|
uv_check_init(&node::gc_check, NULL, NULL);
|
||||||
ev_check_start(EV_DEFAULT_UC_ &node::gc_check);
|
uv_check_start(&node::gc_check, node::Check);
|
||||||
ev_unref(EV_DEFAULT_UC);
|
uv_unref();
|
||||||
|
|
||||||
ev_idle_init(&node::gc_idle, node::Idle);
|
uv_idle_init(&node::gc_idle, NULL, NULL);
|
||||||
ev_timer_init(&node::gc_timer, node::CheckStatus, 5., 5.);
|
uv_unref();
|
||||||
|
|
||||||
|
uv_timer_init(&node::gc_timer, NULL, NULL);
|
||||||
|
uv_unref();
|
||||||
|
|
||||||
// Setup the EIO thread pool. It requires 3, yes 3, watchers.
|
// Setup the EIO thread pool. It requires 3, yes 3, watchers.
|
||||||
{
|
{
|
||||||
ev_idle_init(&node::eio_poller, node::DoPoll);
|
uv_idle_init(&node::eio_poller, NULL, NULL);
|
||||||
// TODO Probably don't need to start this each time.
|
uv_idle_start(&eio_poller, node::DoPoll);
|
||||||
// Avoids failing on test/simple/test-eio-race3.js though
|
|
||||||
ev_idle_start(EV_DEFAULT_UC_ &eio_poller);
|
|
||||||
|
|
||||||
ev_async_init(&node::eio_want_poll_notifier, node::WantPollNotifier);
|
uv_async_init(&node::eio_want_poll_notifier, node::WantPollNotifier, NULL, NULL);
|
||||||
ev_async_start(EV_DEFAULT_UC_ &node::eio_want_poll_notifier);
|
uv_unref();
|
||||||
ev_unref(EV_DEFAULT_UC);
|
|
||||||
|
|
||||||
ev_async_init(&node::eio_done_poll_notifier, node::DonePollNotifier);
|
uv_async_init(&node::eio_done_poll_notifier, node::DonePollNotifier, NULL, NULL);
|
||||||
ev_async_start(EV_DEFAULT_UC_ &node::eio_done_poll_notifier);
|
uv_unref();
|
||||||
ev_unref(EV_DEFAULT_UC);
|
|
||||||
|
|
||||||
eio_init(node::EIOWantPoll, node::EIODonePoll);
|
eio_init(node::EIOWantPoll, node::EIODonePoll);
|
||||||
// Don't handle more than 10 reqs on each eio_poll(). This is to avoid
|
// Don't handle more than 10 reqs on each eio_poll(). This is to avoid
|
||||||
@ -2397,20 +2392,16 @@ char** Init(int argc, char *argv[]) {
|
|||||||
V8::SetFatalErrorHandler(node::OnFatalError);
|
V8::SetFatalErrorHandler(node::OnFatalError);
|
||||||
|
|
||||||
|
|
||||||
// Initialize the async watcher for receiving messages from the debug
|
|
||||||
// thread and marshal it into the main thread. DebugMessageCallback()
|
|
||||||
// is called from the main thread to execute a random bit of javascript
|
|
||||||
// - which will give V8 control so it can handle whatever new message
|
|
||||||
// had been received on the debug thread.
|
|
||||||
ev_async_init(&node::debug_watcher, node::DebugMessageCallback);
|
|
||||||
ev_set_priority(&node::debug_watcher, EV_MAXPRI);
|
|
||||||
// Set the callback DebugMessageDispatch which is called from the debug
|
// Set the callback DebugMessageDispatch which is called from the debug
|
||||||
// thread.
|
// thread.
|
||||||
Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
|
Debug::SetDebugMessageDispatchHandler(node::DebugMessageDispatch);
|
||||||
// Start the async watcher.
|
// Initialize the async watcher. DebugMessageCallback() is called from the
|
||||||
ev_async_start(EV_DEFAULT_UC_ &node::debug_watcher);
|
// main thread to execute a random bit of javascript - which will give V8
|
||||||
|
// control so it can handle whatever new message had been received on the
|
||||||
|
// debug thread.
|
||||||
|
uv_async_init(&node::debug_watcher, node::DebugMessageCallback, NULL, NULL);
|
||||||
// unref it so that we exit the event loop despite it being active.
|
// unref it so that we exit the event loop despite it being active.
|
||||||
ev_unref(EV_DEFAULT_UC);
|
uv_unref();
|
||||||
|
|
||||||
|
|
||||||
// If the --debug flag was specified then initialize the debug thread.
|
// If the --debug flag was specified then initialize the debug thread.
|
||||||
@ -2470,7 +2461,7 @@ int Start(int argc, char *argv[]) {
|
|||||||
// All our arguments are loaded. We've evaluated all of the scripts. We
|
// All our arguments are loaded. We've evaluated all of the scripts. We
|
||||||
// might even have created TCP servers. Now we enter the main eventloop. If
|
// might even have created TCP servers. Now we enter the main eventloop. If
|
||||||
// there are no watchers on the loop (except for the ones that were
|
// there are no watchers on the loop (except for the ones that were
|
||||||
// ev_unref'd) then this function exits. As long as there are active
|
// uv_unref'd) then this function exits. As long as there are active
|
||||||
// watchers, it blocks.
|
// watchers, it blocks.
|
||||||
uv_run();
|
uv_run();
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#ifndef SRC_NODE_H_
|
#ifndef SRC_NODE_H_
|
||||||
#define SRC_NODE_H_
|
#define SRC_NODE_H_
|
||||||
|
|
||||||
#include <ev.h>
|
#include <uv.h>
|
||||||
#include <eio.h>
|
#include <eio.h>
|
||||||
#include <v8.h>
|
#include <v8.h>
|
||||||
#include <sys/types.h> /* struct stat */
|
#include <sys/types.h> /* struct stat */
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include <node_constants.h>
|
#include <node_constants.h>
|
||||||
|
|
||||||
#include <ev.h>
|
#include <uv.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -44,9 +44,6 @@ namespace node {
|
|||||||
using namespace v8;
|
using namespace v8;
|
||||||
|
|
||||||
void DefineConstants(Handle<Object> target) {
|
void DefineConstants(Handle<Object> target) {
|
||||||
NODE_DEFINE_CONSTANT(target, EV_MINPRI);
|
|
||||||
NODE_DEFINE_CONSTANT(target, EV_MAXPRI);
|
|
||||||
|
|
||||||
// file access modes
|
// file access modes
|
||||||
NODE_DEFINE_CONSTANT(target, O_RDONLY);
|
NODE_DEFINE_CONSTANT(target, O_RDONLY);
|
||||||
NODE_DEFINE_CONSTANT(target, O_WRONLY);
|
NODE_DEFINE_CONSTANT(target, O_WRONLY);
|
||||||
|
@ -88,7 +88,7 @@ static int After(eio_req *req) {
|
|||||||
|
|
||||||
Persistent<Function> *callback = cb_unwrap(req->data);
|
Persistent<Function> *callback = cb_unwrap(req->data);
|
||||||
|
|
||||||
ev_unref(EV_DEFAULT_UC);
|
uv_unref();
|
||||||
|
|
||||||
// there is always at least one argument. "error"
|
// there is always at least one argument. "error"
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
@ -213,7 +213,7 @@ static int After(eio_req *req) {
|
|||||||
eio_req *req = eio_##func(__VA_ARGS__, EIO_PRI_DEFAULT, After, \
|
eio_req *req = eio_##func(__VA_ARGS__, EIO_PRI_DEFAULT, After, \
|
||||||
cb_persist(callback)); \
|
cb_persist(callback)); \
|
||||||
assert(req); \
|
assert(req); \
|
||||||
ev_ref(EV_DEFAULT_UC); \
|
uv_ref(); \
|
||||||
return Undefined();
|
return Undefined();
|
||||||
|
|
||||||
static Handle<Value> Close(const Arguments& args) {
|
static Handle<Value> Close(const Arguments& args) {
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include <node.h>
|
#include <node.h>
|
||||||
#include <node_object_wrap.h>
|
#include <node_object_wrap.h>
|
||||||
#include <v8.h>
|
#include <v8.h>
|
||||||
#include <ev.h>
|
#include <uv.h>
|
||||||
|
|
||||||
namespace node {
|
namespace node {
|
||||||
|
|
||||||
|
@ -415,18 +415,19 @@ static Handle<Value> ClearLine(const Arguments& args) {
|
|||||||
|
|
||||||
|
|
||||||
/* TTY watcher data */
|
/* TTY watcher data */
|
||||||
bool tty_watcher_initialized = false;
|
|
||||||
HANDLE tty_handle;
|
HANDLE tty_handle;
|
||||||
HANDLE tty_wait_handle;
|
HANDLE tty_wait_handle;
|
||||||
void *tty_error_callback;
|
void *tty_error_callback;
|
||||||
void *tty_keypress_callback;
|
void *tty_keypress_callback;
|
||||||
void *tty_resize_callback;
|
void *tty_resize_callback;
|
||||||
static ev_async tty_avail_notifier;
|
static bool tty_watcher_initialized = false;
|
||||||
|
static bool tty_watcher_active = false;
|
||||||
|
static uv_handle_t tty_avail_notifier;
|
||||||
|
|
||||||
|
|
||||||
static void CALLBACK tty_want_poll(void *context, BOOLEAN didTimeout) {
|
static void CALLBACK tty_want_poll(void *context, BOOLEAN didTimeout) {
|
||||||
assert(!didTimeout);
|
assert(!didTimeout);
|
||||||
ev_async_send(EV_DEFAULT_UC_ &tty_avail_notifier);
|
uv_async_send(&tty_avail_notifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -437,12 +438,13 @@ static void tty_watcher_arm() {
|
|||||||
// but apparently this does not apply to wait threads. Sigh.
|
// but apparently this does not apply to wait threads. Sigh.
|
||||||
|
|
||||||
HANDLE old_wait_handle = tty_wait_handle;
|
HANDLE old_wait_handle = tty_wait_handle;
|
||||||
tty_wait_handle = NULL;
|
tty_wait_handle = NULL;
|
||||||
|
|
||||||
|
assert(tty_watcher_active);
|
||||||
|
|
||||||
if (ev_is_active(&tty_avail_notifier)) {
|
if (!RegisterWaitForSingleObject(&tty_wait_handle, tty_handle, tty_want_poll, NULL,
|
||||||
if (!RegisterWaitForSingleObject(&tty_wait_handle, tty_handle, tty_want_poll, NULL,
|
INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) {
|
||||||
INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE))
|
ThrowException(ErrnoException(GetLastError(), "RegisterWaitForSingleObject"));
|
||||||
ThrowException(ErrnoException(GetLastError(), "RegisterWaitForSingleObject"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_wait_handle != NULL) {
|
if (old_wait_handle != NULL) {
|
||||||
@ -463,18 +465,19 @@ static void tty_watcher_disarm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void tty_watcher_start() {
|
static void tty_watcher_start() {
|
||||||
if (!ev_is_active(&tty_avail_notifier)) {
|
assert(tty_watcher_initialized);
|
||||||
ev_async_start(EV_DEFAULT_UC_ &tty_avail_notifier);
|
if (!tty_watcher_active) {
|
||||||
|
tty_watcher_active = true;
|
||||||
tty_watcher_arm();
|
tty_watcher_arm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void tty_watcher_stop() {
|
static void tty_watcher_stop() {
|
||||||
if (ev_is_active(&tty_avail_notifier)) {
|
if (tty_watcher_active) {
|
||||||
|
tty_watcher_active = false;
|
||||||
tty_watcher_disarm();
|
tty_watcher_disarm();
|
||||||
ev_async_stop(EV_DEFAULT_UC_ &tty_avail_notifier);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,9 +491,9 @@ static inline void tty_emit_error(Handle<Value> err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void tty_poll(EV_P_ ev_async *watcher, int revents) {
|
static void tty_poll(uv_handle_t* handle, int status) {
|
||||||
assert(watcher == &tty_avail_notifier);
|
assert(handle == &tty_avail_notifier);
|
||||||
assert(revents == EV_ASYNC);
|
assert(status == 0);
|
||||||
|
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
TryCatch try_catch;
|
TryCatch try_catch;
|
||||||
@ -509,8 +512,8 @@ static void tty_poll(EV_P_ ev_async *watcher, int revents) {
|
|||||||
numev = 0;
|
numev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = numev; i > 0 &&
|
for (i = numev; i > 0 &&
|
||||||
ev_is_active(EV_DEFAULT_UC_ &tty_avail_notifier); i--) {
|
tty_watcher_active; i--) {
|
||||||
if (!ReadConsoleInputW(tty_handle, &input, 1, &read)) {
|
if (!ReadConsoleInputW(tty_handle, &input, 1, &read)) {
|
||||||
tty_emit_error(ErrnoException(GetLastError(), "ReadConsoleInputW"));
|
tty_emit_error(ErrnoException(GetLastError(), "ReadConsoleInputW"));
|
||||||
break;
|
break;
|
||||||
@ -561,7 +564,7 @@ static void tty_poll(EV_P_ ev_async *watcher, int revents) {
|
|||||||
j = k.wRepeatCount;
|
j = k.wRepeatCount;
|
||||||
do {
|
do {
|
||||||
(*callback)->Call(global, 2, argv);
|
(*callback)->Call(global, 2, argv);
|
||||||
} while (--j > 0 && ev_is_active(EV_DEFAULT_UC_ &tty_avail_notifier));
|
} while (--j > 0 && tty_watcher_active);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WINDOW_BUFFER_SIZE_EVENT:
|
case WINDOW_BUFFER_SIZE_EVENT:
|
||||||
@ -606,7 +609,7 @@ static Handle<Value> InitTTYWatcher(const Arguments& args) {
|
|||||||
? cb_persist(args[3])
|
? cb_persist(args[3])
|
||||||
: NULL;
|
: NULL;
|
||||||
|
|
||||||
ev_async_init(EV_DEFAULT_UC_ &tty_avail_notifier, tty_poll);
|
uv_async_init(&tty_avail_notifier, tty_poll, NULL, NULL);
|
||||||
|
|
||||||
tty_watcher_initialized = true;
|
tty_watcher_initialized = true;
|
||||||
tty_wait_handle = NULL;
|
tty_wait_handle = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user