# Future and Promises in Modern C++

* * *

# Introduction

Imagine you're downloading a large file while editing a document. Your computer does not freeze waiting for the download to complete. It performs multiple tasks simultaneously.

As multi-core CPUs became common, C++ needed a standard mechanism for asynchronous programming and thread communication. C++11 introduced `std::future` and `std::promise` to solve this problem.

* * *

# When Were Future and Promise Added?

Future and Promise were introduced in **C++11**.

```cpp
#include <future>
```

The library introduced:

*   `std::future`
    
*   `std::promise`
    
*   `std::async`
    
*   `std::packaged_task`
    

* * *

# Why Were Future and Promise Needed?

Before C++11, developers relied on:

*   Shared variables
    
*   Mutexes
    
*   Condition variables
    
*   Polling loops
    
*   Callback functions
    

Example:

```cpp
int result;
bool ready = false;
```

Problems:

*   Race conditions
    
*   Deadlocks
    
*   Busy waiting
    
*   Difficult debugging
    
*   Complex synchronization logic
    

Future and Promise provide a clean abstraction that handles synchronization safely.

* * *

# Real-Life Analogy

Food Delivery Example:

*   Restaurant prepares food → `std::promise`
    
*   Customer receives tracking token → `std::future`
    

The promise produces the result. The future receives the result later.

* * *

# What is std::future?

A future represents a value that will become available later.

```cpp
std::future<int>
```

Meaning:

> I don't have the value yet, but I will receive it in the future.

* * *

# What is std::promise?

A promise allows one thread to store a value which another thread retrieves later.

```cpp
std::promise<int> promise;
```

* * *

# Internal Working - Shared State

Future and Promise communicate through a hidden Shared State.

```text
Producer Thread
      |
std::promise
      |
 Shared State
      |
std::future
      |
Consumer Thread
```

Promise writes data. Future reads data.

* * *

# Future Lifecycle

```text
Create Promise
      ↓
Create Future
      ↓
Future Waiting
      ↓
Promise set_value()
      ↓
Future Ready
      ↓
future.get()
      ↓
State Consumed
```

* * *

# Basic Example

```cpp
#include <future>
#include <thread>
#include <iostream>

void worker(std::promise<int> promise)
{
    std::this_thread::sleep_for(std::chrono::seconds(2));
    promise.set_value(42);
}

int main()
{
    std::promise<int> promise;
    auto future = promise.get_future();

    std::thread t(worker, std::move(promise));

    std::cout << "Waiting...
";

    int result = future.get();

    std::cout << result << std::endl;

    t.join();
}
```

* * *

# Valid and Invalid Futures

After calling:

```cpp
future.get();
```

The future becomes invalid.

```cpp
if(future.valid())
{
    auto value = future.get();
}
```

* * *

# Exception Propagation

One major advantage is safe exception transfer across threads.

```cpp
try
{
    throw std::runtime_error("Database Error");
}
catch(...)
{
    promise.set_exception(std::current_exception());
}
```

Consumer:

```cpp
try
{
    future.get();
}
catch(const std::exception& e)
{
    std::cout << e.what();
}
```

* * *

# Waiting APIs

## wait()

```cpp
future.wait();
```

## wait\_for()

```cpp
future.wait_for(std::chrono::seconds(2));
```

## wait\_until()

```cpp
future.wait_until(deadline);
```

* * *

# Using std::async

```cpp
int calculate()
{
    return 10 * 20;
}

auto future = std::async(
                std::launch::async,
                calculate);

std::cout << future.get();
```

Output:

```text
200
```

* * *

# Async Launch Policies

## std::launch::async

Creates a new thread.

```cpp
std::async(std::launch::async, task);
```

## std::launch::deferred

Executes only when get() is called.

```cpp
std::async(std::launch::deferred, task);
```

* * *

# Shared Future

Normal future supports one consumer.

```cpp
std::future<int>
```

For multiple consumers:

```cpp
std::shared_future<int>
```

Example:

```cpp
auto sf = promise.get_future().share();
```

Multiple threads may call:

```cpp
sf.get();
```

* * *

# Packaged Task

```cpp
std::packaged_task<int()> task(function);
```

Useful in:

*   Thread pools
    
*   Schedulers
    
*   Task queues
    

* * *

# Future vs Promise vs Async

## Promise

Produces value.

```cpp
promise.set_value(100);
```

## Future

Receives value.

```cpp
future.get();
```

## Async

Creates Promise and Future internally.

```cpp
auto future = std::async(task);
```

* * *

# Practical Industry Use Cases

## Automotive ADAS

*   Camera processing
    
*   Radar processing
    
*   LiDAR processing
    
*   Sensor fusion
    

Example:

```cpp
cameraFuture.get();
radarFuture.get();
lidarFuture.get();

performSensorFusion();
```

## Cloud Services

*   OTA updates
    
*   Backend communication
    
*   Vehicle configuration downloads
    

## Database Queries

Execute long-running queries asynchronously.

## Image Processing

Pipeline stage synchronization.

## GUI Applications

Keep UI responsive while background work continues.

* * *

# Thread Pool Architecture

```text
Task
 |
packaged_task
 |
Thread Pool
 |
future
 |
Consumer
```

Common in:

*   Trading systems
    
*   Backend servers
    
*   Game engines
    
*   ADAS middleware
    

* * *

# Coroutines vs Future

Future and Promise:

```text
C++11
```

Coroutines:

```text
C++20
```

Future style:

```cpp
auto value = future.get();
```

Coroutine style:

```cpp
auto value = co_await task();
```

* * *

# Common Mistakes

## Calling get() Twice

```cpp
future.get();
future.get();
```

## Forgetting std::move

```cpp
std::move(promise)
```

## Never Calling set\_value()

The waiting thread may block forever.

* * *

# Performance Considerations

Good For:

*   One-time result transfer
    
*   Task synchronization
    
*   Exception propagation
    
*   Async operations
    

Not Good For:

*   High-frequency messaging
    
*   Real-time streaming
    
*   Massive message queues
    

* * *

# Interview Questions

### Difference between Future and Promise?

Promise produces data. Future consumes data.

### Can Future be copied?

No, it is move-only.

### Can one Promise create multiple Futures?

No.

### Difference between Future and Shared Future?

Future supports one consumer. Shared Future supports multiple consumers.

### What happens if Promise is destroyed before set\_value()?

Future receives `std::future_error`.

### Difference between get() and wait()?

*   get() waits and returns value
    
*   wait() only waits
    

* * *

# Evolution of Modern C++

*   C++11 : Future, Promise, Async
    
*   C++14 : Async improvements
    
*   C++17 : Parallel algorithms
    
*   C++20 : Coroutines
    
*   C++23 : Concurrency improvements
    

* * *

# Key Takeaways

> `Introduced in C++11`
> 
> `Found in <future> Simplifies thread synchronization`
> 
> `Eliminates busy polling`
> 
> `Supports exception propagation`
> 
> `Makes asynchronous programming easier`
> 
> `Widely used in automotive, embedded, backend and cloud systems Foundation for modern concurrency in C++`

* * *

# Conclusion

Future and Promise transformed C++ concurrency by providing a clean, safe, and standardized mechanism for asynchronous communication between threads. They hide much of the complexity of mutexes and condition variables while making code easier to write, debug, and maintain.

Whether you are building ADAS software, embedded systems, backend services, cloud platforms, or high-performance applications, understanding Future and Promise is essential for becoming a strong Modern C++ developer.

* * *
