C++ Logo


Advanced search

Re: [std-proposals] Copy-construct, move-construct, and PR-construct

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Tue, 22 Aug 2023 08:18:20 +0100
On Mon, Aug 21, 2023 at 10:59 PM Frederick Virchanza Gotham
<cauldwell.thomas_at_[hidden]> wrote:
> (Step 4) After the first tiny thunk-like function returns, the
> function 'FuncThatReturnsMutex' is invoked with the RDI register set
> to the address of the member variable 'buf' which resides inside the
> 'optional' object, and so the mutex gets emplaced in 'buf'.

I just realised that the call to 'FuncThatReturnsMutex' would have to
be a part of the first tiny thunk-like function. So the first
thunk-like function would:
(a) Copy values from the stack into the registers (and possibly to the
top of the stack)
(b) Call 'FuncThatReturnsMutex'

I might actually write the x86_64 assembler for this later today.

On Mon, Aug 21, 2023 at 11:24 PM Thiago Macieira wrote:
> Can you explain why a function would return a mutex in the first place?

No, I can't. Since the beginning of the discussion about NRVO, I've
been using mutex as an easy example from the Std library of a class
that is both uncopiable and unmovable.
Other guys have written papers on NRVO in which they've used a
'Widget' instead of a mutex.

> Mutexes aren't copyable or movable *because* their address matters. A mutex at
> a different address is not the same mutex, even if it has been locked and
> unlocked exactly as many times.

Yeah I get that.

> Semantically, this function shouldn't *return* a mutex. It should receive a
> mutex by reference so it can lock and unlock it as necessary. And if the
> purpose of the function is to create said mutex, then you've already stumbled
> upon the correct container to pass it: optional<mutex>.
> void FunctionThatCreatesMutex(std::optional<mutex> &where);

The C and C++ languages have already been designed so that functions
have return values.
>From the very beginning when they made K&R C, perhaps the following function:

    int Manipulate(int const a, int const b)
        return a*4 + b*3 + 7;

should have been written as:

    function Manipulate(int *const retval, int const a, int const b)
        *retval = a*4 + b*3 + 7;

But Brian Kernighan and Dennis Ritchie, and then later Bjarne
Stroustrup, kept the whole 'return value' thing. So I'm just working
with what we have.

> If you want to avoid the 100% overhead incurred by std::optional,

I don't know where you get 100% from here.... having an extra bool
isn't a big deal. Also using 'operator->' instead of 'value' avoids
the check.

> you can use
> std::unique_ptr and accept the penalty of the indirection. Or you can avoid
> both if you can accept the non-RAII-safe implementation:
> void FunctionThatCreatesMutex(std::mutex *where); // or void*

That's pretty much what I do on Page 5 of my NRVO paper:

> If you want to argue that the above is cumbersome or prone to failure or hard
> to maintain or any of a series of possible drawbacks, you can do that. But you
> must start by examining the state of the art and explaining those things,
> which you haven't done. Moreover, you must illustrate how widespread the
> problem is and/or how many other similar use-cases could benefit from a similar
> solution.
> You don't start with the solution in search of a problem.

People are already vibrantly taking about RVO and NRVO, so obviously
returning a class by value from function is something that programmers
are doing today.
So all I'm saying is that if you have a function that returns an
unmovable-and-uncopiable class by value, then you should be able to
put that object inside an optional or variant or any or some Boost
class or your own personal class.

Received on 2023-08-23 13:07:16