Date: Sun, 16 Jul 2023 13:20:20 +0100
On Sun, Jul 16, 2023 at 12:54 PM Frederick Virchanza Gotham
<cauldwell.thomas_at_[hidden]> wrote:
>
> For the time being I will
> re-write the code to accommodate lambdas-with-captures by using
> "std::function<void(void*)>" instead of function pointers.
I have it working with "std::function" now, and so we can use
lambdas-with-captures:
https://godbolt.org/z/6788exab5
Ok now I'm going to write a function that can put this
returned-by-value-locked-mutex inside an std::optional.
And copy-pasted:
#include <new> // placement 'new'
#include <functional> // function
#include <type_traits> // remove_cvref_t
#include <iostream> // ------- just for testing -------
extern "C" void InvokeFunctional(void *const p,
std::function<void(void*)> const &f)
{
if ( f ) f(p);
}
struct Mutex {
// ---------- cannot move and cannot copy ----------
Mutex(Mutex &&) = delete;
Mutex(Mutex const & ) = delete;
Mutex &operator=(Mutex &&) = delete;
Mutex &operator=(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 rsi \n" // save to restore later
" push rdi \n" // save to restore later
" push rdx \n" // save to restore later
" call InvokeFunctional \n" // call 'create'
" pop rdx \n" // restore after call
" pop rdi \n" // restore after call
" mov rsi, rdx \n" // Move 3rd argument to 2nd
" call InvokeFunctional \n" // call 'manipulate'
" pop rsi \n" // restore after call
" ret \n"
".att_syntax");
template<typename T>
std::remove_cvref_t<T> FuncT(
std::function<void(std::remove_cvref_t<T>*)> create,
std::function<void(std::remove_cvref_t<T>*)> manipulate )
{
typedef decltype(FuncT<Mutex>) *FuncPtr;
FuncPtr const f = reinterpret_cast<FuncPtr>( Func );
return f(create,manipulate);
}
// ==================================== And now the test code:
int main(int const argc, char **const argv)
{
auto retval = FuncT<Mutex>(
[](Mutex *const p) { ::new(p) Mutex(); },
[argc](Mutex *const p) { if ( argc % 2 ) p->lock(); } );
// Func has returned a locked mutex by value!
retval.unlock();
}
<cauldwell.thomas_at_[hidden]> wrote:
>
> For the time being I will
> re-write the code to accommodate lambdas-with-captures by using
> "std::function<void(void*)>" instead of function pointers.
I have it working with "std::function" now, and so we can use
lambdas-with-captures:
https://godbolt.org/z/6788exab5
Ok now I'm going to write a function that can put this
returned-by-value-locked-mutex inside an std::optional.
And copy-pasted:
#include <new> // placement 'new'
#include <functional> // function
#include <type_traits> // remove_cvref_t
#include <iostream> // ------- just for testing -------
extern "C" void InvokeFunctional(void *const p,
std::function<void(void*)> const &f)
{
if ( f ) f(p);
}
struct Mutex {
// ---------- cannot move and cannot copy ----------
Mutex(Mutex &&) = delete;
Mutex(Mutex const & ) = delete;
Mutex &operator=(Mutex &&) = delete;
Mutex &operator=(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 rsi \n" // save to restore later
" push rdi \n" // save to restore later
" push rdx \n" // save to restore later
" call InvokeFunctional \n" // call 'create'
" pop rdx \n" // restore after call
" pop rdi \n" // restore after call
" mov rsi, rdx \n" // Move 3rd argument to 2nd
" call InvokeFunctional \n" // call 'manipulate'
" pop rsi \n" // restore after call
" ret \n"
".att_syntax");
template<typename T>
std::remove_cvref_t<T> FuncT(
std::function<void(std::remove_cvref_t<T>*)> create,
std::function<void(std::remove_cvref_t<T>*)> manipulate )
{
typedef decltype(FuncT<Mutex>) *FuncPtr;
FuncPtr const f = reinterpret_cast<FuncPtr>( Func );
return f(create,manipulate);
}
// ==================================== And now the test code:
int main(int const argc, char **const argv)
{
auto retval = FuncT<Mutex>(
[](Mutex *const p) { ::new(p) Mutex(); },
[argc](Mutex *const p) { if ( argc % 2 ) p->lock(); } );
// Func has returned a locked mutex by value!
retval.unlock();
}
Received on 2023-07-16 12:20:30