如何在 class 中正确使用升压通道(和光纤)?
How to use boost channels (and fibers) properly in a class?
我正在尝试在 class 中使用升压通道和光纤。这是一个简单的测试用例,可以正常工作,但它并不是我想要的。如果我将“line:1”移动到“loc:1”,程序会挂起(gdb 在 boost::fibers 内的自旋锁处显示c->推(a))。谁能指出我做错了什么来帮助我?谢谢
这是运行并生成以下内容的示例代码,
#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 会见它的经销商。
我只想将 temp
留在 do_work
中。
channel_t temp{_n}; _chan = &temp; // <<<<<<<<<<<< line:1
在 Block()
中 不起作用 因为 temp 在离开 Block()
的 body 和 _chan 将指向垃圾/释放的内存
可能有两个版本:
1) 保持通道 temp 为 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) 保持通道temp为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 为成员没问题。我猜它指向垃圾。我还了解到 boost sync primitives 不喜欢 std::move(ed)。
感谢大家的帮助。
我正在尝试在 class 中使用升压通道和光纤。这是一个简单的测试用例,可以正常工作,但它并不是我想要的。如果我将“line:1”移动到“loc:1”,程序会挂起(gdb 在 boost::fibers 内的自旋锁处显示c->推(a))。谁能指出我做错了什么来帮助我?谢谢
这是运行并生成以下内容的示例代码,
#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 会见它的经销商。
我只想将 temp
留在 do_work
中。
channel_t temp{_n}; _chan = &temp; // <<<<<<<<<<<< line:1
在 Block()
中 不起作用 因为 temp 在离开 Block()
的 body 和 _chan 将指向垃圾/释放的内存
可能有两个版本:
1) 保持通道 temp 为 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) 保持通道temp为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 为成员没问题。我猜它指向垃圾。我还了解到 boost sync primitives 不喜欢 std::move(ed)。
感谢大家的帮助。