0

再会,

好吧,我知道已经有一些关于 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

toStop <- timeout因此,当我调试代码时,它会运行 2 个过程,因此我在and处放置了一个断点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);and中放置了断点toStop.push(timeout);,所以与 Go 相同,它runDurationTimer先运行然后等待它完成clientWatchControlChannel并运行toStop.push(serverDone);,但不同之处在于它不是终止,而是返回runDurationTimer并运行toStop.push(timeout);。所以我认为这是我真正感到困惑的事情。然后chan.pop(i)返回serverDone

所以,我真的需要一些帮助来理解它是否正确,或者我应该继续使用 Boost.Fiber 进行 Go 迁移还是使用 Boost.Coroutines2。感谢任何建议,反应和更正,我愿意从中学习。

我也对我的 C++ 表示歉意,一直停滞不前。:)

谢谢。

4

1 回答 1

0

你必须关闭频道

 #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);
     // return value would indicate that the channel was closed
     // `timeout` will not be inserted into the channel
     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);
     toStop.close();
   });
  } 

  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;
   }
   std::cout << "\n";
   return 0;
  }

你好世界!

进程完成,服务器终止会话。

于 2019-12-04T14:04:07.573 回答