繁体   English   中英

如何在课堂上正确使用增强通道(和光纤)?

[英]How to use boost channels (and fibers) properly in a class?

我正在尝试在课堂上使用增强通道和光纤。 这是一个简单的测试用例, 可以很好地工作,但这并不是我想要的。 如果我将“ line:1 ”移动到“ loc:1 ”,程序将挂起(gdb在c-> push(a)之后显示boost :: fibers内部的自旋锁)。 谁能指出我做错了什么来帮助我? 谢谢。

这是起作用并产生以下结果的示例代码,

#include <iostream>
#include <boost/fiber/all.hpp>

using namespace std;

template <class T>
class Block
{
    private:
        typedef boost::fibers::buffered_channel<T> channel_t;
        typedef boost::fibers::fiber fiber_t;
        fiber_t _thread_send;
        fiber_t _thread_recv;
        size_t _n;
        channel_t* _chan;

    public:
        Block(size_t n) : _n(n), _chan(nullptr) {
            // >>>>>>>>>> loc:1 <<<<<<<<<<<
        }
        virtual ~Block() {}
        void _send(channel_t *c) {
            cout << __func__ << endl;
            int a = 1000;
            cout << "Sending: " << a << endl;
            c->push(a);
        }
        void _recv(channel_t *c) {
            cout << __func__ << endl;
            int a = 0;
            c->pop(a);
            cout << "Received: " << a << endl;
        }
        void do_work() {
            cout << "do_work\n";
            channel_t temp{_n}; _chan = &temp; // <<<<<<<<<<<< line:1
            _thread_send = boost::fibers::fiber(bind(&Block::_send, this, _chan));
            _thread_recv = boost::fibers::fiber(bind(&Block::_recv, this, _chan));
            _thread_send.join();
            _thread_recv.join();
        }
};

int main()
{
    Block<int> B(2);
    B.do_work(); 
    return 0;
}

输出:

do_work
_send
Sending: 1000
_recv
Received: 1000

编译使用:

GNU/Linux 64 bit x86-64
g++ (GCC) 7.1.1 2017051
boost 1.64.0
g++ -c --std=c++14 -g -Wall -Wpedantic boost_channels.cpp -o boost_channels.o
g++ -lboost_context -lboost_fiber boost_channels.o -o boost_channels

当您在Block构造函数中构造通道并获取指向它的指针时,当temp超出范围时,指针_chan指向垃圾。 您可以将temp设置为Block的成员,也可以将其保留在可以工作的位置,以便转发。

更新:C ++中的括号(大括号)定义范围

Block(size_t n) : _n(n), _chan(nullptr)
    //the scope of the constructor starts at this brace
{
    //temp gets instantiated
    channel_t temp{_n};
    //assign the pointer to the object
    _chan = &temp;

} //put a break point here

然后使用内存表查看_chan。 当您越过右方括号时,您应该看到随着温度被破坏,内存变成了垃圾。 如果您在那时进行跟踪,您将看到temp与其分销商见面。

我只是将temp保留在do_work

channel_t temp{_n}; _chan = &temp; // <<<<<<<<<<<< line:1

Block()中将不起作用,因为在离开Block()的主体之后temp超出了范围,并且_chan将指向垃圾/已释放的内存

可能有两个版本:

1)保持通道温度为do_work()的局部变量:

template <class T>
class Block
{
private:
    typedef boost::fibers::buffered_channel<T> channel_t;
    typedef boost::fibers::fiber fiber_t;
    fiber_t _thread_send;
    fiber_t _thread_recv;
    size_t _n;

public:
    Block(size_t n) : _n(n) {
    }
    virtual ~Block() {}
    void _send(channel_t *c) {
        cout << __func__ << endl;
        int a = 1000;
        cout << "Sending: " << a << endl;
        c->push(a);
    }
    void _recv(channel_t *c) {
        cout << __func__ << endl;
        int a = 0;
        c->pop(a);
        cout << "Received: " << a << endl;
    }
    void do_work() {
        cout << "do_work\n";
        channel_t chan{_n};
        _thread_send = boost::fibers::fiber(bind(&Block::_send, this, & chan));
        _thread_recv = boost::fibers::fiber(bind(&Block::_recv, this, & chan));
        _thread_send.join();
        _thread_recv.join();
    }
};

2)保持通道温度为Block <>的成员变量:

template <class T>
class Block
{
private:
    typedef boost::fibers::buffered_channel<T> channel_t;
    typedef boost::fibers::fiber fiber_t;
    fiber_t _thread_send;
    fiber_t _thread_recv;
    channel_t _chan;

public:
    Block(size_t n) : _chan(n) {
    }
    virtual ~Block() {}
    void _send(channel_t *c) {
        cout << __func__ << endl;
        int a = 1000;
        cout << "Sending: " << a << endl;
        c->push(a);
    }
    void _recv(channel_t *c) {
        cout << __func__ << endl;
        int a = 0;
        c->pop(a);
        cout << "Received: " << a << endl;
    }
    void do_work() {
        cout << "do_work\n";
        _thread_send = boost::fibers::fiber(bind(&Block::_send, this, & _chan));
        _thread_recv = boost::fibers::fiber(bind(&Block::_recv, this, & _chan));
        _thread_send.join();
        _thread_recv.join();
    }
};

这两个版本都会生成:

do_work
_send
Sending: 1000
_recv
Received: 1000

好的,将channel_t声明为成员可以正常工作。 我猜它指向垃圾。 我还了解到,增强同步原语不喜欢被std :: move(ed)接受。

谢谢你们的帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM