Task

Returning Values (Task)

Returning values from an asynchronous task call is substantially harder than dropping off work. If the caller needs a result back from the server, the call must split into two: one to submit the request, one to retrieve the result. The gap between the two lets the caller run concurrently with the server, but the protocol for matching clients to results is where the complexity lives.

Why can't we just use the server's return value?

Because a synchronous return blocks the caller for the whole computation, which defeats the point of handing work off. The two-call pattern makes the return explicit and optional: the caller can do other work between start and wait, and only blocks at the moment it actually needs the result. The cost is a protocol for naming outstanding work.

Two-call structure

callee.start( arg );       // drop off arguments, return immediately
// caller does other work
result = callee.wait();    // retrieve result, blocks if not ready

Unlike START / WAIT thread creation, the server thread already exists: this is a many-to-one interaction where many clients share one server, not one-to-one per work item.

What to do if result is not ready

Two options on the second call:

  • Block: caller waits on a condition until server produces the result.
  • Poll: caller does tryWait and decides whether to spin, do other work, or come back later.

The matching problem

The hard part: when the second call arrives, which outstanding request does it match? Three common protocols, each with trade-offs.

  • Tickets: server returns a token on start; caller presents it on wait. Error-prone because clients can forge, lose, or reuse tickets.
  • Call-backs: caller registers a routine on start; server invokes it with the result. Server can push results faster; client controls poll vs block.
  • Futures: object returned immediately, filled in asynchronously; accessing it transparently blocks if empty. Protocol becomes implicit. This is the cleanest of the three and what uC++ standardizes on (Future_ISM, Future_ESM).