liveBook · Manning

Synchronous call

As explained in Latency

Synchronous processing is a processing model in which operations are handled sequentially and completion or errors are observed before subsequent processing proceeds.

A synchronous call waits for its operation to complete before the caller proceeds. In a synchronous processing sequence, the next task does not start until the current one finishes. This is straightforward to follow, but a slow or blocked operation delays the work behind it. section 10.1.1

One request at a time

A single-threaded server receives a message, parses it, obtains the requested information, formats a response, and sends it before handling another request. Receiving may block until the message arrives; slow request processing holds up the next request. section 10.1.1

Synchronous calls do not rule out concurrency across threads. One thread can block in a socket call while the operating system runs another. An asynchronous server instead uses interfaces such as I/O multiplexing to find ready sockets and make progress on other requests without waiting on the same thread. That distinction matters when the aim is to hide I/O latency rather than shorten the I/O itself. section 10.1.1 section 10.1

Figure 10.1 Synchronous versus asynchronous processing. Synchronous processing (at the top) processes sequentially from one task to the next. In this example, we have tasks A and B, where A submits I/O. The I/O is executed synchronously before task B can execute. In contrast, asynchronous processing (at the bottom) can perform I/O in parallel with task B. That is, task A runs, submits the I/O, and immediately starts executing task B. When the I/O for task A and task B finishes, we’re done, completing the work faster than with synchronous processing.
Figure 10.1: Synchronous vs asynchronous processing. With synchronous processing (at the top of the diagram), a task runs to completion before we start a new task. Therefore, the total time to run tasks A, B, and C is the sum of each task’s time. In contrast, with asynchronous processing (at the bottom of the diagram), all the tasks are started simultaneously, resulting in the total time of the slowest task. Asynchronous processing allows you to reduce perceived latency if you can execute the tasks in parallel.

The timelines show the cost of waiting: synchronous I/O finishes before the next task starts, while asynchronous I/O can overlap that task. section 10.1.1

Listing 10.1 A simple example of a synchronous system
fn process_requests(socket: &Socket) {
  loop {
    process_request(socket);
  }
}

fn process_request(socket: &Socket) {
  let msg = socket.recv();
  let request = parse_message(msg);
  let resp = match request {
    Request::GetUserInfo(id) => get_user_info(id);    
  };
  let resp = format_response(resp);
  socket.send(resp);
}

The request loop makes the sequencing concrete: receive, parse, process, and send all finish before the next iteration. section 10.1.1

How Latency covers it

How deep it goes
Defines completion-before-next-task behavior and traces a blocking server request, without developing a separate synchronous-call API.
Examples
Uses a socket request loop and task timelines to show where waiting prevents the next task from starting.
What you can do after
Evaluate/understand when a blocking call delays subsequent work and when another thread can still make progress.
How it connects
Contrasts synchronous calls with asynchronous processing, I/O multiplexing, event loops, and thread-based concurrency.

Also explained in

Compare how 6 books explain synchronous call →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Latency. The section links point to the parts of the book it draws on.