Skip to content

MoMo790-m/CoreTaskOrchestrator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

Repository files navigation

CoreTaskOrchestrator

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).


Problem Statement

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.

Key Features

  • Heterogeneous task model

    • Abstract BaseTask interface with concrete CpuBoundTask, IoBoundTask, and NetworkBoundTask.
    • Tasks carry IDs, priorities, and types, enabling flexible scheduling policies.
  • Custom data structures

    • MinHeap implementation used as a priority queue for task scheduling.
    • TaskDAG using adjacency lists and in‑degree tracking for topological sort and cycle detection.
  • Advanced OOP and design patterns

    • Singleton: Scheduler as the global orchestrator with a single instance.
    • Strategy: SchedulingStrategy interface with PrioritySchedulingStrategy and RoundRobinSchedulingStrategy implementations, swappable at runtime.
    • Observer: ITaskObserver interface implemented by Scheduler; WorkerNode notifies on task completion/failure.
    • Encapsulation: WorkerNode hides internal state (queues, telemetry) behind clear interfaces and mutex‑protected accessors.
  • OS & concurrency integration

    • Thread‑pool of WorkerNodes, each owning a work queue and executing tasks in a loop.
    • Use of std::thread, std::mutex, and std::condition_variable to implement a classic producer–consumer model.
    • ResourceMonitor for periodic CPU and memory sampling, enabling backpressure when utilization exceeds thresholds (full metrics on Linux; stubbed on Windows with room to extend).
  • 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.

Project Structure

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.


Installation & Build

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.

Prerequisites

  • 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>.
  • For Windows:
    • The core scheduler and thread‑pool work as-is; resource metrics are stubbed and can be extended via WinAPI if desired.

Option 1: Build with CMake (recommended)

From the project root:

mkdir build
cd build
cmake ..
cmake --build .

This will produce an executable named radto (or radto.exe on Windows).

Option 2: Manual compilation (example with g++)

From the project root:

g++ -std=c++17 -pthread src/main.cpp -Iinclude -o radto

On Windows with MinGW, adjust the output name if desired:

g++ -std=c++17 -pthread src/main.cpp -Iinclude -o radto.exe

Usage

The provided src/main.cpp demonstrates how to:

  1. Configure the scheduler and worker pool.
  2. Choose a scheduling strategy.
  3. Submit a large workload of heterogeneous tasks.
  4. Observe the runtime dashboard and completion statistics.

Running the example

After building:

./radto          # or .\radto.exe on Windows

You 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).

Switching scheduling strategies

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.

Integrating into your own project

To embed CoreTaskOrchestrator into another application:

  1. Add include/radto/ to your include path.
  2. Include the aggregator header:
#include "radto/radto.hpp"
  1. 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.


Design & Implementation Details

  • Thread safety

    • All shared state (task maps, status maps, worker queues) is protected with std::mutex and std::condition_variable.
    • The scheduler runs separate threads for dispatch and dashboard logging, coordinating with worker threads via the observer pattern.
  • 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.
  • Backpressure

    • The dispatch loop periodically queries ResourceMonitor before 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.
  • Load balancing

    • LoadBalancer implements a Least Connections strategy, always assigning the next task to the worker with the fewest active tasks.

Extending the Project

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.

Notes on Platform Support

  • 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.
  • 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 GetProcessMemoryInfo and GetSystemTimes.

License

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.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors 2

  •  
  •