Skip to content

Latest commit

 

History

History
100 lines (76 loc) · 3.77 KB

File metadata and controls

100 lines (76 loc) · 3.77 KB

Contributing to Taskflow Internals


10. Repository Map

taskflow/          Header-only library implementation (highest risk)
unittests/         doctest-based tests
examples/          Usage examples and API demonstrations
benchmarks/        Performance measurement harnesses
tfprof/            Profiler components
doxygen/           Documentation source
docs/              Generated documentation (treat as output)
.github/workflows/ CI workflows
3rd-party/         Vendored dependencies (avoid edits)

11. Build and Test

Baseline Validation (minimum for any code change)

cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=20
cmake --build build --parallel 10
cd build && ctest --output-on-failure

Thread Sanitizer (required when touching taskflow/core/)

cmake -S . -B build_tsan \
  -DCMAKE_CXX_FLAGS="-fsanitize=thread -g" \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_CXX_STANDARD=20
cmake --build build_tsan --parallel 10
cd build_tsan && ctest --output-on-failure

Fresh build directory per sanitizer. ASan/UBSan follow the same pattern.

12. Architecture Overview

Execution model:

  1. User builds a Taskflow (owns a Graph of Nodes) via FlowBuilder.
  2. Executor::run() creates a Topology and schedules root nodes.
  3. Workers run a work-stealing loop: drain local BoundedWSQ, then steal or park via the Notifier 2PC protocol (prepare_wait → check → commit_wait or cancel_wait).
  4. _invoke dispatches each Node by its handle_t variant index (10 task types).
  5. When all nodes complete, _tear_down_topology signals the tf::Future.

Key ownership: Executor owns workers + buffers + notifier. Taskflow extends FlowBuilder and owns the Graph. Node holds a handle_t (std::variant of work types).

13. Risk Classes and Hot Paths

Risk Files Hot-path functions
High taskflow/core/*, algorithm/* _exploit_task, _explore_task, _invoke, _schedule
Medium unittests/*, examples/*
Low doxygen/*, docs/*, metadata

When modifying hot paths: avoid heap allocations, respect alignas(TF_CACHELINE_SIZE), preserve memory orderings.

14. Change Workflow

  1. Classify — bug fix, feature, refactor, performance, or tests/docs.
  2. Scope — identify files/directories before editing.
  3. Implement — minimal, focused diffs. No unrelated cleanup.
  4. Validate — baseline tests. TSan for core changes.
  5. Report — changed files, commands, results, risk notes.

15. Concurrency Rules

  • Always run TSan when modifying taskflow/core/.
  • Prefer acquire/release orderings; avoid relaxed without TSan proof.
  • No blocking synchronization (mutex, condition_variable) in the worker hot loop.
  • Respect alignas(TF_CACHELINE_SIZE) on Executor/Worker fields (false sharing).

16. Key Pitfalls

  • Weakening memory orderings without TSan — races manifest only under load.
  • Adding fields to Executor/Worker without cache-line alignment — false sharing.
  • Forgetting notify_one() after scheduling — lost wakeup, parked workers never run.
  • Forgetting cancel_wait() after prepare_wait() — thread deadlock.
  • Heap allocations in _exploit_task/_explore_task/_invoke — kills throughput.
  • Changing Node::handle_t variant without updating _invoke switch and index constants.
  • Assuming .cpp source files exist — Taskflow is entirely header-only.

17. Safety Rules

  • Do not modify 3rd-party/ unless explicitly requested.
  • Do not include unrelated refactors in scoped changes.
  • Do not claim validation passed without running the commands.

Agent output contract:

  1. Files changed and why
  2. Validation commands executed and outcomes
  3. Known limitations or follow-up items