Ответы пользователя по тегу Проектирование программного обеспечения
  • Как правильно настроить взаимодействие от переменной объявленной в классе?

    @menkar3
    Отвечу как сам понял вопрос, может быть вообще мимо.
    Основная проблема - сильная связность. У вас более низкоуровневый класс SocketServer зачем-то должен знать о существовании InstrumentInterface который им владеет.
    Я бы предложил передавать серверу в конструкторе "что-то", куда он сможет писать полученные данные. Простой пример - InstrumentalServer ждет, пока не поступят данные от сервера, и пишет их в девайс. Простой пример, который работает вечно - сервер просыпается раз в секунду, записывает данные и засыпает. При появление данных InstrumentalServer просыпается, пишет их в девайс, и засыпает, снова ожидая входящие данные. Классическая многопоточная задачка же. Удалил методы из интерфейса.
    struct MessageQueue
    {
        std::condition_variable cv;
        std::mutex messMtx;
        std::queue<std::string> serverMessages;
    };
    
    struct AbstractDevice
    {
        void processData(std::string message)
        {
            std::cout << message << std::endl;
        }
    };
    
    class SocketServer
    {
    public:
        SocketServer(MessageQueue& mess)
            : out(mess)
        {
            std::thread t(&SocketServer::processData, this);
            t.detach();
        }
    
        void processData()
        {
            for (;;)
            {
                try
                {
                    std::lock_guard<std::mutex> lock(out.messMtx);
                    // some output data
                    out.serverMessages.push("some string 1");
                    out.serverMessages.push("some string 2");
                    // completed this iteration
                    out.cv.notify_one();
                }
                catch (const std::exception& ex)
                {
                    std::cerr << ex.what() << std::endl;
                }
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        }
    
    private:
        MessageQueue& out;
    };
    
    class InstrumentInterface {
    public:
        virtual ~InstrumentInterface() = default;
    };
    
    class InstrumentalServer : public InstrumentInterface
    {
    public:
        InstrumentalServer() = default;
    
        void addDevice(AbstractDevice* dev) { device = dev; };
    
        void waitForMessages()
        {
            for (;;)
            {
                std::unique_lock<std::mutex> lock(messages.messMtx);
                // sleep until messages received
                messages.cv.wait(lock, [this]() {return !messages.serverMessages.empty(); });
                while (!messages.serverMessages.empty())
                {
                    device->processData(messages.serverMessages.front());
                    messages.serverMessages.pop();
                }
            }
        }
    
    private:
        MessageQueue messages;
        std::unique_ptr<SocketServer> sockServer = std::make_unique<SocketServer>(messages);
        AbstractDevice* device;
    };
    
    int main()
    {
        AbstractDevice device;
        InstrumentalServer iServer;
        iServer.addDevice(&device);
        iServer.waitForMessages();
        return 0;
    }

    Можно было бы сделать отдельный мьютекс для девайса, конечно, чтобы надолго мьютекс сообщений не захватывать. Тогда под мьютексом сообщений создаем пустую очередь, свопаем ее с очередью сообщений, освобождаем мьютекс сообщений, захватываем мьютекс девайса, пишем в девайс.
    Я правильно понял вопрос?
    Ответ написан