Асинхронное ведение журнала Boost.Log периодически вызывает flu sh () - PullRequest
0 голосов
/ 31 марта 2020

Я реализую оболочку над Boost.Log. в асинхронном ведении журнала регистратор не записывает сообщение журнала сразу и создает очередь сообщений. при вызове метода core.get()->flush() сообщения будут записываться в файл.

Но очевидно, что неэффективно вызывать грипп sh () после каждого сообщения. И в этом случае регистрация asyn c не имеет никакой выгоды. А также не стоит вызывать его один раз в конце программы. (возможно, программа долго работает на сервере)

Я хочу написать код для периодического запуска flu sh () (например, каждые 10 мс).

С помощью этого примера и этого вопроса я написал асинхронный таймер, используя Boost.asio, но он не записывал сообщения в файл. На самом деле регистратор не создает файл .log. может быть, из-за гриппа метод sh () должен вызываться, когда не ведется регистрация.

typedef sinks::asynchronous_sink<
    sinks::text_file_backend,
    sinks::unbounded_ordering_queue<
        logging::attribute_value_ordering< unsigned int, std::less< unsigned int > >
    >
> Async_file_sink;

void do_flush(const boost::system::error_code& /*e*/,
    boost::asio::deadline_timer* t)
{
    logging::core::get()->flush();

    t->expires_at(t->expires_at() + boost::posix_time::milliseconds(10));
    t->async_wait(boost::bind(do_flush,
          boost::asio::placeholders::error, t));
}

struct PerodicTimer{
    PerodicTimer(boost::asio::deadline_timer &timer) : t(timer) {
        t.async_wait(boost::bind(do_flush,
                    boost::asio::placeholders::error, &t));
   }
   boost::asio::deadline_timer& t;
};

void init_flushing()
{
    boost::asio::io_service io;
    boost::asio::deadline_timer t(io, boost::posix_time::milliseconds(10));

    PerodicTimer m(t);
        std::thread th([&]{
        // std::cout << "inside thread" << std::endl;
        io.run();
    });

    th.detach();
}

static void init_logging() 
{
    logging::add_common_attributes();
    boost::shared_ptr< Async_file_sink > sink(new Async_file_sink(
        boost::make_shared< sinks::text_file_backend >(),
        keywords::file_name = "sample_%N.log",
        keywords::rotation_size = 1024 * 1024,
        // We'll apply record ordering to ensure that records from different threads go sequentially in the file
        keywords::order = logging::make_attr_ordering("LineID", std::less< unsigned int >())
    ));

    // Set up where the rotated files will be stored
    init_file_collecting(sink);
    sink->set_formatter(&my_formatter);
    sink->locked_backend()->scan_for_files();
    logging::core::get()->add_sink(sink);
    init_flushing();  // Starting Timer
} 

int main()
{
    init_logging();

    ADD_LOG("SOME MESSAGE");
}

Я думаю, что проблема в том, что одновременно вызывается грипп sh () () Асинхронный журнал регистрирует сообщения. Я не могу запустить асинхронный таймер в том же потоке, потому что io.run () блокирует.

что такое минимальное решение?

1 Ответ

1 голос
/ 01 апреля 2020

В init_flushing вы сразу выходите после порождения потока и уничтожаете объекты io_service io и deadline_timer t во время работы потока. Это неопределенное поведение, поэтому оно может объяснить, почему код работает не так, как вы ожидаете.

И io, и t должны оставаться активными во время работы потока. Но, поскольку вы не используете io для чего-либо еще, кроме ожидания таймера, было бы намного проще просто иметь oop, который вызывает std::this_thread::sleep_for, чтобы ждать, и флаг atomi c, чтобы завершить l oop.

std::thread flushing_thread;
std::atomic<bool> terminate_flushing_thread{ false };

void init_flushing()
{
    assert(!flushing_thread.joinable());

    flushing_thread = std::thread([]()
    {
        while (!terminate_flushing_thread.load(std::memory_order_relaxed))
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            logging::core::get()->flush();
        }
    });
}

void stop_flushing()
{
    if (flushing_thread.joinable())
    {
        terminate_flushing_thread.store(true, std::memory_order_relaxed);
        flushing_thread.join();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...