Components at a Glance
| Component | Use Case | Threads | Queue Type |
| simple_worker | Single async task | 1 | Shared |
| simple_pool | Parallel processing | N | Shared |
| roundrobin_pool | Load balancing | N | Per-thread |
| periodic_worker | Scheduled tasks | 1 | N/A |
| resource_pool | Resource management | N/A | N/A |
Include Files
#include "siddiqsoft/simple_worker.hpp"
#include "siddiqsoft/simple_pool.hpp"
#include "siddiqsoft/roundrobin_pool.hpp"
#include "siddiqsoft/periodic_worker.hpp"
#include "siddiqsoft/resource_pool.hpp"
Basic Patterns
Single Worker
[](auto&& task) { task.execute(); }
};
worker.
queue(std::move(task));
Implements a simple queue + semaphore driven asynchronous processor.
void queue(T &&item)
Queue item into this worker thread's deque.
Thread Pool
[](auto&& task) { task.execute(); }
};
for (
auto& t : tasks) pool.
queue(std::move(t));
Implements a single deque based vector of jthreads. All threads wait on the next available item via s...
void queue(T &&item)
Queue item into the deque (takes "ownership" of the item).
Round-Robin Pool
[](auto&& task) { task.execute(); }
};
for (
auto& t : tasks) pool.
queue(std::move(t));
Implements a lock-free round robin work allocation into vector of simple_worker<T>.
void queue(T &&item)
Queue item into one of the thread's queue.
Periodic Task
[]() { },
std::chrono::milliseconds(1000)
};
Implements a simple queue + semaphore driven asynchronous processor.
Resource Pool
auto res = pool.checkout();
Implements a resource pool that stores objects of type T. Said objects can be shared_ptr or unique_pt...
void checkin(T &&rsrc)
Insert a new element or return a borrowed element.
Template Parameters
simple_worker<T, Pri>
- T: Data type (must be move-constructible)
- Pri: Thread priority (-10 to +10, default 0)
simple_pool<T, N>
- T: Data type (must be move-constructible)
- N: Number of threads (0 = hardware_concurrency)
roundrobin_pool<T, N>
- T: Data type (must be move-constructible)
- N: Number of threads (0 = hardware_concurrency)
periodic_worker<Pri>
- Pri: Thread priority (-10 to +10, default 0)
resource_pool<T>
- T: Resource type (must be move-constructible)
Common Methods
queue(T&& item)
Queue an item for processing
worker.
queue(std::move(item));
toJson()
Get JSON representation (requires nlohmann/json)
auto json = worker.toJson();
std::cout << json.dump(2) << std::endl;
checkout() / checkin()
Resource pool operations
auto resource = pool.checkout();
size()
Get current pool size
auto size()
Get the current size of the pool FIX: Removed unnecessary empty check - return size unconditionally T...
clear()
Clear all resources from pool
void clear()
Clear all items from the pool FIX: Removed unnecessary empty check - clear() is safe on empty deque.
Requirements
- C++20 or later
- Compiler: GCC 10+, MSVC 16.11+, Clang 10+
- Platform: Windows, Linux, macOS
- Dependencies: None (header-only for core functionality)
- Optional: nlohmann/json for JSON serialization
Compilation
GCC/Clang:
g++ -std=c++20 -pthread your_file.cpp
clang++ -std=c++20 -fexperimental-library -pthread your_file.cpp
MSVC:
cl /std:c++20 your_file.cpp
CMake:
target_link_libraries(your_target PRIVATE asynchrony::asynchrony)
Tips & Tricks
- Keep callbacks lightweight - Avoid blocking operations
- Use move semantics - Always move items into the queue
- Handle exceptions - Catch exceptions in callbacks
- Monitor queue depth - Check for bottlenecks using toJson()
- Choose right pool type - Use roundrobin for variable-duration tasks
- Lifetime management - Keep worker/pool alive while queuing
- Thread priority - Use carefully, may affect system performance
- Resource pool capacity - Set to match thread pool size for optimal performance
Common Issues
| Issue | Solution |
| Compilation error: jthread not found | Use C++20 or later |
| Tasks not executing | Ensure worker/pool is not destroyed |
| High CPU usage | Increase wait timeout or reduce threads |
| Deadlock | Avoid circular dependencies in callbacks |
| Memory leak | Ensure proper RAII cleanup |
| checkout() throws | Pool is empty, add resources first |
| Clang compilation fails | Add -fexperimental-library flag |
Performance Tips
- CPU-bound tasks: Use threads = hardware_concurrency()
- I/O-bound tasks: Use threads > hardware_concurrency()
- Batch small tasks: Reduce overhead
- Use roundrobin: For variable-duration tasks
- Monitor metrics: Use toJson() to track queue depth
- Avoid blocking: Keep callbacks fast and non-blocking
Quick Examples
Example 1: Simple Async Task
[](auto&& msg) { std::cout << msg << std::endl; }
};
worker.
queue(
"Hello, World!");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
Example 2: Parallel Processing
[](auto&& num) { std::cout << num * 2 << std::endl; }
};
for (
int i = 0; i < 100; ++i) pool.
queue(i);
std::this_thread::sleep_for(std::chrono::seconds(1));
Example 3: Periodic Monitoring
[]() { std::cout << "Tick!" << std::endl; },
std::chrono::seconds(1)
};
std::this_thread::sleep_for(std::chrono::seconds(10));
Example 4: Resource Management
auto conn = pool.checkout();
conn.query("SELECT * FROM users");
JSON Output Format
When calling toJson() on workers, the output includes:
{
"_typver": "siddiqsoft.asynchrony-lib.simple_worker/0.10",
"itemsSize": 5,
"queueCounter": 100,
"itemsQueued": 100,
"itemsPopped": 95,
"itemsOutstanding": 5,
"threadPriority": 0,
"outstandingCallback": 1,
"waitInterval": 1500
}