Boost logo

Boost :

From: Phil Endecott (spam_from_boost_dev_at_[hidden])
Date: 2024-01-06 15:15:27


Dominique Devienne wrote:
> On Fri, Jan 5, 2024 at 2:15 PM Phil Endecott via Boost <boost_at_[hidden]> wrote:
>
>> What do you do about multi-threaded usage?
>
> Hi. What is there to do Phil?

I mentioned this because it is something that I got burned by recently.
The sqlite docs are now improved after my feedback. Having the wrapper
assert() if it detects non-thread-safe usage would be useful. I don't
know how feasible that is.

> [...] use one connection per thread

Yes, this is likely the best approach in most cases. You might also
consider a connection pool. Could a generalised connection pool be
something of value in Boost? I may have mentioned this before in
relation to MySQL.

On another subject, I note that the proposed API extensively uses
string_view as a function return type. For example, field::column_name()
returns a string_view. I consider this an anti-pattern. (In case anyone
doesn't understand the issue, the danger is that the view will be
dangling if the caller keeps it beyond the life of... some other object;
I was going to write "the field object", but I'm not sure if that's
right; maybe the row? The docs don't say.) In the case of e.g. column_name(),
std::string's small buffer optimisation means that returning a std::string
will not involve dynamic allocation unless the column name is more than
maybe 23 characters long, which surely must be sufficient in practically
all cases. If you really worry about long column names, please have a
separate method (e.g. column_name_view()) whose name is a warning that
it returns a view.

There is more justification for using view-like types for the actual
data. I'd still argue that the default should be to return safe types
with value semantics, with those methods that return views named to indicate
that.

There is a lot of criticism of C++'s memory-unsafety. Dangling views are
part of that. In newly-designed APIs, we should be going out of our way to
offer memory safety by default.

Note how I handle this in my sqlite wrapper:

     Query q(db, "select a,b from t where c=?");
     q("hello").foreach_row( [&](std::string a, std::string_view b) {
       // do something with a and b
     });

Note that I can use strings or string_views as the parameters to the
per-row lambda. If I choose to use a string_view I have to explicitly write
"string_view", making it clear what the type is.

If I were writing this today, I'd investigate whether generator co-routines
could be used instead of the lambda.

Regards, Phil.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk