|
10 | 10 | #include <erl_nif.h> |
11 | 11 | #include <sqlite3.h> |
12 | 12 |
|
13 | | -// --------------------------------------------------------------------------- |
14 | 13 | // Platform timed-wait abstraction |
15 | 14 | // |
16 | | -// We need pthread_cond_timedwait / SleepConditionVariableCS because OTP's |
17 | | -// enif_cond does not expose a timed wait (deliberate omission due to clock |
18 | | -// jump safety concerns in telecom). BEAM has exactly two threading backends |
19 | | -// (pthreads and Win32), so #ifdef _WIN32 covers 100% of supported platforms. |
20 | | -// --------------------------------------------------------------------------- |
| 15 | +// OTP doesn't provide enif_cond_timedwait, so we wrap pthread_cond_timedwait |
| 16 | +// (POSIX) and SleepConditionVariableCS (Windows). BEAM has two threading |
| 17 | +// backends (pthreads and Win32), so #ifdef _WIN32 covers all platforms. |
21 | 18 |
|
22 | 19 | #ifdef _WIN32 |
23 | 20 | #include <windows.h> |
@@ -63,8 +60,7 @@ typedef struct { |
63 | 60 | static void tw_init(timed_wait_t* tw) |
64 | 61 | { |
65 | 62 | pthread_mutex_init(&tw->mtx, NULL); |
66 | | - // Use CLOCK_REALTIME (the default) because macOS doesn't support |
67 | | - // pthread_condattr_setclock(CLOCK_MONOTONIC). |
| 63 | + // CLOCK_REALTIME: macOS doesn't support CLOCK_MONOTONIC for condvars |
68 | 64 | pthread_cond_init(&tw->cond, NULL); |
69 | 65 | } |
70 | 66 |
|
@@ -141,11 +137,11 @@ typedef struct connection |
141 | 137 | ErlNifPid update_hook_pid; |
142 | 138 |
|
143 | 139 | // Custom busy handler state |
144 | | - timed_wait_t cancel_tw; // condvar for cancellable busy waits |
145 | | - volatile int cancelled; // 1 = cancel requested (volatile for MSVC compat) |
146 | | - int busy_timeout_ms; // total busy timeout in milliseconds |
147 | | - ErlNifEnv* callback_env; // env for enif_is_process_alive checks |
148 | | - ErlNifPid caller_pid; // pid of the process that started the current op |
| 140 | + timed_wait_t cancel_tw; |
| 141 | + volatile int cancelled; // volatile for MSVC compat |
| 142 | + int busy_timeout_ms; |
| 143 | + ErlNifEnv* callback_env; // for enif_is_process_alive |
| 144 | + ErlNifPid caller_pid; |
149 | 145 | } connection_t; |
150 | 146 |
|
151 | 147 | typedef struct statement |
@@ -1766,11 +1762,8 @@ exqlite_interrupt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) |
1766 | 1762 | } |
1767 | 1763 |
|
1768 | 1764 | /// |
1769 | | -/// Set the busy timeout without destroying the custom busy handler. |
1770 | | -/// |
1771 | | -/// Unlike PRAGMA busy_timeout (which internally calls sqlite3_busy_timeout() |
1772 | | -/// and replaces any custom handler), this NIF only updates the timeout value |
1773 | | -/// that our custom handler reads. |
| 1765 | +/// Set busy timeout without destroying the custom handler. |
| 1766 | +/// (PRAGMA busy_timeout calls sqlite3_busy_timeout() which replaces handlers) |
1774 | 1767 | /// |
1775 | 1768 | ERL_NIF_TERM |
1776 | 1769 | exqlite_set_busy_timeout(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) |
@@ -1800,11 +1793,8 @@ exqlite_set_busy_timeout(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) |
1800 | 1793 | return am_ok; |
1801 | 1794 | } |
1802 | 1795 |
|
1803 | | -/// |
1804 | | -/// Cancel a running query: wake the busy handler and interrupt VDBE execution. |
1805 | | -/// |
1806 | | -/// This is a superset of interrupt/1 — it sets the cancel flag, signals the |
1807 | | -/// condvar to wake any busy handler sleep, AND calls sqlite3_interrupt(). |
| 1796 | +/// Cancel: wake busy handler + interrupt VDBE. |
| 1797 | +/// Superset of interrupt/1: sets flag, signals condvar, calls sqlite3_interrupt(). |
1808 | 1798 | /// |
1809 | 1799 | ERL_NIF_TERM |
1810 | 1800 | exqlite_cancel(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) |
|
0 commit comments