C ++:std :: thread的简单返回值?

时间:2011-10-07 12:00:37

标签: c++ multithreading

使用win32线程,我有直接的GetExitCodeThread(),它给出了线程函数返回的值。我正在为std::thread(或提升线程)寻找类似的东西 据我所知,这可以用期货来完成,但究竟是怎么做的?

7 个答案:

答案 0 :(得分:54)

请参阅有关C ++ 11期货的this video tutorial

明确表示线程和期货:

#include <thread>
#include <future>

void func(std::promise<int> && p) {
    p.set_value(1);
}

std::promise<int> p;
auto f = p.get_future();
std::thread t(&func, std::move(p));
t.join();
int i = f.get();

或者使用std::async(线程和期货的更高级别包装器):

#include <thread>
#include <future>
int func() { return 1; }
std::future<int> ret = std::async(&func);
int i = ret.get();

我无法评论它是否可以在所有平台上运行(它似乎适用于Linux,但不适用于使用GCC 4.6.1的Mac OSX上)。

答案 1 :(得分:29)

我会说:

#include <thread>
#include <future>

int simplefunc(std::string a)
{ 
    return a.size();
}

int main()
{
      auto future = std::async(simplefunc, "hello world");
      int simple = future.get();

      return simple;
}

请注意,async甚至会传播从线程函数抛出的任何异常

答案 2 :(得分:2)

使用C ++ 11线程,无法获得返回值作为线程退出,而pthread_exit(...)

就是这种情况

您需要使用C ++ 11 Future<>来获取返回值。 Future是使用模板化参数创建的,其中模板采用返回值(内置于用户定义类型)..

您可以使用future<..>::get(..)函数在另一个线程中获取值。

使用future<..>的一个好处是,您可以检查返回值的有效性,即如果已经采用,则可以通过使用get()函数检查有效性来避免意外调用future<..>::isValid(...)。 / p>

以下是编写代码的方法。

#include <iostream>
#include <future>
using namespace std;
auto retFn() {
    return 100;
}
int main() {
    future<int> fp = async(launch::async, retFn);
    if(fp.valid())
       cout<<"Return value from async thread is => "<<fp.get()<<endl;
    return 0;
}

还应该注意的是,我们可以使用launch::deferred选项作为

在同一个线程上运行。
 future<int> fp = async(launch::deferred, retFn);

答案 3 :(得分:0)

使用std::ref

将引用/指针传递给线程

async远胜于此,但是就科学而言,它可以做到:

void myfunc_reference(int& i);
std::thread(myfunc_reference, std::ref(output));

我怀疑async的实现必须在幕后为我们做些事情,这实际上是您在pthread后端中要做的事情:How to return a value from pthread threads in C? < / p>

您当然必须确保变量生存期一直持续到线程返回为止。

以下可运行代码示例比较了异步方法和该更差的方法:

main.cpp

#include <cassert>
#include <future>
#include <iostream>
#include <thread>
#include <vector>

int myfunc(int i) {
    return i + 1;
}

void myfunc_reference(int& i) {
    i = myfunc(i);
}

int main() {
    unsigned int nthreads = 4;
    std::vector<int> inputs{1, 2, 3, 4};
    std::vector<int> outputs_expect{2, 3, 4, 5};

    // future and sync. Nirvana. When you are not fighting to death with types:
    // https://stackoverflow.com/questions/10620300/can-stdasync-be-use-with-template-functions
    {
        std::vector<std::future<int>> futures(nthreads);
        std::vector<int> outputs(nthreads);
        for (decltype(futures)::size_type i = 0; i < nthreads; ++i) {
            futures[i] = std::async(
                myfunc,
                inputs[i]
            );
        }
        for (decltype(futures)::size_type i = 0; i < nthreads; ++i) {
            outputs[i] = futures[i].get();
        }
        assert(outputs_expect == outputs);
    }

    // Reference arguments.
    //
    // Annoying because requires:
    //
    // - wrapping the return function to accept references
    // - keeping an array of outputs
    // - std::ref
    {
        std::vector<std::thread> threads(nthreads);
        std::vector<int> inouts(inputs);
        for (decltype(threads)::size_type i = 0; i < nthreads; ++i) {
            threads[i] = std::thread(myfunc_reference, std::ref(inouts[i]));
        }
        for (auto& thread : threads) {
            thread.join();
        }
        assert(outputs_expect == inouts);
    }
}

GitHub upstream

编译并运行:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp -pthread
./main.out

在Ubuntu 19.04中测试。

答案 4 :(得分:0)

这是一个更具体的例子。

一个函数使用回调参数模拟下载,以显示进度并取消下载。

ReactWrapper {}

我们要获取下载状态,

import {expect} from 'chai';
import sinon from 'sinon';
import sinonTest from 'sinon-test';
import {Map} from 'immutable';
import React from 'react';
import {shallow, mount, configure} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import {mockStore} from '../test_helper';

//import {constants} from '../src/react/constants/constants.js';

import {ModalContainer} from '../../src/react/ModalContainer/ModalContainer';

configure({adapter: new Adapter()});

describe('Modal Container - Modal Container JSX', () => {

  describe('Render from switch case', () => {

    const fakeStore = mockStore(Map({}));

    it('Render Search And Highlight Modal', () => {

      const props = {
        constants: {
          SEARCH_AND_HIGHLIGHT_MODAL: 'search-and-highlight'
        }
      }

      const wrapper = mount(<ModalContainer store={fakeStore}
                                            visible={false}
                                            modal={false}
                                            metaData={null}
                                            {...props}
      />);
      //const visibleElement = wrapper.find();
      //const myProps = wrapper.props();
      console.log(wrapper.find('SearchAndHighlightModal'));

      //expect(wrapper.find('SearchAndHighlightModal')).to.have.lengthOf(1);

    });

  });

});

答案 5 :(得分:-1)

我认为参考变量的读取更直观。

int x = 0;
std::thread theThread(threadFunction, std::ref(x));
theThread.join();
std::cout << x << std::endl;

答案 6 :(得分:-5)

这一切都取决于你对“简单”的定义。

使用期货肯定会在几行C ++中做出神奇的伎俩,但我发现劫持一种专为并行处理而设计的机制是值得商榷的。

期货通常在多核CPUS上有意义,它们允许一个进程启动非同步任务,这些任务将从其他核心中获取计算能力(撇开这样一个事实,即找到一组足够值得付出努力的非核心数据不是这样一个微不足道的事情。)

使用整个机制作为解决方法来检索纯粹的int返回值就是我所说的语法驱动的软件设计。它非常适合作为C ++ 11多功能性的展示,但它确实隐藏了大量的语法糖结构下的资源消耗。

如果不是将其他核心用作原始电源,那么创建线程的重点是什么?如果你不打算与它进行通信直到完成它? 因为如果你这样做,从它那里检索任何状态,无论是在终止时还是在任何其他时间,都将是一件小事,你甚至不会想到首先使用期货。

除了(可论证的)方便性或审美吸引力之外,这些技巧如何实现 功能性 ,这些技巧可以被认为足以抵消隐藏的成本?

在没有适当的多任务处理背景的情况下阅读这些答案,可能会定期使用这些效率低下的机制诱惑这些新的孩子。 这只会污染未来的软件,而Schlemiel the Painter的综合症更多。