Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Asynchronous Tasks #42

Open
Michael-F-Bryan opened this issue Nov 3, 2017 · 0 comments
Open

Asynchronous Tasks #42

Michael-F-Bryan opened this issue Nov 3, 2017 · 0 comments

Comments

@Michael-F-Bryan
Copy link
Owner

There's currently an "Asynchronous Operations" chapter which is meant to spin a a job off into the background and will periodically poll it to see if there's a result. We could accomplish this quite easily by using futures and a global CpuPool, with a TaskHandle struct which wraps a future and periodically polls.

The TaskHandle would have to be generic over any generic Task, meaning if we want to use it for FFI we'll want to use some sort of code generation (macro) for generating specialised functions for interacting with the background task.

I've done something like this before at work, so here's a gist to help get started. I was thinking it could use a Task trait similar to the following:

pub trait Task {
  type Output;
  type Error;

  fn run(&self, ctx: Context) -> Result<Self::Output, Self::Error>;
  fn description(&self) -> &'static str;
}

Then the macro which generates FFI bindings for a particular Task implementation might look like this:

struct Foo;
impl Task for Foo { ... } 

generate_task!(Foo; 
  spawn: foo_task_spawn,
  cancel:  foo_task_cancel,
  get_result: foo_task_get_result,
  is_failed: foo_task_is_failed,
  wait: foo_task_wait,
  ...
);

Which might then generate:

/// Spawn the task on a background thread, returning a `TaskHandle`. 
///
/// # Safety
///
/// This **consumes** the task, so it shouldn't be used once the task is spawned.
#[no_mangle]
pub unsafe extern "C" fn foo_task_spawn(task: *mut Foo) -> TaskHandle<Foo> { ... }

/// Cancel a background task.
#[no_mangle]
pub unsafe extern "C" fn foo_task_cancel(handle: *mut TaskHandle<Foo>) { ... } 

/// Wait until the task completes.
///
/// # Safety
///
/// This will consume the task handle and return a `Box<Task::Output>` (that you need
/// to deallocate manually).
#[no_mangle]
pub unsafe extern "C" fn foo_task_wait(handle: *mut TaskHandle<Foo>) -> *const Foo::Output { ... } 

...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant