CoreTaskOrchestrator is a high-performance C++ task orchestration engine designed to schedule, execute, and monitor large volumes of heterogeneous tasks (CPU‑bound, I/O‑bound, and network‑bound) on a resource‑constrained machine. It demonstrates advanced Object‑Oriented Design, custom Data Structures & Algorithms, and low‑level OS‑aware concurrency primitives.
The project is intentionally built without high‑level task frameworks to showcase mastery of core concepts such as custom heaps, DAG‑based dependency management, thread pools, backpressure, and classic design patterns (Singleton, Strategy, Observer).
Modern systems often need to process tens of thousands of concurrent workloads with different characteristics (CPU, I/O, networking) while:
- Respecting inter‑task dependencies.
- Maintaining high throughput on limited hardware.
- Avoiding oversubscription of CPU and memory.
- Remaining predictable, debuggable, and testable.
CoreTaskOrchestrator addresses this by providing:
- A resource‑aware scheduler that applies backpressure when system utilization is high.
- A pluggable scheduling strategy layer (priority‑based vs. round‑robin).
- A thread‑pool–based worker layer that executes heterogeneous tasks safely and efficiently.
- A DAG‑based dependency graph to enforce valid execution order and detect deadlocks.
-
Heterogeneous task model
- Abstract
BaseTaskinterface with concreteCpuBoundTask,IoBoundTask, andNetworkBoundTask. - Tasks carry IDs, priorities, and types, enabling flexible scheduling policies.
- Abstract
-
Custom data structures
MinHeapimplementation used as a priority queue for task scheduling.TaskDAGusing adjacency lists and in‑degree tracking for topological sort and cycle detection.
-
Advanced OOP and design patterns
- Singleton:
Scheduleras the global orchestrator with a single instance. - Strategy:
SchedulingStrategyinterface withPrioritySchedulingStrategyandRoundRobinSchedulingStrategyimplementations, swappable at runtime. - Observer:
ITaskObserverinterface implemented byScheduler;WorkerNodenotifies on task completion/failure. - Encapsulation:
WorkerNodehides internal state (queues, telemetry) behind clear interfaces and mutex‑protected accessors.
- Singleton:
-
OS & concurrency integration
- Thread‑pool of
WorkerNodes, each owning a work queue and executing tasks in a loop. - Use of
std::thread,std::mutex, andstd::condition_variableto implement a classic producer–consumer model. ResourceMonitorfor periodic CPU and memory sampling, enabling backpressure when utilization exceeds thresholds (full metrics on Linux; stubbed on Windows with room to extend).
- Thread‑pool of
-
Scalability & stress testing
- Built‑in stress test that submits 10,000+ mixed tasks, validates dependency handling, and exercises scheduling strategies.
- Live textual dashboard showing PENDING/RUNNING/DONE counts and approximate resource usage over time.
The project is organized to separate concerns cleanly and keep each concept in its own header:
CoreTaskOrchestrator/
├─ CMakeLists.txt # CMake configuration (optional if building manually)
├─ README.md # Project documentation (this file)
├─ include/
│ └─ radto/
│ ├─ Common.hpp # Shared types (TaskId, enums) and time utility
│ ├─ Task.hpp # BaseTask + CpuBoundTask, IoBoundTask, NetworkBoundTask
│ ├─ MinHeap.hpp # Custom binary min-heap used for priority scheduling
│ ├─ TaskDAG.hpp # DAG for inter-task dependencies and topological sort
│ ├─ ResourceMonitor.hpp # Lightweight CPU/Memory usage sampling
│ ├─ Observer.hpp # ITaskObserver interface for completion/failure callbacks
│ ├─ WorkerNode.hpp # Threaded worker node with its own queue and telemetry
│ ├─ SchedulingStrategy.hpp# Strategy interface + Priority/Round-Robin implementations
│ ├─ LoadBalancer.hpp # Least-connections load balancer across WorkerNodes
│ ├─ Scheduler.hpp # Singleton orchestrator, DAG integration, dashboard
│ └─ radto.hpp # Aggregator convenience header (includes all of the above)
└─ src/
└─ main.cpp # Example entry point + 10,000-task stress test
You typically only need to include radto/radto.hpp from your own code.
CoreTaskOrchestrator is a header‑only library plus a small example executable. You can either:
- Use the provided CMake configuration, or
- Compile manually with your C++17 compiler.
- A C++17‑capable compiler (e.g.
g++ >= 9,clang++ >= 9, MSVC with C++17). - For Linux resource monitoring (recommended to see CPU/MEM metrics):
- POSIX headers:
<sys/resource.h>,<sys/sysinfo.h>.
- POSIX headers:
- For Windows:
- The core scheduler and thread‑pool work as-is; resource metrics are stubbed and can be extended via WinAPI if desired.
From the project root:
mkdir build
cd build
cmake ..
cmake --build .This will produce an executable named radto (or radto.exe on Windows).
From the project root:
g++ -std=c++17 -pthread src/main.cpp -Iinclude -o radtoOn Windows with MinGW, adjust the output name if desired:
g++ -std=c++17 -pthread src/main.cpp -Iinclude -o radto.exeThe provided src/main.cpp demonstrates how to:
- Configure the scheduler and worker pool.
- Choose a scheduling strategy.
- Submit a large workload of heterogeneous tasks.
- Observe the runtime dashboard and completion statistics.
After building:
./radto # or .\radto.exe on WindowsYou will see periodic log lines similar to:
[HH:MM:SS] PENDING=... RUNNING=... DONE=... CPU~X% MEM~Y%
Final completed tasks: 10000
These show:
- PENDING: Tasks not yet assigned to workers (includes READY).
- RUNNING: Tasks currently executing on worker threads.
- DONE: Tasks that completed successfully or failed.
- CPU / MEM: Approximate process CPU and memory utilization (on Linux).
In src/main.cpp:
- Priority-based scheduling (default):
Scheduler& sched = Scheduler::instance();
sched.setStrategy(std::make_unique<PrioritySchedulingStrategy>());- Round-Robin scheduling:
Scheduler& sched = Scheduler::instance();
sched.setStrategy(std::make_unique<RoundRobinSchedulingStrategy>());Rebuild and rerun to observe behavioral differences under load.
To embed CoreTaskOrchestrator into another application:
- Add
include/radto/to your include path. - Include the aggregator header:
#include "radto/radto.hpp"- Initialize and use the scheduler:
using namespace radto;
int main() {
Scheduler& sched = Scheduler::instance();
// Choose strategy at runtime
sched.setStrategy(std::make_unique<PrioritySchedulingStrategy>());
// Initialize worker pool
unsigned int hw = std::thread::hardware_concurrency();
if (hw == 0) hw = 4;
sched.initWorkers(static_cast<int>(hw));
// Create and submit tasks
auto task = std::make_shared<CpuBoundTask>(0, /*priority=*/10, /*iterations=*/5000);
sched.submitTask(task);
// Start orchestrator
sched.start();
// Wait for completion (in a real app, integrate with your own lifecycle)
// ...
sched.shutdown();
}You can also build your own BaseTask subclasses to model domain‑specific work.
-
Thread safety
- All shared state (task maps, status maps, worker queues) is protected with
std::mutexandstd::condition_variable. - The scheduler runs separate threads for dispatch and dashboard logging, coordinating with worker threads via the observer pattern.
- All shared state (task maps, status maps, worker queues) is protected with
-
Dependency management & deadlock prevention
- Dependencies are stored in
TaskDAG. - A topological sort is computed before dispatch begins.
- If a cycle is detected, the scheduler throws an exception, preventing undefined behavior and making deadlocks explicit.
- Dependencies are stored in
-
Backpressure
- The dispatch loop periodically queries
ResourceMonitorbefore assigning work. - If CPU or memory utilization exceed defined thresholds (e.g., 90%), the scheduler temporarily pauses dispatching new tasks, allowing the system to recover.
- The dispatch loop periodically queries
-
Load balancing
LoadBalancerimplements a Least Connections strategy, always assigning the next task to the worker with the fewest active tasks.
Here are some natural extensions if you want to evolve CoreTaskOrchestrator further:
- Additional scheduling strategies
- Earliest Deadline First (EDF), Weighted Round Robin, Multi‑level Feedback Queue, etc.
- Richer task types
- Tasks with explicit deadlines, SLAs, or resource hints (e.g., estimated runtime, memory footprint).
- Persistence & fault tolerance
- Periodically checkpoint task states to disk or a database and recover in case of process restarts.
- Metrics and observability
- Expose metrics via HTTP/JSON or integrate with Prometheus/Grafana for richer dashboards.
-
Linux/Unix
- Full resource monitoring via
<sys/resource.h>and<sys/sysinfo.h>. - Recommended platform if you want to observe real CPU/MEM backpressure behavior.
- Full resource monitoring via
-
Windows
- Scheduler, thread pool, and data structures work normally.
- Resource monitoring is currently a stub (returns 0s). It can be extended using WinAPI calls such as
GetProcessMemoryInfoandGetSystemTimes.
This project is intended primarily as an educational and portfolio example.
Add your preferred license (e.g., MIT, Apache‑2.0) to this repository if you plan to use it in production or share it publicly.