Использование std :: thread для вызова функций из двух классов в C ++ 11 - PullRequest
0 голосов
/ 13 ноября 2018

Я пытаюсь реализовать API, который позволит пользователю создавать два канала связи параллельно.Один канал использует TCP, а другой - UDP.У меня есть два класса, представляющих два канала.В этих классах реализованы разные функции.Я бы хотел, чтобы функции двух каналов работали параллельно.Для этого я использую std::thread для создания двух потоков, по одному для каждого канала (класса).Идея состоит в следующем. Файл заголовка выглядит как

class Channel_1
{
public:
     int myfunc(int a, int b);
};

class Channel_2
{
public:
    int anotherfunc(int a, int b);
};

В основной файл cpp включается файл заголовка

int main()
{
  int a = 10, b = 20;
  Channel_1 ch1;
  Channel_2 ch2;

  std::thread t(ch1.myfunc, a,b);
  return 0;
}

Я получаю сообщение об ошибке, говорящее, что ни один экземпляр конструктора std::thread существует.

У меня есть следующие вопросы.

  1. Разве мы не можем вызывать функции из класса в конструкторе потоков?
  2. Имеет ли эта идея использовать потоки для вызовафункции из разных классов имеют смысл?

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Как сказал Некоторые программисты, чувак , должны указать указатель на функцию (статическую или нестатическую).Третьим вариантом может быть создание базового класса, который реализует метод start(), который использует этот конструктор потока:

template< class Function, class... Args > 
explicit thread( Function&& f, Args&&... args );

Пример использования лямбда-выражения.Это не полный рабочий пример, он только показывает, как можно использовать конструктор третьего потока .

class thread_base {
private:
    std::thread m_th;
    bool m_terminated;

    void proxy() {
        // in the new thread
        // add thread_base setup here if needed and
        // call the execute() method in the derived class
        execute();
    }
public:
    thread_base() : m_th(), m_terminated(false) {}
    thread_base(const thread_base&) = delete;
    thread_base& operator=(const thread_base&) = delete;
    thread_base(thread_base&&) = default;
    thread_base& operator=(thread_base&&) = default;
    virtual ~thread_base() { join(); }

    virtual void start() {
        if(joinable()) throw std::runtime_error("thread already running");
        else m_th = std::thread( [this] { proxy(); } );
    }

    inline bool joinable() { return m_th.joinable(); }
    inline void join() { if(joinable()) { m_th.join(); m_terminated=false; } }
    inline void terminate() { m_terminated=true; }
    inline bool terminated() { return m_terminated; }

    virtual void execute() = 0; // implement this in your derived classes
};


class Channel_1 : public thread_base {
    void execute() {
        // runs in a thread
        // with a volontary check if a soft termination
        // request has been issued
        while( !terminated() ) {
            // work
        }
    }
};
0 голосов
/ 13 ноября 2018

У вас на самом деле две проблемы:

  1. Синтаксис неверен. Вам нужно передать указатель на функцию-член, как в

    std::thread t(&Channel_1::myfunc, a, b);
    
  2. Нестатические функции-члены необходимо вызывать для экземпляра класса. Этот экземпляр должен быть передан в качестве первого аргумента:

    std::thread t(&Channel_1::myfunc, ch1, a, b);
    
...