Date: Sun, 16 Jul 2023 10:53:22 +0100
On Sun, Jul 16, 2023 at 1:26 AM Jason McKesson via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> I doubt that returning locked mutexes is the kind of example that
> would change their minds.
I've made it generic, so maybe they're more interested in returning a
decremented semaphore or a true atomic_flag?
https://godbolt.org/z/6j3bKcYGd
I could have simplified it more by making combining the 'create' and
'manipulate' into one function. Or alternatively I could have gotten
rid of the programmer's use of 'placement new' by having the
programmer just give me a typename (and then I do the placement new
behind the scenes for them).
If the Standards Committee isn't keen on giving us guaranteed elision
for NRVO, then maybe a compromise would be to put a template function
something like the following in the Standard Library?
I might actually implement this template function on half a dozen
different architectures and then put it in a paper. Next I'll do
Microsoft x64.
And here it is copy-pasted:
#include <mutex> // mutex
#include <type_traits> // remove_cvref_t
#include <new> // placement 'new'
#include <iostream> // ------- just for testing -------
struct Mutex {
// ---------- cannot move and cannot copy ----------
Mutex(Mutex &&) = delete;
Mutex(Mutex const & ) = delete;
Mutex(void) { std::cout << "construct\n"; }
void lock(void) { std::cout << "lock\n" ; }
void unlock(void) { std::cout << "unlock\n" ; }
~Mutex(void) { std::cout << "destroy\n" ; }
};
extern "C" void Func(void);
__asm("Func: \n"
".intel_syntax noprefix \n"
" push rdi \n" // save to restore later
" push rsi \n" // save to restore later
" push rdx \n" // save to restore later
" call rsi \n" // call constructor
" pop rdx \n" // restore after call
" pop rsi \n" // restore after call
" pop rdi \n" // restore after call
" call rdx \n" // call manipulator
" ret \n"
".att_syntax");
template<typename T>
std::remove_cvref_t<T> FuncT( void (*const
create)(std::remove_cvref_t<T>*), void (*const
manipulate)(std::remove_cvref_t<T>*) )
{
typedef decltype(FuncT<Mutex>) *FuncPtr;
FuncPtr const f = reinterpret_cast<FuncPtr>( Func );
return f(create,manipulate);
}
// ==================================== And now the test code:
int main(void)
{
auto retval = FuncT<Mutex>(
[](Mutex *const p) { ::new(p) Mutex(); },
[](Mutex *const p) { p->lock(); } );
// Func has returned a locked mutex by value!
retval.unlock();
}
<std-proposals_at_[hidden]> wrote:
>
> I doubt that returning locked mutexes is the kind of example that
> would change their minds.
I've made it generic, so maybe they're more interested in returning a
decremented semaphore or a true atomic_flag?
https://godbolt.org/z/6j3bKcYGd
I could have simplified it more by making combining the 'create' and
'manipulate' into one function. Or alternatively I could have gotten
rid of the programmer's use of 'placement new' by having the
programmer just give me a typename (and then I do the placement new
behind the scenes for them).
If the Standards Committee isn't keen on giving us guaranteed elision
for NRVO, then maybe a compromise would be to put a template function
something like the following in the Standard Library?
I might actually implement this template function on half a dozen
different architectures and then put it in a paper. Next I'll do
Microsoft x64.
And here it is copy-pasted:
#include <mutex> // mutex
#include <type_traits> // remove_cvref_t
#include <new> // placement 'new'
#include <iostream> // ------- just for testing -------
struct Mutex {
// ---------- cannot move and cannot copy ----------
Mutex(Mutex &&) = delete;
Mutex(Mutex const & ) = delete;
Mutex(void) { std::cout << "construct\n"; }
void lock(void) { std::cout << "lock\n" ; }
void unlock(void) { std::cout << "unlock\n" ; }
~Mutex(void) { std::cout << "destroy\n" ; }
};
extern "C" void Func(void);
__asm("Func: \n"
".intel_syntax noprefix \n"
" push rdi \n" // save to restore later
" push rsi \n" // save to restore later
" push rdx \n" // save to restore later
" call rsi \n" // call constructor
" pop rdx \n" // restore after call
" pop rsi \n" // restore after call
" pop rdi \n" // restore after call
" call rdx \n" // call manipulator
" ret \n"
".att_syntax");
template<typename T>
std::remove_cvref_t<T> FuncT( void (*const
create)(std::remove_cvref_t<T>*), void (*const
manipulate)(std::remove_cvref_t<T>*) )
{
typedef decltype(FuncT<Mutex>) *FuncPtr;
FuncPtr const f = reinterpret_cast<FuncPtr>( Func );
return f(create,manipulate);
}
// ==================================== And now the test code:
int main(void)
{
auto retval = FuncT<Mutex>(
[](Mutex *const p) { ::new(p) Mutex(); },
[](Mutex *const p) { p->lock(); } );
// Func has returned a locked mutex by value!
retval.unlock();
}
Received on 2023-07-16 09:53:32