ThreadSchedule provides comprehensive error handling for asynchronous tasks with support for error callbacks and better exception management.
Features
- ✅ Global error callbacks - Handle all exceptions in one place
- ✅ Per-future error callbacks - Handle specific task errors
- ✅ Error context - Get detailed information about errors (task description, thread ID, timestamp)
- ✅ Thread-safe - Error handlers work correctly across threads
- ✅ Non-intrusive - Original thread pools remain unchanged
Quick Start
using namespace threadschedule;
int main() {
pool.add_error_callback([](
const TaskError& error) {
std::cerr <<
"Task error: " << error.
what() <<
"\n";
});
auto future = pool.submit([]() {
throw std::runtime_error("Something failed");
return 42;
});
try {
future.get();
} catch (const std::exception& e) {
}
}
Information about a task exception.
auto what() const -> std::string
Get the exception message if it's a std::exception.
Modern C++23 Thread Scheduling Library.
Thread Pool Variants
HighPerformancePoolWithErrors
High-performance work-stealing pool with error handling.
pool.add_error_callback([](
const TaskError& error) {
});
auto future = pool.submit([]() {
});
FastThreadPoolWithErrors
Single-queue pool with error handling.
pool.add_error_callback([](
const TaskError& error) {
std::cerr << error.
what() <<
"\n";
});
Fast thread pool with built-in error handling.
ThreadPoolWithErrors
Simple general-purpose pool with error handling.
pool.add_error_callback([](
const TaskError& error) {
handle_error(error);
});
Simple thread pool with built-in error handling.
Error Callbacks
Global Error Callbacks
Global callbacks are invoked for every task that throws an exception:
pool.add_error_callback([](
const TaskError& error) {
std::cerr <<
"[ERROR] " << error.
what() <<
"\n";
std::cerr << "Thread: " << error.thread_id << "\n";
std::cerr << "Time: " << error.timestamp.time_since_epoch().count() << "\n";
if (!error.task_description.empty()) {
std::cerr << "Task: " << error.task_description << "\n";
}
});
Per-Future Error Callbacks
Handle errors for specific tasks:
auto future = pool.submit(risky_task)
.on_error([](std::exception_ptr eptr) {
try {
std::rethrow_exception(eptr);
} catch (const std::runtime_error& e) {
std::cerr << "Runtime error: " << e.what() << "\n";
} catch (const std::logic_error& e) {
std::cerr << "Logic error: " << e.what() << "\n";
}
});
try {
future.get();
} catch (...) {
}
Task Descriptions
Add descriptions to tasks for better error messages:
auto future = pool.submit_with_description(
"Database Query",
[]() {
return query_database();
}
);
Error output will include:
[ERROR] Connection timeout
Thread: 139745814427328
Task: Database Query
TaskError Structure
std::exception_ptr exception;
std::string task_description;
std::thread::id thread_id;
std::chrono::steady_clock::time_point timestamp;
[[nodiscard]] auto what() const -> std::string;
void rethrow() const;
};
FutureWithErrorHandler
Extended future with error callback support:
template <typename T>
auto on_error(std::function<void(std::exception_ptr)> callback)
auto get() -> T;
void wait() const;
template<typename Rep, typename Period>
auto wait_for(std::chrono::duration<Rep, Period> const&) const;
template<typename Clock, typename Duration>
auto wait_until(std::chrono::time_point<Clock, Duration> const&) const;
[[nodiscard]] auto valid() const -> bool;
};
Future wrapper that provides error callback support.
Error Statistics
Track error counts:
std::cout << "Errors: " << pool.error_count() << "\n";
pool.reset_error_count();
pool.clear_error_callbacks();
Complete Example
#include <iostream>
#include <fstream>
using namespace threadschedule;
class ErrorLogger {
public:
std::ofstream file("errors.log", std::ios::app);
file << "[" << error.timestamp.time_since_epoch().count() << "] ";
file << error.what();
if (!error.task_description.empty()) {
file << " (Task: " << error.task_description << ")";
}
file << "\n";
}
};
int main() {
ErrorLogger logger;
pool.add_error_callback([&logger](
const TaskError& error) {
logger.log(error);
std::cerr << "Error logged: " << error.what() << "\n";
});
std::vector<FutureWithErrorHandler<int>> futures;
for (int i = 0; i < 10; i++) {
futures.push_back(
pool.submit_with_description(
"Task " + std::to_string(i),
[i]() {
if (i % 3 == 0) {
throw std::runtime_error("Task " + std::to_string(i) + " failed");
}
return i * 10;
}
)
);
}
int successful = 0;
int failed = 0;
for (auto& future : futures) {
try {
int result = future.get();
std::cout << "Success: " << result << "\n";
successful++;
} catch (const std::exception& e) {
std::cerr << "Failed: " << e.what() << "\n";
failed++;
}
}
std::cout << "\n=== Summary ===\n";
std::cout << "Successful: " << successful << "\n";
std::cout << "Failed: " << failed << "\n";
std::cout << "Total errors: " << pool.error_count() << "\n";
pool.shutdown();
return 0;
}
Advanced Usage
Custom Error Handler
public:
}
}
};
auto handler = std::make_shared<CustomErrorHandler>();
handler->add_callback([&handler](
const TaskError& error) {
handler->log_to_syslog(error);
if (error.what().find("CRITICAL") != std::string::npos) {
handler->send_alert(error);
}
});
Global error handler for thread pool tasks.
Error Classification
pool.add_error_callback([](
const TaskError& error) {
try {
error.rethrow();
} catch (const std::system_error& e) {
handle_system_error(e);
} catch (const std::runtime_error& e) {
handle_runtime_error(e);
} catch (const std::logic_error& e) {
handle_logic_error(e);
} catch (...) {
handle_unknown_error();
}
});
Retry Logic
template <typename F>
for (int attempt = 0; attempt < max_retries; attempt++) {
try {
return pool.
submit(std::forward<F>(func)).get();
} catch (const std::exception& e) {
if (attempt == max_retries - 1) {
throw;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100 * (attempt + 1)));
}
}
throw std::runtime_error("All retries exhausted");
}
Best Practices
- Always add error callbacks - Don't let exceptions go unnoticed
- Use task descriptions - Make debugging easier
- Log errors - Keep track of what went wrong
- Handle exceptions in .get() - Callbacks don't prevent exception propagation
- Clean up callbacks - Call clear_error_callbacks() when done
See Also