The DigitalOutputGuard class provides Resource Acquisition Is Initialization (RAII) management
for GPIO output operations.
It ensures that a GPIO pin is automatically set to active state when the guard is created and
automatically set to inactive state when the guard is destroyed,
providing safe and reliable GPIO state management.
Key Features
RAII Pattern: Automatic GPIO state management with guaranteed cleanup
Exception Safety: Proper cleanup even in error scenarios
Flexible Interface: Supports both reference and pointer-based GPIO objects
Output Mode Enforcement: Automatically configures GPIO as output if needed
Thread Safety: Safe for use in multi-threaded environments
Performance Optimized: Minimal overhead for high-frequency operations
Use Case: Check the current state of the managed GPIO
Usage Examples
Basic RAII Usage
1
2
3
4
5
6
7
8
9
10
11
12
// GPIO will be set active when guard is created{DigitalOutputGuardguard(my_gpio);if(!guard.IsValid()){// Handle initialization errorreturn;}// GPIO is now active and ready for use// ... perform operations ...}// GPIO automatically set inactive when guard goes out of scope
Manual State Control
1
2
3
4
5
6
7
8
9
10
11
12
DigitalOutputGuardguard(my_gpio);if(!guard.IsValid()){return;}// Manually control the GPIO stateguard.SetInactive();// Turn off// ... some operations ...guard.SetActive();// Turn back on// ... more operations ...// GPIO will be automatically set inactive when guard is destroyed
EspGpio*gpio_ptr=newEspGpio(pin,direction,active_state,output_mode,pull_mode);if(!gpio_ptr->EnsureInitialized()){deletegpio_ptr;return;}{DigitalOutputGuardguard(gpio_ptr);if(!guard.IsValid()){// Handle errordeletegpio_ptr;return;}// Use the GPIO through the guardguard.SetActive();// ... operations ...}// Guard ensures GPIO is set inactivedeletegpio_ptr;
Move Semantics
1
2
3
4
5
6
7
8
9
10
11
12
DigitalOutputGuardguard1(my_gpio);if(!guard1.IsValid()){return;}// Move the guard to another variableDigitalOutputGuardguard2=std::move(guard1);// guard1 is now in a moved-from state// guard2 now manages the GPIO// Use guard2guard2.SetActive();
Error Handling
The DigitalOutputGuard provides comprehensive error handling:
Common Error Codes
hf_gpio_err_t::GPIO_SUCCESS: Operation successful
hf_gpio_err_t::GPIO_ERR_NULL_POINTER: Null pointer provided to constructor
hf_gpio_err_t::GPIO_ERR_NOT_INITIALIZED: GPIO not properly initialized
hf_gpio_err_t::GPIO_ERR_DIRECTION_MISMATCH: GPIO not in output mode and ensure_output_mode=false
Error Handling Pattern
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DigitalOutputGuardguard(my_gpio);if(!guard.IsValid()){hf_gpio_err_terror=guard.GetLastError();switch(error){casehf_gpio_err_t::GPIO_ERR_NULL_POINTER:ESP_LOGE(TAG,"Null pointer provided");break;casehf_gpio_err_t::GPIO_ERR_NOT_INITIALIZED:ESP_LOGE(TAG,"GPIO not initialized");break;casehf_gpio_err_t::GPIO_ERR_DIRECTION_MISMATCH:ESP_LOGE(TAG,"GPIO direction mismatch");break;default:ESP_LOGE(TAG,"Unknown error: %d",static_cast<int>(error));break;}return;}
Performance Characteristics
The DigitalOutputGuard is optimized for performance:
Creation/Destruction: ~2-5 ฮผs per cycle on ESP32-C6
State Transitions: ~1-3 ฮผs per operation on ESP32-C6
Memory Overhead: Minimal (4 member variables)
Thread Safety: Safe for concurrent access
Thread Safety
The DigitalOutputGuard is thread-safe when used with thread-safe GPIO implementations:
Multiple guards can manage the same GPIO simultaneously
Each guard maintains its own state independently
No internal locking (relies on underlying GPIO thread safety)
Best Practices
Always Check Validity: Use IsValid() before performing operations
Scope Management: Use braces to control guard lifetime
Error Handling: Check GetLastError() for detailed error information
Resource Management: Ensure GPIO objects live longer than guards
Move Semantics: Use move operations for efficient resource transfer
Integration with Hardware Types
The DigitalOutputGuard integrates seamlessly with the HardFOC hardware abstraction:
Works with any BaseGpio implementation
Supports all GPIO directions, active states, and output modes
Compatible with ESP32, STM32, and other MCU implementations
Uses standard hf_gpio_err_t and hf_gpio_state_t types