← Back to Blogs

Singleton Design Pattern in C++ and How It Is Used in HALs

Why some classes should have only one instance - and how AOSP HALs rely on this idea

1 min read
Singleton Design Pattern in C++ and How It Is Used in HALs

In software design, not everything should be created again and again. Some components are too important - and too shared - to have multiple copies floating around in memory. That is exactly the problem the Singleton Design Pattern was created to solve.

What is Singleton?

The Singleton pattern is a creational design pattern that guarantees a class has only one instance, and provides a single, well-known global access point to it. Think of it as a single source of truth for a particular concern in your system.

Why It Matters in AOSP HALs

In systems like Android Automotive and AOSP HALs, the underlying hardware is a shared resource. Multiple framework modules, services, and clients all need to talk to the same physical sensor, audio device, vehicle bus, or display controller.

What goes wrong without a Singleton

What a Singleton gives you

Singleton in C++

Below is a classic Singleton implementation in C++. The constructor is private, the only way to obtain the instance is through the static getInstance() method, and a static pointer holds the one and only object.

C++ Code

// input-output stream library
#include <iostream>

// avoid the std:: prefix on cout
using namespace std;

class Singleton {
private:
    // holds the single instance
    static Singleton* instance;

    // private constructor
    Singleton() {
        cout << "Singleton Instance Created!" << endl;
    }

public:
    // global access point to the instance
    static Singleton* getInstance() {
        if (instance == nullptr) {
            // create the instance only the first time
            instance = new Singleton();
        }
        // return the same instance every call
        return instance;
    }

    void showMessage() {
        cout << "Hello from Singleton!" << endl;
    }
};

// initialize the static member
Singleton* Singleton::instance = nullptr;

int main() {
    // creates the instance
    Singleton* obj1 = Singleton::getInstance();

    // returns the same instance
    Singleton* obj2 = Singleton::getInstance();

    obj1->showMessage();
    obj2->showMessage();

    if (obj1 == obj2) {
        cout << "Both objects are the same instance!" << endl;
    }

    return 0;
}

What this code shows

In real AOSP HAL code you will usually see a thread-safe variant - either using std::call_once with std::once_flag, or the Meyers Singleton (a function-local static), which the C++ standard guarantees is initialized exactly once even with multiple threads. The pattern is the same, the safety guarantees are stronger.