1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// src/include/duckdb/parallel/interrupt.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/atomic.hpp"
12#include "duckdb/common/mutex.hpp"
13#include "duckdb/parallel/task.hpp"
14#include <condition_variable>
15#include <memory>
16
17namespace duckdb {
18
19//! InterruptMode specifies how operators should block/unblock, note that this will happen transparently to the
20//! operator, as the operator only needs to return a BLOCKED result and call the callback using the InterruptState.
21//! NO_INTERRUPTS: No blocking mode is specified, an error will be thrown when the operator blocks. Should only be used
22//! when manually calling operators of which is known they will never block.
23//! TASK: A weak pointer to a task is provided. On the callback, this task will be signalled. If the Task has
24//! been deleted, this callback becomes a NOP. This is the preferred way to await blocked pipelines.
25//! BLOCKING: The caller has blocked awaiting some synchronization primitive to wait for the callback.
26enum class InterruptMode : uint8_t { NO_INTERRUPTS, TASK, BLOCKING };
27
28//! Synchronization primitive used to await a callback in InterruptMode::BLOCKING.
29struct InterruptDoneSignalState {
30 //! Called by the callback to signal the interrupt is over
31 void Signal();
32 //! Await the callback signalling the interrupt is over
33 void Await();
34
35protected:
36 mutex lock;
37 std::condition_variable cv;
38 bool done = false;
39};
40
41//! State required to make the callback after some asynchronous operation within an operator source / sink.
42class InterruptState {
43public:
44 //! Default interrupt state will be set to InterruptMode::NO_INTERRUPTS and throw an error on use of Callback()
45 InterruptState();
46 //! Register the task to be interrupted and set mode to InterruptMode::TASK, the preferred way to handle interrupts
47 InterruptState(weak_ptr<Task> task);
48 //! Register signal state and set mode to InterruptMode::BLOCKING, used for code paths without Task.
49 InterruptState(weak_ptr<InterruptDoneSignalState> done_signal);
50
51 //! Perform the callback to indicate the Interrupt is over
52 DUCKDB_API void Callback() const;
53
54protected:
55 //! Current interrupt mode
56 InterruptMode mode;
57 //! Task ptr for InterruptMode::TASK
58 weak_ptr<Task> current_task;
59 //! Signal state for InterruptMode::BLOCKING
60 weak_ptr<InterruptDoneSignalState> signal_state;
61};
62
63} // namespace duckdb
64