Inside the companion
Renderer Engineering
Explore bounded image work, allocator lifetimes, cancellation, and Asio coroutines.
Project files 15
Bound a batch of work
Jobs, options, results, and the blocking batch interface.
#pragma once
#include <condition_variable>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <memory>
#include <mutex>
#include <optional>
#include <stop_token>
#include <vector>
namespace prism_engineering {
inline constexpr std::size_t max_jobs = 32;
inline constexpr std::size_t max_samples_per_job = 4096;
inline constexpr std::size_t max_workers = 8;
// A deterministic admission gate, useful for testing cancellation before work.
// shared_ptr ownership in Options keeps the gate alive until every worker
// joins.
class WorkGate {
public:
bool arrive_and_wait(std::stop_token stop);
bool wait_for_arrivals(std::size_t count, std::stop_token stop = {});
void open();
private:
std::mutex mutex_;
std::condition_variable_any changed_;
std::size_t arrivals_{};
bool open_{};
};
struct Job {
std::uint64_t generation{};
std::vector<std::uint32_t> samples; // Queued payload owns its storage.
bool inject_failure{}; // Explicit experiment seam, not an external callback.
};
enum class Status { pending, succeeded, cancelled, failed };
struct Result {
std::uint64_t generation{};
Status status{Status::pending};
std::uint64_t checksum{};
};
struct Options {
std::size_t workers{2};
std::shared_ptr<WorkGate> gate;
// Test seam: simulate failure before launching worker N (zero-based).
// The default launches normally; values >= workers do not trigger it.
std::optional<std::size_t> fail_launch_after{};
};
struct Report {
std::vector<Result>
results; // One fixed slot per accepted job, no growing result queue.
std::size_t peak_active{};
};
enum class Error {
invalid_worker_count,
too_many_jobs,
payload_too_large,
allocation,
thread_start,
worker_runtime
};
// The caller transfers a bounded batch into this function. Workers execute
// asynchronously, but this orchestration call returns ONLY after joining them.
// Cancellation is cooperative; it does not interrupt arbitrary blocking I/O.
[[nodiscard]] std::expected<Report, Error>
run_batch(std::vector<Job> owned_jobs, Options options = {},
std::stop_token cancellation = {});
// A generation check is a policy on values, not a claim that cancellation
// undoes work. The caller applies it before publishing a result to the current
// asset.
[[nodiscard]] bool accepts(const Result &result,
std::uint64_t current_generation) noexcept;
} // namespace prism_engineering
This is the file included with the course. Copy and download give you its complete source.
Taking your work offline? Download all course companions
