У меня есть приложение, которое написано для использования boost::asio
исключительно как источник входных данных, так как большинство наших объектов основаны на сетевой коммуникации. Из-за некоторых конкретных требований теперь требуется возможность использования разделяемой памяти как метода ввода. Я уже написал компонент общей памяти, и он работает относительно хорошо.
Проблема заключается в том, как обрабатывать уведомления из процесса разделяемой памяти в потребляющем приложении, чтобы данные были доступны для чтения, - нам нужно обрабатывать данные в существующем потоке ввода (используя boost::asio
), и нам также нужно чтобы не блокировать входной поток, ожидающий данных.
Я реализовал это, введя промежуточный поток, который ждет событий, которые будут сигнализироваться из процесса поставщика общей памяти, затем отправляет обработчик завершения во входной поток для обработки чтения в данных.
Теперь это работает, но введение промежуточного потока означает, что в значительном числе случаев у нас есть дополнительный контекстный переключатель, прежде чем мы сможем прочитать данные, которые оказывают отрицательное влияние на латентность, и накладные расходы дополнительного поток также относительно дорог.
Здесь упрощенный пример того, что делает приложение:
#include <iostream>
using namespace std;
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/bind.hpp>
class simple_thread
{
public:
simple_thread(const std::string& name)
: name_(name)
{}
void start()
{
thread_.reset(new boost::thread(
boost::bind(&simple_thread::run, this)));
}
private:
virtual void do_run() = 0;
void run()
{
cout << "Started " << name_ << " thread as: " << thread_->get_id() << "\n";
do_run();
}
protected:
boost::scoped_ptr<boost::thread> thread_;
std::string name_;
};
class input_thread
: public simple_thread
{
public:
input_thread() : simple_thread("Input")
{}
boost::asio::io_service& svc()
{
return svc_;
}
void do_run()
{
boost::system::error_code e;
boost::asio::io_service::work w(svc_);
svc_.run(e);
}
private:
boost::asio::io_service svc_;
};
struct dot
{
void operator()()
{
cout << '.';
}
};
class interrupt_thread
: public simple_thread
{
public:
interrupt_thread(input_thread& input)
: simple_thread("Interrupt")
, input_(input)
{}
void do_run()
{
do
{
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
input_.svc().post(dot());
}
while(true);
}
private:
input_thread& input_;
};
int main()
{
input_thread inp;
interrupt_thread intr(inp);
inp.start();
intr.start();
while(true)
{
Sleep(1000);
}
}
Есть ли способ получить данные, обрабатываемые в input_thread
напрямую (без необходимости post
) через interrupt_thread
? Предполагается, что поток прерываний полностью управляется таймингами из внешнего приложения ( уведомление о том, что данные доступны через семафор). Кроме того, предположим, что мы имеем полный контроль над как потребляющими, так и предоставляющими приложениями, что у нас есть дополнительные объекты, которые должны обрабатываться объектом input_thread
(поэтому мы не можем просто блокировать и ждать на объектах семафора). Цель состоит в том, чтобы уменьшить накладные расходы, загрузку процессора и задержку данных, поступающих через приложение для предоставления общей памяти.