Compare commits
4 Commits
main
...
rename-eve
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f75368a2d2 | ||
|
|
6221ee21a8 | ||
|
|
280fdbd42a | ||
|
|
f2d3703ab9 |
@ -152,7 +152,7 @@ use crate::borrow::internal::Ledger;
|
||||
use crate::borrow::{Borrow, BorrowMut, Ref, RefMut};
|
||||
use crate::context::internal::Env;
|
||||
#[cfg(all(feature = "napi-4", feature = "event-queue-api"))]
|
||||
use crate::event::EventQueue;
|
||||
use crate::event::Channel;
|
||||
use crate::handle::{Handle, Managed};
|
||||
#[cfg(feature = "legacy-runtime")]
|
||||
use crate::object::class::Class;
|
||||
@ -550,9 +550,16 @@ pub trait Context<'a>: ContextInternal<'a> {
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "napi-4", feature = "event-queue-api"))]
|
||||
/// Creates an unbounded queue of events to be executed on a JavaScript thread
|
||||
fn queue(&mut self) -> EventQueue {
|
||||
EventQueue::new(self)
|
||||
/// Creates an unbounded channel for scheduling events to be executed on the JavaScript thread.
|
||||
fn channel(&mut self) -> Channel {
|
||||
Channel::new(self)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "napi-4", feature = "event-queue-api"))]
|
||||
#[deprecated(since = "0.9.0", note = "Please use the channel() method instead")]
|
||||
#[doc(hidden)]
|
||||
fn queue(&mut self) -> Channel {
|
||||
self.channel()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ use crate::result::NeonResult;
|
||||
|
||||
type Callback = Box<dyn FnOnce(Env) + Send + 'static>;
|
||||
|
||||
/// Queue for scheduling Rust closures to execute on the JavaScript main thread.
|
||||
/// Channel for scheduling Rust closures to execute on the JavaScript main thread.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -17,11 +17,11 @@ type Callback = Box<dyn FnOnce(Env) + Send + 'static>;
|
||||
/// # use neon::prelude::*;
|
||||
/// # fn fibonacci(_: f64) -> f64 { todo!() }
|
||||
/// fn async_fibonacci(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
/// // These types (`f64`, `Root<JsFunction>`, `EventQueue`) may all be sent
|
||||
/// // These types (`f64`, `Root<JsFunction>`, `Channel`) may all be sent
|
||||
/// // across threads.
|
||||
/// let n = cx.argument::<JsNumber>(0)?.value(&mut cx);
|
||||
/// let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
|
||||
/// let queue = cx.queue();
|
||||
/// let channel = cx.channel();
|
||||
///
|
||||
/// // Spawn a thread to complete the execution. This will _not_ block the
|
||||
/// // JavaScript event loop.
|
||||
@ -29,8 +29,8 @@ type Callback = Box<dyn FnOnce(Env) + Send + 'static>;
|
||||
/// let result = fibonacci(n);
|
||||
///
|
||||
/// // Send a closure as a task to be executed by the JavaScript event
|
||||
/// // queue. This _will_ block the event queue while executing.
|
||||
/// queue.send(move |mut cx| {
|
||||
/// // loop. This _will_ block the event loop while executing.
|
||||
/// channel.send(move |mut cx| {
|
||||
/// let callback = callback.into_inner(&mut cx);
|
||||
/// let this = cx.undefined();
|
||||
/// let null = cx.null();
|
||||
@ -49,19 +49,19 @@ type Callback = Box<dyn FnOnce(Env) + Send + 'static>;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
pub struct EventQueue {
|
||||
pub struct Channel {
|
||||
tsfn: ThreadsafeFunction<Callback>,
|
||||
has_ref: bool,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for EventQueue {
|
||||
impl std::fmt::Debug for Channel {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("EventQueue")
|
||||
f.write_str("Channel")
|
||||
}
|
||||
}
|
||||
|
||||
impl EventQueue {
|
||||
/// Creates an unbounded queue for scheduling closures on the JavaScript
|
||||
impl Channel {
|
||||
/// Creates an unbounded channel for scheduling closures on the JavaScript
|
||||
/// main thread
|
||||
pub fn new<'a, C: Context<'a>>(cx: &mut C) -> Self {
|
||||
let tsfn = unsafe { ThreadsafeFunction::new(cx.env().to_raw(), Self::callback) };
|
||||
@ -72,7 +72,7 @@ impl EventQueue {
|
||||
}
|
||||
}
|
||||
|
||||
/// Allow the Node event loop to exit while this `EventQueue` exists.
|
||||
/// Allow the Node event loop to exit while this `Channel` exists.
|
||||
/// _Idempotent_
|
||||
pub fn unref<'a, C: Context<'a>>(&mut self, cx: &mut C) -> &mut Self {
|
||||
self.has_ref = false;
|
||||
@ -82,7 +82,7 @@ impl EventQueue {
|
||||
self
|
||||
}
|
||||
|
||||
/// Prevent the Node event loop from exiting while this `EventQueue` exists. (Default)
|
||||
/// Prevent the Node event loop from exiting while this `Channel` exists. (Default)
|
||||
/// _Idempotent_
|
||||
pub fn reference<'a, C: Context<'a>>(&mut self, cx: &mut C) -> &mut Self {
|
||||
self.has_ref = true;
|
||||
@ -92,7 +92,7 @@ impl EventQueue {
|
||||
self
|
||||
}
|
||||
|
||||
/// Schedules a closure to execute on the JavaScript thread that created this EventQueue
|
||||
/// Schedules a closure to execute on the JavaScript thread that created this Channel
|
||||
/// Panics if there is a libuv error
|
||||
pub fn send<F>(&self, f: F)
|
||||
where
|
||||
@ -101,9 +101,9 @@ impl EventQueue {
|
||||
self.try_send(f).unwrap()
|
||||
}
|
||||
|
||||
/// Schedules a closure to execute on the JavaScript thread that created this EventQueue
|
||||
/// Schedules a closure to execute on the JavaScript thread that created this Channel
|
||||
/// Returns an `Error` if the task could not be scheduled.
|
||||
pub fn try_send<F>(&self, f: F) -> Result<(), EventQueueError>
|
||||
pub fn try_send<F>(&self, f: F) -> Result<(), SendError>
|
||||
where
|
||||
F: FnOnce(TaskContext) -> NeonResult<()> + Send + 'static,
|
||||
{
|
||||
@ -117,11 +117,11 @@ impl EventQueue {
|
||||
});
|
||||
});
|
||||
|
||||
self.tsfn.call(callback, None).map_err(|_| EventQueueError)
|
||||
self.tsfn.call(callback, None).map_err(|_| SendError)
|
||||
}
|
||||
|
||||
/// Returns a boolean indicating if this `EventQueue` will prevent the Node event
|
||||
/// queue from exiting.
|
||||
/// Returns a boolean indicating if this `Channel` will prevent the Node event
|
||||
/// loop from exiting.
|
||||
pub fn has_ref(&self) -> bool {
|
||||
self.has_ref
|
||||
}
|
||||
@ -138,19 +138,19 @@ impl EventQueue {
|
||||
}
|
||||
}
|
||||
|
||||
/// Error indicating that a closure was unable to be scheduled to execute on the event queue
|
||||
pub struct EventQueueError;
|
||||
/// Error indicating that a closure was unable to be scheduled to execute on the event loop.
|
||||
pub struct SendError;
|
||||
|
||||
impl std::fmt::Display for EventQueueError {
|
||||
impl std::fmt::Display for SendError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "EventQueueError")
|
||||
write!(f, "SendError")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for EventQueueError {
|
||||
impl std::fmt::Debug for SendError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for EventQueueError {}
|
||||
impl std::error::Error for SendError {}
|
||||
|
||||
@ -32,20 +32,20 @@
|
||||
//! # #[cfg(feature = "napi-1")] {
|
||||
//! # use neon::prelude::*;
|
||||
//! #
|
||||
//! # fn parse(filename: String, callback: Root<JsFunction>, queue: EventQueue) { }
|
||||
//! # fn parse(filename: String, callback: Root<JsFunction>, channel: Channel) { }
|
||||
//! #
|
||||
//! fn parse_async(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
//! // The types `String`, `Root<JsFunction>`, and `EventQueue` can all be
|
||||
//! // The types `String`, `Root<JsFunction>`, and `Channel` can all be
|
||||
//! // sent across threads.
|
||||
//! let filename = cx.argument::<JsString>(0)?.value(&mut cx);
|
||||
//! let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
|
||||
//! let queue = cx.queue();
|
||||
//! let channel = cx.channel();
|
||||
//!
|
||||
//! // Spawn a thread to complete the execution. This will _not_ block the
|
||||
//! // JavaScript event loop.
|
||||
//! // Spawn a background thread to complete the execution. The background
|
||||
//! // execution will _not_ block the JavaScript event loop.
|
||||
//! std::thread::spawn(move || {
|
||||
//! // Do the heavy lifting inside the background thread.
|
||||
//! parse(filename, callback, queue);
|
||||
//! parse(filename, callback, channel);
|
||||
//! });
|
||||
//!
|
||||
//! Ok(cx.undefined())
|
||||
@ -58,7 +58,7 @@
|
||||
//! thread.)
|
||||
//!
|
||||
//! Upon completion of its task, the background thread can use the JavaScript
|
||||
//! callback and the event queue to notify the main thread of the result:
|
||||
//! callback and the channel to notify the main thread of the result:
|
||||
//!
|
||||
//! ```
|
||||
//! # #[cfg(feature = "napi-1")] {
|
||||
@ -70,12 +70,12 @@
|
||||
//! Psd::from_bytes(&std::fs::read(&filename)?)
|
||||
//! }
|
||||
//!
|
||||
//! fn parse(filename: String, callback: Root<JsFunction>, queue: EventQueue) {
|
||||
//! fn parse(filename: String, callback: Root<JsFunction>, channel: Channel) {
|
||||
//! let result = psd_from_filename(filename);
|
||||
//!
|
||||
//! // Send a closure as a task to be executed by the JavaScript event
|
||||
//! // queue. This _will_ block the event queue while executing.
|
||||
//! queue.send(move |mut cx| {
|
||||
//! // loop. This _will_ block the event loop while executing.
|
||||
//! channel.send(move |mut cx| {
|
||||
//! let callback = callback.into_inner(&mut cx);
|
||||
//! let this = cx.undefined();
|
||||
//! let null = cx.null();
|
||||
@ -127,7 +127,17 @@
|
||||
mod event_queue;
|
||||
|
||||
#[cfg(all(feature = "napi-4", feature = "event-queue-api"))]
|
||||
pub use self::event_queue::{EventQueue, EventQueueError};
|
||||
pub use self::event_queue::{Channel, SendError};
|
||||
|
||||
#[cfg(all(feature = "napi-4", feature = "event-queue-api"))]
|
||||
#[deprecated(since = "0.9.0", note = "Please use the Channel type instead")]
|
||||
#[doc(hidden)]
|
||||
pub type EventQueue = self::event_queue::Channel;
|
||||
|
||||
#[cfg(all(feature = "napi-4", feature = "event-queue-api"))]
|
||||
#[deprecated(since = "0.9.0", note = "Please use the SendError type instead")]
|
||||
#[doc(hidden)]
|
||||
pub type EventQueueError = self::event_queue::SendError;
|
||||
|
||||
#[cfg(all(not(feature = "napi-1"), feature = "event-handler-api"))]
|
||||
mod event_handler;
|
||||
@ -138,5 +148,5 @@ pub use self::event_handler::EventHandler;
|
||||
#[cfg(all(feature = "napi-1", feature = "event-handler-api"))]
|
||||
compile_error!(
|
||||
"The `EventHandler` API is not supported with the N-API \
|
||||
backend. Use `EventQueue` instead."
|
||||
backend. Use `Channel` instead."
|
||||
);
|
||||
|
||||
@ -10,6 +10,9 @@ pub use crate::declare_types;
|
||||
#[cfg(all(not(feature = "napi-1"), feature = "event-handler-api"))]
|
||||
pub use crate::event::EventHandler;
|
||||
#[cfg(all(feature = "napi-4", feature = "event-queue-api"))]
|
||||
pub use crate::event::{Channel, SendError};
|
||||
#[cfg(all(feature = "napi-4", feature = "event-queue-api"))]
|
||||
#[allow(deprecated)]
|
||||
pub use crate::event::{EventQueue, EventQueueError};
|
||||
pub use crate::handle::Handle;
|
||||
#[cfg(feature = "legacy-runtime")]
|
||||
|
||||
@ -6,7 +6,7 @@ const assert = require('chai').assert;
|
||||
return typeof global.gc === 'function' ? describe : describe.skip;
|
||||
})()('sync', function() {
|
||||
afterEach(() => {
|
||||
// Force garbage collection to shutdown `EventQueue`
|
||||
// Force garbage collection to shutdown `Channel`
|
||||
global.gc();
|
||||
});
|
||||
|
||||
@ -60,9 +60,9 @@ const assert = require('chai').assert;
|
||||
global.gc();
|
||||
});
|
||||
|
||||
it('should be able to unref event queue', function () {
|
||||
// If the EventQueue is not unreferenced, the test runner will not cleanly exit
|
||||
addon.leak_event_queue();
|
||||
it('should be able to unref channel', function () {
|
||||
// If the Channel is not unreferenced, the test runner will not cleanly exit
|
||||
addon.leak_channel();
|
||||
});
|
||||
|
||||
it('should drop leaked Root from the global queue', function (cb) {
|
||||
|
||||
@ -13,10 +13,10 @@ pub fn useless_root(mut cx: FunctionContext) -> JsResult<JsObject> {
|
||||
|
||||
pub fn thread_callback(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);
|
||||
let queue = cx.queue();
|
||||
let channel = cx.channel();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
queue.send(move |mut cx| {
|
||||
channel.send(move |mut cx| {
|
||||
let callback = callback.into_inner(&mut cx);
|
||||
let this = cx.undefined();
|
||||
let args = Vec::<Handle<JsValue>>::new();
|
||||
@ -33,14 +33,14 @@ pub fn thread_callback(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
pub fn multi_threaded_callback(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let n = cx.argument::<JsNumber>(0)?.value(&mut cx);
|
||||
let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
|
||||
let queue = Arc::new(cx.queue());
|
||||
let channel = Arc::new(cx.channel());
|
||||
|
||||
for i in 0..(n as usize) {
|
||||
let callback = callback.clone(&mut cx);
|
||||
let queue = Arc::clone(&queue);
|
||||
let channel = Arc::clone(&channel);
|
||||
|
||||
std::thread::spawn(move || {
|
||||
queue.send(move |mut cx| {
|
||||
channel.send(move |mut cx| {
|
||||
let callback = callback.into_inner(&mut cx);
|
||||
let this = cx.undefined();
|
||||
let args = vec![cx.number(i as f64)];
|
||||
@ -63,17 +63,17 @@ pub struct AsyncGreeter {
|
||||
greeting: String,
|
||||
callback: Root<JsFunction>,
|
||||
shutdown: Option<Root<JsFunction>>,
|
||||
queue: Arc<EventQueue>,
|
||||
channel: Arc<Channel>,
|
||||
}
|
||||
|
||||
impl AsyncGreeter {
|
||||
fn greet<'a, C: Context<'a>>(&self, mut cx: C) -> JsResult<'a, JsUndefined> {
|
||||
let greeting = self.greeting.clone();
|
||||
let callback = self.callback.clone(&mut cx);
|
||||
let queue = Arc::clone(&self.queue);
|
||||
let channel = Arc::clone(&self.channel);
|
||||
|
||||
std::thread::spawn(move || {
|
||||
queue.send(|mut cx| {
|
||||
channel.send(|mut cx| {
|
||||
let callback = callback.into_inner(&mut cx);
|
||||
let this = cx.undefined();
|
||||
let args = vec![cx.string(greeting)];
|
||||
@ -110,7 +110,7 @@ pub fn greeter_new(mut cx: FunctionContext) -> JsResult<BoxedGreeter> {
|
||||
let callback = cx.argument::<JsFunction>(1)?.root(&mut cx);
|
||||
let shutdown = cx.argument_opt(2);
|
||||
|
||||
let queue = cx.queue();
|
||||
let channel = cx.channel();
|
||||
let shutdown = shutdown
|
||||
.map(|v| v.downcast_or_throw::<JsFunction, _>(&mut cx))
|
||||
.transpose()?
|
||||
@ -120,7 +120,7 @@ pub fn greeter_new(mut cx: FunctionContext) -> JsResult<BoxedGreeter> {
|
||||
greeting,
|
||||
callback,
|
||||
shutdown,
|
||||
queue: Arc::new(queue),
|
||||
channel: Arc::new(channel),
|
||||
}));
|
||||
|
||||
Ok(greeter)
|
||||
@ -133,14 +133,14 @@ pub fn greeter_greet(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
greeter.greet(cx)
|
||||
}
|
||||
|
||||
pub fn leak_event_queue(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let queue = Box::new({
|
||||
let mut queue = cx.queue();
|
||||
queue.unref(&mut cx);
|
||||
queue
|
||||
pub fn leak_channel(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
let channel = Box::new({
|
||||
let mut channel = cx.channel();
|
||||
channel.unref(&mut cx);
|
||||
channel
|
||||
});
|
||||
|
||||
Box::leak(queue);
|
||||
Box::leak(channel);
|
||||
|
||||
Ok(cx.undefined())
|
||||
}
|
||||
@ -148,7 +148,7 @@ pub fn leak_event_queue(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
pub fn drop_global_queue(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
struct Wrapper {
|
||||
callback: Option<Root<JsFunction>>,
|
||||
queue: EventQueue,
|
||||
channel: Channel,
|
||||
}
|
||||
|
||||
impl Finalize for Wrapper {}
|
||||
@ -158,7 +158,7 @@ pub fn drop_global_queue(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
impl Drop for Wrapper {
|
||||
fn drop(&mut self) {
|
||||
if let Some(callback) = self.callback.take() {
|
||||
self.queue.send(|mut cx| {
|
||||
self.channel.send(|mut cx| {
|
||||
let callback = callback.into_inner(&mut cx);
|
||||
let this = cx.undefined();
|
||||
let args = vec![cx.undefined()];
|
||||
@ -172,11 +172,11 @@ pub fn drop_global_queue(mut cx: FunctionContext) -> JsResult<JsUndefined> {
|
||||
}
|
||||
|
||||
let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);
|
||||
let queue = cx.queue();
|
||||
let channel = cx.channel();
|
||||
|
||||
let wrapper = cx.boxed(Wrapper {
|
||||
callback: Some(callback),
|
||||
queue,
|
||||
channel,
|
||||
});
|
||||
|
||||
// Put the `Wrapper` instance in a `Root` and drop it
|
||||
|
||||
@ -255,7 +255,7 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
||||
cx.export_function("multi_threaded_callback", multi_threaded_callback)?;
|
||||
cx.export_function("greeter_new", greeter_new)?;
|
||||
cx.export_function("greeter_greet", greeter_greet)?;
|
||||
cx.export_function("leak_event_queue", leak_event_queue)?;
|
||||
cx.export_function("leak_channel", leak_channel)?;
|
||||
cx.export_function("drop_global_queue", drop_global_queue)?;
|
||||
|
||||
Ok(())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user