For comprehensive documentation, visit our GitHub Pages:
- API Reference - Complete Doxygen-generated API documentation
- Getting Started - Installation and setup guide
- Usage Guide - Detailed usage examples and best practices
- Examples - Real-world code examples
- Quick Reference - Quick lookup guide for common tasks
- We needed to add asynchrony to our code.
- A periodic worker
- A resource pool
- A round robin pool
- A simple thread pool
- A simple worker pool
- The code here is a set of helpers that utilize the underlying deque, semaphore, mutex features found in std.
- Be instructive while providing functional code.
- Use only C++20 standard code: jthread, deque, semaphore, and concepts
- Depends on RunOnEnd for encapsulating cleanup code on destructor.
Requires C++20 support!
Specifically we require
jthreadandstop_tokensupport. This library works with GCC 10+, MSVC 16.11+, or Clang 10+.
The library uses concepts to ensure the type T meets move construct requirements.
#include "siddiqsoft/simple_worker.hpp"
#include <chrono>
#include <iostream>
#include <format>
// Define your data
struct MyWork
{
std::string urlDestination{};
std::string data{};
void operator()(){
// magic_post_to(urlDestination, data);
std::cout << "Processing: " << urlDestination << std::endl;
}
};
int main()
{
// Declare worker with our data type and the driver function.
siddiqsoft::simple_worker<MyWork> worker{[](auto& item){
// call the item's operator()
// to invoke actual work.
item();
}};
// Fire 100 items
for( int i=0; i < 100; i++ )
{
// Queues into the single worker
worker.queue({std::format("https://localhost:443/test?iter={}",i),
"hello-world"});
}
// As the user, you must control the lifetime of the worker
// Trying to delete the worker will cause it to stop
// and abandon any items in the internal deque.
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}#include "siddiqsoft/simple_pool.hpp"
#include <chrono>
#include <iostream>
#include <format>
int main()
{
// Declare worker with our data type and the driver function.
siddiqsoft::simple_pool<MyWork> worker{[](auto& item){
// call the item's operator()
// to invoke actual work.
item();
}};
// Fire 100 items
for( int i=0; i < 100; i++ )
{
// Queues into the single queue but multiple worker threads
// (defaults to CPU thread count)
worker.queue({std::format("https://localhost:443/test?iter={}",i),
"hello-world"});
}
// As the user, you must control the lifetime of the worker
// Trying to delete the worker will cause it to stop
// and abandon any items in the internal deque.
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}#include "siddiqsoft/roundrobin_pool.hpp"
#include <chrono>
#include <iostream>
#include <format>
int main()
{
// Declare worker with our data type and the driver function.
siddiqsoft::roundrobin_pool<MyWork> worker{[](auto& item){
// call the item's operator()
// to invoke actual work.
item();
}};
// Fire 100 items
for( int i=0; i < 100; i++ )
{
// Queues into the thread pools individual queue by round-robin
// across the threads with simple counter.
// (defaults to CPU thread count)
worker.queue({std::format("https://localhost:443/test?iter={}",i),
"hello-world"});
}
// As the user, you must control the lifetime of the worker
// Trying to delete the worker will cause it to stop
// and abandon any items in the internal deque.
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}Execute a function at regular intervals:
#include "siddiqsoft/periodic_worker.hpp"
#include <chrono>
#include <iostream>
int main()
{
// Create a periodic worker that executes every 500ms
siddiqsoft::periodic_worker<> timer{
[]() {
std::cout << "Tick!" << std::endl;
},
std::chrono::milliseconds(500)
};
// Keep the program running
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}Provides a basic resource pool useful for keeping a pool of connection objects for the various threadpools to checkout/checkin.
namespace siddiqsoft {
template<typename T>
class resource_pool {
public:
auto size(); // Get current pool size
[[nodiscard]] T checkout(); // Checkout a resource (throws if empty)
void checkin(T&& rsrc); // Return a resource to the pool
void clear(); // Clear all resources from the pool
};
}In order to use std::jthread on Clang 10 and later, we enable the compiler flag "CMAKE_CXX_FLAGS": "-fexperimental-library" in the CMakeLists.txt. This option will show up in your client library under Clang compilers.
Author: Siddiq Software LLC
© 2021 Siddiq Software LLC. All rights reserved.