Bonita Montero
2024-05-08 18:43:43 UTC
I tried to implement a thread-creation function which undos moving
thread-parameters if thread creation fails. That's not because of
necessity but just to try if this is possible:
#include <Windows.h>
#include <iostream>
#include <tuple>
#include <memory>
#include <utility>
using namespace std;
template<typename Fn, typename ... Args>
void xthread( Fn &&fn, Args &&... args )
{
using tupl_t = tuple<decay_t<Fn>, decay_t<Args> ...>;
auto argsSeq = make_index_sequence<sizeof ...(Args)>();
auto thr = []<size_t ... Indices>( index_sequence<Indices ...> )
{
return +[]( LPVOID lpvThreadParam ) -> DWORD
{
tupl_t &tupl = *(tupl_t *)lpvThreadParam;
get<0>( tupl )( get<Indices + 1>( tupl ) ... );
return 0;
};
};
auto fnObj = make_unique<tupl_t>( forward<Fn>( fn ), forward<Args>(
args ) ... );
HANDLE hThread = CreateThread( nullptr, 0, thr( argsSeq ), fnObj.get(),
0, nullptr );
if( hThread )
fnObj.reset(),
WaitForSingleObject( hThread, INFINITE );
else
{
auto back = []<typename Dst>( Dst &&dst, auto &&src )
{
if constexpr( is_rvalue_reference_v<Dst> && !is_const_v<Dst> )
dst = move( src );
};
back( forward<Fn>( fn ), get<0>( *fnObj ) );
[&]<size_t ... Indices>( index_sequence<Indices ...> )
{
(back( forward<Args>( args ), get<Indices + 1>( *fnObj.get() ) ), ...);
}( argsSeq );
}
}
int main()
{
string str( "hello world" );
xthread( []( string &str ) { cout << str << endl; }, move( str ) );
}
Unfortunatly the lambda passed to xthread doesn't see the str
-object from the passed tuple; it just sees nulled memory by
accident and thereby an empty strign object. But the function
-object itself inside the tuple is called correctly.
thread-parameters if thread creation fails. That's not because of
necessity but just to try if this is possible:
#include <Windows.h>
#include <iostream>
#include <tuple>
#include <memory>
#include <utility>
using namespace std;
template<typename Fn, typename ... Args>
void xthread( Fn &&fn, Args &&... args )
{
using tupl_t = tuple<decay_t<Fn>, decay_t<Args> ...>;
auto argsSeq = make_index_sequence<sizeof ...(Args)>();
auto thr = []<size_t ... Indices>( index_sequence<Indices ...> )
{
return +[]( LPVOID lpvThreadParam ) -> DWORD
{
tupl_t &tupl = *(tupl_t *)lpvThreadParam;
get<0>( tupl )( get<Indices + 1>( tupl ) ... );
return 0;
};
};
auto fnObj = make_unique<tupl_t>( forward<Fn>( fn ), forward<Args>(
args ) ... );
HANDLE hThread = CreateThread( nullptr, 0, thr( argsSeq ), fnObj.get(),
0, nullptr );
if( hThread )
fnObj.reset(),
WaitForSingleObject( hThread, INFINITE );
else
{
auto back = []<typename Dst>( Dst &&dst, auto &&src )
{
if constexpr( is_rvalue_reference_v<Dst> && !is_const_v<Dst> )
dst = move( src );
};
back( forward<Fn>( fn ), get<0>( *fnObj ) );
[&]<size_t ... Indices>( index_sequence<Indices ...> )
{
(back( forward<Args>( args ), get<Indices + 1>( *fnObj.get() ) ), ...);
}( argsSeq );
}
}
int main()
{
string str( "hello world" );
xthread( []( string &str ) { cout << str << endl; }, move( str ) );
}
Unfortunatly the lambda passed to xthread doesn't see the str
-object from the passed tuple; it just sees nulled memory by
accident and thereby an empty strign object. But the function
-object itself inside the tuple is called correctly.