将Boost.Fiber与Goroutines比较正确的可用性

时间:2019-12-02 17:26:54

标签: c++ boost goroutine boost-fiber

美好的一天,

嗯,我知道已经有一些关于Boost.Fiber和Goroutines比较的讨论。但是,作为并发领域的新开发人员,我对差异和可用性感到非常困惑。

因此,目前,我正在做一些Go to 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.")
    }
}

因此,上面的代码是基本的成功和超时方案,其中,当某个函数在一定时间内未能返回状态时,它将超时。

对于实际情况下的clientWatchControlChannelSleep将是其他一些需要返回某些内容并完成该过程的过程。基于硬编码值,整个程序将返回"Process done, server terminated the session.",因为运行clientWatchControlChannel的持续时间是<runDurationTimer中的超时值。

因此,当我调试代码时,它将运行2个过程,因此我在toStop <- timeouttoStop <- 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 ++的道歉也一直停滞不前。 :)

谢谢。

1 个答案:

答案 0 :(得分: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;
  }
  

你好,世界!

     

处理完成,服务器终止了会话。