static void embed_thread_runner(void* arg) { int r; int fd; int timeout; while (!embed_closed) { fd = uv_backend_fd(uv_default_loop()); timeout = uv_backend_timeout(uv_default_loop()); do { #if defined(HAVE_KQUEUE) struct timespec ts; ts.tv_sec = timeout / 1000; ts.tv_nsec = (timeout % 1000) * 1000000; r = kevent(fd, NULL, 0, NULL, 0, &ts); #elif defined(HAVE_EPOLL) { struct epoll_event ev; r = epoll_wait(fd, &ev, 1, timeout); } #endif } while (r == -1 && errno == EINTR); uv_async_send(&embed_async); uv_sem_wait(&embed_sem); } }
static void embed_thread_runner(void* arg) { uv_os_fd_t fd; int timeout; while (!embed_closed) { fd = uv_backend_fd(uv_default_loop()); timeout = uv_backend_timeout(uv_default_loop()); #if defined(_WIN32) embed_thread_poll_win(fd, timeout); #else embed_thread_poll_unix(fd, timeout); #endif uv_async_send(&embed_async); uv_sem_wait(&embed_sem); } }
void NodeBindingsMac::PollEvents() { struct timeval tv; int timeout = uv_backend_timeout(uv_loop_); if (timeout != -1) { tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; } fd_set readset; int fd = uv_backend_fd(uv_loop_); FD_ZERO(&readset); FD_SET(fd, &readset); // Wait for new libuv events. int r; do { r = select(fd + 1, &readset, NULL, NULL, timeout == -1 ? NULL : &tv); } while (r == -1 && errno == EINTR); }
int hijack_main_loop() { int returnValue; uv_loop_t *uv_loop = NULL; SOL_DBG("Entering with state %s", RESOLVE_MAINLOOP_STATE(mainloopState)); if (mainloopState == MAINLOOP_HIJACKED || mainloopState == MAINLOOP_HIJACKING_STARTED) { return 0; } uv_loop = uv_default_loop(); // The actual hijacking starts here, inspired by node-gtk. The plan: // 1. uv has two ways of letting us know that it needs to run its loop. One // is that its backend timeout is >= 0, and the other is a file // descriptor which can become readable/writable/errored. So, attach a // source to the soletta main loop which will run the uv main loop in // a non-blocking fashion. Also attach a file descriptor watch via which // uv can signal that it needs to run an iteration. // 2. Attach an idler to the uv main loop and call sol_run() from it when // it first runs. This interrupts the uv main loop, because sol_run() // doesn't return but, since we've already added the above sources to // the soletta main loop in the first step, the source or the file // descriptor watch will end up running one non-blocking iteration of // the uv main loop which, in turn, will recursively call the idler we // added. At that point, the idler can remove itself from the uv main // loop. After that, only the soletta main loop runs, but it runs an // iteration of the uv main loop in a non-blocking fashion whenever the // uv main loop signals to the soletta main loop via the attached // source or the attached file descriptor watch. // 3. Attach a token handle to the uv main loop which represents all // soletta open handles. This is necessary because the uv main loop // would otherwise quit when it runs out of its own handles. We remove // this token handle when we release the uv main loop so that if, at // that point, it has no more handles, it is free to cause the node.js // process to quit. // We allocate the various needed structures only once. After that, we // reuse them. We never free them, even if we release the uv main loop. if (!uv_loop_source) { uv_loop_source = sol_mainloop_add_source(&uv_loop_source_funcs, uv_loop); if (!uv_loop_source) { return -ENOMEM; } } if (!uv_loop_fd) { uv_loop_fd = sol_fd_add(uv_backend_fd(uv_loop), SOL_FD_FLAGS_IN | SOL_FD_FLAGS_OUT | SOL_FD_FLAGS_ERR, uv_loop_fd_changed, uv_loop); if (!uv_loop_fd) { return -ENOMEM; } } returnValue = uv_prepare_init(uv_loop, &uv_token_handle); if (returnValue) { return returnValue; } returnValue = uv_idle_init(uv_loop, &uv_idle); if (returnValue) { return returnValue; } SOL_DBG("Starting token handle"); returnValue = uv_prepare_start(&uv_token_handle, uv_token_callback); if (returnValue) { return returnValue; } SOL_DBG("Starting idler"); returnValue = uv_idle_start(&uv_idle, uv_idle_callback); if (returnValue) { return returnValue; } mainloopState = MAINLOOP_HIJACKING_STARTED; return 0; }
int ThreadManager::AdaptorImpl::getBackendFd() { return uv_backend_fd(&main_loop); }