У меня есть вечный цикл обработки событий в многопоточной программе, многие функции и методы будут отправлять сообщения в этот цикл событий. Упрощенная версия:
class EventLoop {
public:
void run();
private:
std::deque<std::string> m_msg_queue;
std::condition_variable m_q_cv;
std::mutex m_q_mtx;
};
void EventLoop::run() {
while(true) {
//use m_q_cv to wait for data in m_msg_queue and dispatch
}
}
int main() {
EventLoop el;
el.run();
return 0;
}
Правильный ли этот подход? Если так, каков наилучший способ поставить в очередь события в других функциях / методах, кроме main ()?
Я не люблю делать extern Event el
в других .cpp файлах …
Определите договор для публикации или отправки сообщений в цикл событий и реагирования на полученные события. Типичный API-интерфейс предоставляет как минимум пару процедур отправки / отправки, а также некоторый контракт для сообщений и механизм подключения обратных вызовов. Затем предоставьте этот контракт вместо вашей реализации, которая может остаться скрытой внутри библиотеки.
Определите свой EventLoop
в заголовке и включите его в другие файлы, которые нужны для определения.
Затем укажите классы, которые нуждаются в ссылках или не владеющих указателями на EventLoop
экземпляр, который вы создали в main()
, Они могут быть переданы в конструкторах или установлены, например, с помощью методов установки.
Здесь не нужно ничего глобального.
Когда у вас есть большое количество классов, вы также можете просто наследовать их от общего базового класса, который обрабатывает вашу обработку событий, примерно так:
class EventSource {
EventLoop* _eventLoop;
protected:
// Puts a message on the message queue of the event loop.
void sendMessage(std::string message);
public:
EventSource(EventLoop *eventLoop);
}
class Subclass : public EventSource {
public:
Subclass(EventLoop* loop);
}
Вы по-прежнему передаете указатель на конструктор ваших подклассов, но базовый класс отвечает за фактическое взаимодействие.