【发布时间】:2020-03-27 08:38:03
【问题描述】:
早安,
嗯,我知道已经有一些关于 Boost.Fiber 和 Goroutines 比较的讨论。但是作为并发领域的新开发人员,我对差异和可用性感到很困惑。
所以目前,我正在做一些 Go 到 C++ 的迁移,我的一些障碍是使用 Channels 和 Goroutines,所以我对并发、Boost.Fiber 和 Goroutines 做了一些小阅读,并基于我对这个话题的理解。
package main
import (
"fmt"
"time"
)
const (
timeout = 0
interrupt = 1
serverDone = 2
)
func runDurationTimer(d time.Duration, toStop chan int) {
go func() {
dSeconds := uint64(d.Seconds())
if dSeconds == 0 {
return
}
time.Sleep(d)
toStop <- timeout
}()
}
func clientWatchControlChannel(d time.Duration, toStop chan int) {
go func() {
time.Sleep(d)
toStop <- serverDone
}()
}
func main() {
toStop := make(chan int, 1)
d := 5 * time.Second
runDurationTimer(d, toStop)
clientWatchControlChannel(1 * time.Second, toStop)
fmt.Println("Hello World \n")
reason := <-toStop
switch reason {
case timeout:
fmt.Println("Process done, duration: " + d.String() +".")
case interrupt:
fmt.Println("Process done, received interrupt signal.")
case serverDone:
fmt.Println("Process done, server terminated the session.")
}
}
所以上面的代码是一个基本的成功和超时方案,当一个函数在一定时间内没有返回一个状态时,它就会超时。
对于实际场景中的clientWatchControlChannel,Sleep 将是需要返回某些内容并完成该过程的其他进程。基于硬编码值,整个程序返回"Process done, server terminated the session.",因为运行clientWatchControlChannel的持续时间是runDurationTimer中的超时值。
所以当我调试代码时,它运行了 2 个过程,所以我在 toStop <- timeout 和 toStop <- serverDone 处放置了一个断点,所以 runDurationTimer 运行然后休眠,然后等待完成它运行 clientWatchControlChannel 然后首先完成因为它的持续时间比runDurationTimer 短,在此之后,它不会回到runDurationTimer 并等待,它只是终止并为输出分配值。
根据我对 C++ 的理解,我编写了以下代码。
#include <boost/fiber/all.hpp>
#include <chrono>
#include <iostream>
typedef boost::fibers::unbuffered_channel<int> unbuffered_channel_t;
enum stop { timeout = 0, interrupt, serverDone };
void runDurationTimer(
const std::chrono::duration<std::uint32_t, std::ratio<1, 1>> &d,
unbuffered_channel_t &toStop) {
boost::fibers::async([&]() {
if (d.count() == 0) {
return;
}
boost::this_fiber::sleep_for(d);
toStop.push(timeout);
});
}
void clientWatchChannel(
const std::chrono::duration<std::uint32_t, std::ratio<1, 1>> &d,
unbuffered_channel_t &toStop) {
boost::fibers::async([&]() {
boost::this_fiber::sleep_for(d);
toStop.push(serverDone);
});
}
int main() {
unbuffered_channel_t chan;
auto dTime = std::chrono::duration<std::uint32_t, std::ratio<1, 1>>(3);
auto dWatch = std::chrono::duration<std::uint32_t, std::ratio<1, 1>>(1);
runDurationTimer(dTime, chan);
clientWatchChannel(dWatch, chan);
std::cout << "Hello, World!\n";
int i = 0;
chan.pop(i);
switch (i) {
case timeout:
std::cout << "Process done, duration: " << std::to_string(dTime.count())
<< ".";
break;
case interrupt:
std::cout << "Process done, received interrupt signal.";
break;
case serverDone:
std::cout << "Process done, server terminated the session.";
break;
default:
break;
}
return 0;
}
因此,长话短说,一切在行为上几乎相同。同样,我调试了代码,在toStop.push(serverDone); 和toStop.push(timeout); 中放置了断点,所以与Go 相同,它先运行runDurationTimer,然后在等待它完成时clientWatchControlChannel 启动并运行toStop.push(serverDone);,但是区别不是终止,而是回到runDurationTimer 并运行toStop.push(timeout);。所以我认为这是我真正感到困惑的事情。然后chan.pop(i)返回serverDone。
所以,我真的需要一些帮助来理解它是否正确,或者我应该继续使用 Boost.Fiber 进行 Go 迁移还是使用 Boost.Coroutines2。任何建议、反应和更正都非常感谢,我愿意从中学习。
我也对我的 C++ 表示歉意,一直停滞不前。 :)
谢谢。
【问题讨论】:
标签: c++ boost goroutine boost-fiber