Suspend functions.

We have seen coroutines and the delay function. But what makes delay special? It is a suspend function. Today we understand what suspend functions are and how they enable non-blocking code.

A suspend function is marked with the suspend modifier.

suspend fun fetchData colon String. This function can suspend. It can pause execution without blocking a thread.

The suspend modifier is a promise. It says: this function might pause. The caller must be prepared for that.

Any function can be marked suspend. The modifier does not change what the function does. It changes where and how it can be called.

Suspend functions look like regular functions. They have parameters, return values, and bodies. The suspend modifier is the only difference.

Suspend functions can only be called from specific places.

You can call a suspend function from another suspend function. This is natural. If your function calls something that might suspend, your function must also be able to suspend.

You can call a suspend function from a coroutine. Coroutines are designed to handle suspension. They know how to pause and resume.

You cannot call a suspend function from a regular function. A regular function cannot pause. It has no mechanism for suspension.

The compiler enforces this. Try to call a suspend function from main, and you get an error. The code will not compile.

When a suspend function suspends, the thread is free.

Consider delay. When you call delay 1000, the coroutine pauses for one second. But the thread does not sleep. The thread can run other coroutines.

This is the key insight. Suspension releases the thread. Blocking holds the thread.

A suspend function like delay works with the coroutine runtime. It says: wake me later. The runtime schedules the wake-up. The thread moves on.

Compare to Thread dot sleep. The thread does nothing. It just waits. Wasteful.

Suspend functions enable efficient waiting. The coroutine waits. The thread works.

You can write your own suspend functions.

suspend fun fetchUser id colon Int colon User. Inside, you call other suspend functions. Maybe a network call that suspends. Maybe a database query that suspends.

Your suspend function is just a function. It can have local variables, loops, conditionals. Everything works normally.

When you call a suspend function inside, your function might suspend at that point. When the call completes, your function continues.

You do not manage suspension. You just call suspend functions. The runtime handles the rest.

Suspend functions compose sequentially by default.

suspend fun loadProfile first calls fetchUser, then calls fetchOrders, then combines results.

Each call happens in order. fetchUser completes, then fetchOrders runs, then the combination.

This looks like blocking code. First do A, then do B, then do C. But it is not blocking. Each step can suspend without holding a thread.

Sequential composition is natural. You write code in order. It executes in order. But suspension makes it efficient.

If you want concurrency, you explicitly use async. Without async, calls are sequential. This is easy to understand.

Except for the modifier, suspend functions are normal.

They can have parameters: suspend fun fetch url colon String.

They can return values: suspend fun compute colon Int.

They can throw exceptions: throw IOException inside a suspend function.

They can be extension functions: suspend fun User dot refresh.

They can have generic types: suspend fun fetch of T colon T.

Everything you know about functions applies. The suspend modifier just adds the ability to pause.

The coroutine library provides many suspend functions.

delay suspends for a time. It does not block.

await suspends until a Deferred completes.

join suspends until a Job completes.

withContext suspends while switching to a different dispatcher.

yield suspends to give other coroutines a chance to run.

Network libraries provide suspend functions for HTTP calls. Database libraries provide suspend functions for queries. The ecosystem builds on suspend functions.

Write operations that might wait as suspend functions.

Network calls wait for responses. Make them suspend functions.

Database queries wait for results. Make them suspend functions.

File reads wait for disk. Make them suspend functions.

User input waits for interaction. Make them suspend functions.

If something might wait, make it suspend. This enables efficient handling without blocking threads.

Let us summarize.

Suspend functions are marked with the suspend modifier.

They can only be called from coroutines or other suspend functions.

When they suspend, the thread is free to do other work.

Suspend functions compose sequentially by default.

Otherwise, they are regular functions with all normal capabilities.

Suspend functions are the building blocks of non-blocking code.