繁体   English   中英

C++ 线程:从主线程触发循环

[英]C++ Threads : Trigger a loop from main thread

我有 4 个传感器,我想在 4 个不同的线程中异步轮询它们。 我有一个计时器,它将以 30Hz 的频率调用 function,我希望这个 function 触发线程内的轮询。

我尝试使用std::async每次定时器调用时产生 4 个线程,但创建线程的开销太大。 这是我对std::async所做的:

for (auto& camera : camera_vector_) {
  camera_asyncs_.emplace_back(
      std::async(std::launch::async, [camera]() -> bool {
          return camera->poll();
      })
  );
}

for (auto& future : camera_asyncs_) {
  future.get();
}


现在我需要在程序开始时生成 4 个线程并等待时钟告诉它们解锁并运行进程 function。 像这样的东西:

for (auto& camera : camera_vector_)
{
  camera_threads_.emplace_back(std::thread([&camera]() {
    while (true)
    {
      wait_for_trigger();
      camera->poll();
      block_trigger();
    }
  }));
}

void Driver::poll_threads() {
  for (auto& thread : camera_threads_) {
    trigger_thread(thread);
  }
}

你会怎么做? 我的研究使我想到了互斥体和条件变量。 例如这里 但是我发现的例子是启动一堆线程并让它们完成。 不要一次在一个线程中触发一个循环。

此外,似乎我在这里需要的不是线程池,因为每个线程都是一个定义的作业,只需要一个触发器。 我对么?

在我看来,使用互斥锁是正确的做法。 我应该将它们存储在与我的线程向量相同大小的第二个向量中吗? 我知道我可以在线程内锁定互斥锁,但我可以从主线程解锁互斥锁吗? 你有什么实现这一点的技巧吗?

我正在使用 C++14。

谢谢你的帮助。

以下是我对您的需求的理解:

  1. 你只需要四个线程,不多不少;
  2. 四个线程相互独立,不共享数据;
  3. 每个线程每 33ms 触发一次工作,一个 33ms 内不能多次工作;
  4. 如果触发发生时线程仍在处理最后一个作业,则允许线程忽略此触发。

我会做如下设计:

#include <thread>
#include <vector>
#include <chrono>
#include <iostream>
#include <atomic>

using namespace std;

std::atomic_flag lock0 = ATOMIC_FLAG_INIT;
std::atomic_flag lock1 = ATOMIC_FLAG_INIT;
std::atomic_flag lock2 = ATOMIC_FLAG_INIT;
std::atomic_flag lock3 = ATOMIC_FLAG_INIT;

void trigger() {
    while (true) {
        lock0.clear(); // set to false
        lock1.clear(); // set to false
        lock2.clear(); // set to false
        lock3.clear(); // set to false
        std::this_thread::sleep_for(std::chrono::milliseconds(33)); // 33 ms = 1000ms/30
        // from now on, all threads lost the chance to be triggered
        // they have to wait for the next time
        lock0.test_and_set(); // set to true
        lock1.test_and_set(); // set to true
        lock2.test_and_set(); // set to true
        lock3.test_and_set(); // set to true
    }
}

void f0()
{
    while (true) {
        while(!lock0.test_and_set()) {
            std::cout << "f0" << std::endl;
        }
    }
}

void f1()
{
    while (true) {
        while(!lock1.test_and_set()) {
            std::cout << "f1" << std::endl;
        }
    }
}

void f2()
{
    while (true) {
        while(!lock2.test_and_set()) {
            std::cout << "f2" << std::endl;
        }
    }
}

void f3()
{
    while (true) {
        while(!lock3.test_and_set()) {
            std::cout << "f3" << std::endl;
        }
    }
}

int main()
{
    std::vector<std::thread> v; // use std::async if you want
    std::thread t(trigger);
    v.emplace_back(f0);
    v.emplace_back(f1);
    v.emplace_back(f2);
    v.emplace_back(f3);
    for (auto &ele : v) {
        ele.join();
    }
    t.join();

    return 0;
}

这段代码不会阻塞,相反,它会继续运行并且什么都不做,直到触发到来。

暂无
暂无

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

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