Blog Infos
Author
Published
Topics
, , ,
Published
The Basics: Main Routine and Subroutines

In traditional programming, execution flow is structured around a main routine (the entry point of the program) and subroutines (helper functions that perform specific tasks).

What is a Main Routine?

The main routine (often called main()) is:

  • The entry point of every program.
  • The first function that executes when you run your code.
  • Responsible for orchestrating the program’s workflow.
  • In Kotlin/Java/C-style languages, it looks like this:

 

 

fun main() {
    // Program starts executing here
    first()
    second()
}

 

Key characteristics:

  1. Mandatory — Every executable program must have one
  2. Parent function — Calls other subroutines
  3. Lifecycle controller — Determines the order of operations
What are Subroutines?

Subroutines (also called functions/methods) are:

  • Reusable blocks of code that perform specific tasks
  • Called by the main routine or other subroutines
  • Modularize code into logical units

 

fun first() {
    // Does task A
}

fun second() {
    // Does task B
}

 

Key characteristics:

  1. Single Responsibility — Each should do one thing well
  2. Callable — Can be invoked multiple times
  3. Stack-based — Follows Last-In-First-Out (LIFO) execution

 

fun main() {
    first() //subroutine
    second() //subroutine
}

fun first() {
    var first = 1
    while (true) {
        println("first: ${first++}")
    }
}

fun second() {
    var second = 1
    while (true) {
        println("second: ${second++}")
    }
}

 

What actually happens:

  1. Program launches → main() starts executing
  2. main() calls first() → execution jumps to first()
  3. first() enters infinite loop → never returns
  4. second() never gets called because control never returns to main()
The Critical Limitation

This demonstrates a fundamental programming constraint:

  • Subroutines are blocking — The caller waits until completion
  • No concurrency — Only one function executes at any moment
  • Order-dependent — Strict sequential execution
Visualizing the Call Stack

 

Call Stack          State
-----------        --------
                    Program starts
main()             Calls first()
first()            Enters loop
[stack frozen]     first() never returns

 

This blocking behavior is exactly what coroutines solve by introducing:

  • Suspendable functions
  • Non-blocking operations
  • Concurrent execution

In our previous example with traditional subroutines, we saw how first()‘s infinite loop completely blocked execution of second(). Now let’s examine how coroutines revolutionize this behavior:

fun main(): Unit = runBlocking {
    launch { first() }  // coroutine 1
    launch { second() } // coroutine 2
}

suspend fun first() {
    var first = 1
    while (true) {
        println("first: ${first++}")
        delay(2000) // Suspension point
    }
}

suspend fun second() {
    var second = 1
    while (true) {
        println("second: ${second++}")
        delay(1000) // Suspension point
    }
}
Key Differences from Subroutines
1. Non-Blocking Concurrent Execution
  • Both functions now run concurrently instead of sequentially
  • Output will interleave: “second” prints twice as often as “first”
  • Neither function blocks the other
2. The Magic of Suspension Points
  • delay() is a suspension function that pauses execution without blocking
  • When encountered, the coroutine:
  • Yields the thread
  • Schedules resumption
  • Allows other coroutines to run
3. Structured Concurrency
  • runBlocking creates a coroutine scope
  • launch starts new coroutines as children of this scope
  • All coroutines are automatically cancelled when the scope completes
How This Works Internally

Coroutine Execution Timeline

Time (ms) | Coroutine 1 (first)      | Coroutine 2 (second)
----------|--------------------------|----------------------
0         | Prints "first: 1"        | 
          | Suspends for 2000ms      | Prints "second: 1"
          |                          | Suspends for 1000ms
1000      |                          | Resumes, prints "second: 2"
          |                          | Suspends for 1000ms
2000      | Resumes, prints "first: 2"|
          | Suspends for 2000ms      | Prints "second: 3"
3000      |                          | Resumes, prints "second: 4"
...       | ...                      | ...
Why This Matters
  1. Resource Efficiency
  • Traditional threads: ~1MB stack per thread
  • Coroutines: ~50 bytes per suspended coroutine

2. Simplified Concurrency

  • No callback hell
  • Sequential-looking code with asynchronous execution

3. Responsive Applications

  • Never blocks the main thread
  • Easy to implement features like:
  • Parallel network requests
  • Animations with delays
  • Background processing
Visual Comparison
Subroutine Execution

 

main()
└── first() (runs forever)
    └── second() (never reached)

 

Coroutine Execution

runBlocking
├── launch { first() } (suspends/resumes)
└── launch { second() } (suspends/resumes)

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

,

Meta-programming with K2 compiler plugins

Let’s see what’s possible with plugins using the new K2 compiler, FIR. This live demo session will go through possible use cases that reduce boilerplate code and make your code safer.
Watch Video

Meta-programming with K2 compiler plugins

Tadeas Kriz
Senior Kotlin Developer
Touchlab

Meta-programming with K2 compiler plugins

Tadeas Kriz
Senior Kotlin Develo ...
Touchlab

Meta-programming with K2 compiler plugins

Tadeas Kriz
Senior Kotlin Developer
Touchlab

Jobs

Conclusion

This demonstrates the paradigm shift from linear, blocking execution to flexible, non-blocking concurrency. By leveraging suspension points and structured concurrency, coroutines enable efficient multitasking without sacrificing code clarity. This evolution from rigid subroutine execution to flexible coroutines represents a fundamental advancement in asynchronous programming.

Hope you liked this article. Happy Coding!!

This article is previously published on proandroiddev.com.

Menu