自己的线程创建,在线程创建失败时恢复函数参数

问题描述 投票:0回答:1

我尝试使用可变线程函数参数来实现自己的线程创建,如果线程创建失败,这些参数会传递回其源。这是我的问题“如果线程创建失败,线程的参数会发生什么?”.

我在 Win32 上尝试过这个,这是代码:

#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 ) );
}

但是这段代码一定有问题,因为它没有打印 hello world,而是什么也没有打印,即函数对象被正确调用,但它没有看到 str 的正确参数,而只是意外地将内存清空,默认为空字符串。

c++ c++20 variadic-functions
1个回答
0
投票

雷米是对的。这是 main() 线程中元组的早期重置()。现在代码如下所示:

#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
            {
                unique_ptr<tupl_t> pTupl( (tupl_t *)lpvThreadParam );
                get<0>( *pTupl )( get<Indices + 1>( *pTupl ) ... );
                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.release(),
        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 ) );
}

我在成功创建线程后分离内存并将其附加到线程函数中的新 unique_ptr 。

© www.soinside.com 2019 - 2024. All rights reserved.