简体   繁体   中英

c++ multi-threading program architecture

I am currently practicing the use of multiple threads in C++. The program is simplified as follow. In this case, I have a global variable Obj , and within each task, a get function is processed by thread and thread detach will be called after.

In practice, get may take a great amount of time to run. If there are many tasks, get will be called repetitively (since each task has its own get function). I wonder if I can design a program where when one task has already obtained the data using get function and the data has been wrote to obj.text , then the rest of tasks can directly access or wait for the data from obj.text .

Can I use std::shared_ptr, std::future, std::async in c++ to implement this? If so, how to design the program? Any advice is greatly appreciated.

#include <chrono>
#include <future>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
using namespace std;

class Info {
public:
  Info() { Ids = 10; };

  int Ids;
  std::string text;
};

Info Objs;

class Module {
public:
  Module() {}
  virtual void check(int &id){};
  virtual void get(){};
};

class task1 : public Module {
public:
  task1() { std::cout << "task1" << std::endl; }
  void check(int &id) override {
    thread s(&task1::get, this);
    s.detach();
  };

  // The function will first do some other work (here, I use sleep to represent
  // that) then set the value of Objs.text
  void get() override {
    // The task may take 2 seconds , So use text instead
    std::this_thread::sleep_for(std::chrono::seconds(5));
    Objs.text = "AAAA";
    std::cout << Objs.text << std::endl;
  };
};

class task2 : public Module {
public:
  task2() { std::cout << "task2" << std::endl; }
  void check(int &id) override {
    thread s(&task2::get, this);
    s.detach();
  };
  // The function will first do some other work (here, I use sleep to represent
  // that) then set the value of Objs.text
  void get() {
    std::this_thread::sleep_for(std::chrono::seconds(5));
    Objs.text = "AAAA";
    std::cout << Objs.text << std::endl;
  };
};

int main() {
  std::vector<std::unique_ptr<Module>> modules;

  modules.push_back(std::make_unique<task1>());
  modules.push_back(std::make_unique<task2>());

  for (auto &m : modules) {
    m->check(Objs.Ids);
  }

  std::this_thread::sleep_for(std::chrono::seconds(12));
  return 0;
}

It is a plain producer-consumer problem.

You have multiple “get()” producers. And did not implemented consumers yet.

First, you should have multiple “Info” for multithread. If there is only one Info, multithread programming is useless. I recommend “concurrent_queue”.

Second, “detach()” is not a good idea. You can't manage child threads. You'd better use “join()”

My code sample follows. I used Visual Studio 2022

#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
#include <concurrent_queue.h>
using namespace std;

class Info {
public:
    Info() { Ids = 10; };
    int Ids;
    std::string text;
};

concurrency::concurrent_queue<Info> Objs;

void producer()
{
    while (true) {
        Info obj;
        std::this_thread::sleep_for(std::chrono::seconds(5));
        obj.text = "AAAA\n";
        Objs.push(obj);
    }
}

void consumer()
{
    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        Info obj;
        bool got_it = Objs.try_pop(obj);
        if (got_it) {
            std::cout << obj.text;
        }
    }
}

int main() {
    const int NUM_CORES = 6;
    std::vector<std::thread> threads;
    for (int i = 0; i < NUM_CORES / 2; ++i)
        threads.emplace_back(producer);
    for (int i = 0; i < NUM_CORES / 2; ++i)
        threads.emplace_back(consumer);
    for (auto& th : threads) th.join();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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