This project simulates a task scheduler that executes tasks based on their dependencies. Tasks are represented as nodes in a directed acyclic graph (DAG), where edges represent dependencies between tasks. The scheduler ensures that tasks are executed in the correct order, respecting their dependencies. Additionally, the system supports concurrent execution of independent tasks using multithreading.
-
Task Representation:
- Each task has a unique ID, a description, and a list of dependencies (other task IDs it depends on).
- Tasks are stored in a dependency graph.
-
Dependency Resolution:
- The scheduler resolves task dependencies using topological sorting to determine the correct execution order.
- If a cycle is detected in the dependency graph, the scheduler reports an error.
-
Concurrent Execution:
- Independent tasks (tasks with no unresolved dependencies) are executed concurrently using a thread pool.
- A thread-safe task queue ensures safe access to shared resources.
-
STL Usage:
- Use
std::unordered_map
to store tasks and their dependencies. - Use
std::vector
andstd::queue
for topological sorting and task scheduling.
- Use
-
OOP Design:
- Encapsulate tasks and the scheduler in separate classes (
Task
andTaskScheduler
). - Use polymorphism to allow different types of tasks (e.g., computational tasks, I/O tasks).
- Encapsulate tasks and the scheduler in separate classes (
-
Error Handling:
- Handle invalid inputs, such as duplicate task IDs or cyclic dependencies.
- Provide meaningful error messages for debugging.
-
Optional SQL Integration:
- Store task definitions and execution logs in a Microsoft SQL Server database for persistence.
TaskScheduler/
├── include/
│ ├── Task.hpp // Task class definition
│ ├── TaskScheduler.hpp // Task scheduler class definition
│ └── ThreadPool.hpp // Thread pool for concurrent task execution
├── src/
│ ├── Task.cpp
│ ├── TaskScheduler.cpp
│ └── ThreadPool.cpp
├── main.cpp // Main entry point
├── CMakeLists.txt // Build configuration
└── README.md // Project documentation
-
Task Definition:
- Users define tasks and their dependencies in a configuration file or via the command line.
- Example:
Task A: No dependencies Task B: Depends on A Task C: Depends on A Task D: Depends on B, C
-
Dependency Resolution:
- The scheduler builds a dependency graph and performs topological sorting to determine the execution order.
-
Task Execution:
- The scheduler executes tasks in the correct order.
- Independent tasks are executed concurrently using a thread pool.
-
Logging:
- Execution logs are printed to the console or stored in a database for later analysis.
- A user defines four tasks:
- Task A: No dependencies.
- Task B: Depends on A.
- Task C: Depends on A.
- Task D: Depends on B and C.
- The scheduler determines the execution order: A → (B, C) → D.
- Tasks B and C are executed concurrently since they are independent of each other.
- Task D is executed only after both B and C are completed.
- STL:
std::unordered_map
,std::vector
,std::queue
,std::thread
,std::mutex
. - OOP: Encapsulation and modularity in designing
Task
andTaskScheduler
classes. - Multithreading: Concurrent execution of independent tasks using a thread pool.
- Graph Algorithms: Topological sorting for dependency resolution.
- SQL (Optional): Interaction with Microsoft SQL Server using ODBC for storing task definitions and logs.