Replace use of function pointers with Fn* traits#1685
Conversation
This commit replaces all instances of methods accepting `fn(_) -> _`
with `F: Fn(_) -> _`, for greater flexibility.
A new internal abstraction is introduced to facilitate this change:
`ThinBoxAny`, a type similar to `Option<Box<dyn Any>>` but stored in a
single pointer in order to avoid inflating the size of the `Connection`
type too much.
There are two exceptions, the deprecated `trace` and `profile`
functions. Users who need this flexibility should migrate to `trace_v2`
instead.
This change is, unfortunately, breaking. There are two ways in which it
breaks code:
+ Code that uses something like `.wal_hook(None)` will now get errors
because Rust cannot infer the type parameter of `F`. Users must now
write `.wal_hook(None::<fn(&Wal, _) -> _>)`.
+ Code that uses something like `.wal_hook(|hook, _| {})` will now fail,
because Rust’s type inference of closures in the presence of HRTBs is
limited. Instead, users should write `.wal_hook(|hook: &Wal, _| {})`.
The change is conservative for now, generally requiring `Fn` and `Sync`
even when this may not be strictly necessary. It is likely many of these
bounds can be relaxed in future.
Fixes: rusqlite#977
|
http://sqlite.org/c3ref/busy_timeout.html
And also:
|
|
I have added a commit to eagerly free old busy handlers if |
|
Idem:
Maybe we should not use |
|
Idem:
https://sqlite.org/c3ref/profile.html
|
The only risk is that at most one function becomes freed at a slightly later point than is optimal. But I don’t think this risk is significant, since:
I could update |
Except if a connection pool is used which is more likely.
I don't understand: if there is non-capturing closures, current |
Even if a connection pool is used, when that pool is pruned, or the pool itself is dropped, everything will be correctly freed. I mean, I would imagine that the overhead of keeping a DB connection alive is significantly greater than the overhead of one function that has potentially not been freed.
Yes, if there are no captures then In the vast majority of cases, users will set one callback and not override it, and so the question of whether this callback is freed is not important. In a small number of cases, users will change the callback through Rusqlite only, and thus it will be freed correctly. In another small number of cases, users will change the callback through first Rusqlite and then Sqlite itself, and in some of these cases it might be important that memory is freed eagerly. However, they can always do something like wrap closure’s state in a |
|
As a user I'd much rather take the risk of having the allocated Fn for longer if it means not having to do the ffi myself in order to have data in the callbacks |
|
There is a side-effect of using |
This commit replaces all instances of methods accepting
fn(_) -> _withF: Fn(_) -> _, for greater flexibility.A new internal abstraction is introduced to facilitate this change:
ThinBoxAny, a type similar toOption<Box<dyn Any>>but stored in a single pointer in order to avoid inflating the size of theConnectiontype too much.There are two exceptions, the deprecated
traceandprofilefunctions. Users who need this flexibility should migrate totrace_v2instead.This change is, unfortunately, breaking. There are two ways in which it breaks code:
.wal_hook(None)will now get errors because Rust cannot infer the type parameter ofF. Users must now write.wal_hook(None::<fn(&Wal, _) -> _>)..wal_hook(|hook, _| {})will now fail, because Rust’s type inference of closures in the presence of HRTBs is limited. Instead, users should write.wal_hook(|hook: &Wal, _| {}).The change is conservative for now, generally requiring
FnandSynceven when this may not be strictly necessary. It is likely many of these bounds can be relaxed in future.Fixes: #977