pthread没有为类实例启动

问题描述 投票:0回答:1

注:C ++ 98

[嗨,我是C ++的新手,我正在编写一个databaes程序,并尝试使用pthread的boost :: asio包来启动计时器。计时器的目的是在将sql查询放入缓冲区后启动,如果一段时间内未收到任何内容,缓冲区将运行execute函数。我设法将其编译,但看起来pthread实例似乎没有启动。

我已经在我的getInstance方法中调用了pthread,并且相应地设置了boost :: asio警报。我将在下面显示的是,通过直接调用io_run()启动计时器会使警报陷入警报循环。

database.h

void *run_io(void *arg);

class Database
{
private:
    static Database *dbInstance; //= NULL;

public:
    boost::asio::io_service io_service;
    boost::posix_time::millisec interval;
    boost::asio::deadline_timer timer;
    pthread_t timerThread;

public:
    static Database &getInstance()
    {
        if (!dbInstance)
        {
            dbInstance = new Database();
            // pthread_create(&dbInstance->timerThread,NULL,run_io,&dbInstance->io_service);
            std::cout << " INSTANCE CREATED " << std::endl;
            pthread_create(&dbInstance->timerThread, NULL, run_io, (void *)&dbInstance->io_service);
            // pthread_join(&dbInstance->timerThread, NULL);
        }
        return *dbInstance;
    }
};

database.cpp

Database *Database::dbInstance = NULL;

Database::Database()
    : interval(2000), timer(io_service, interval) {}

Database::~Database()
{
    sqlite3_close(db);
}

void Database::setAlarm(const boost::system::error_code& /* e */)
{
    std::cout << "[TEST] WE ARE IN SET ALARM " << std::endl;
    DB_WRITE_TIME = 500;

    boost::posix_time::milliseconds interval(DB_WRITE_TIME);

    // Reschedule the timer for 1 second in the future:
    timer.expires_at(timer.expires_at() + interval);
    // Posts the timer event
    timer.async_wait(boost::bind(&Database::setAlarm, this, _1));
}

int Database::buffer()
{
    // DO BUFFER STUFF

    timer.async_wait(boost::bind(&Database::setAlarm, this, _1));
   // io_service.run() <-- uncommenting this results in the loop
    return rc ;
}

void *run_io(void *arg)
{
    boost::asio::io_service *io_service = (boost::asio::io_service *)arg;

    io_service->run();
}

所以我感觉pthread甚至还没有开始。我尝试在其中放置打印语句,看看它是否出来了,但终端没有任何显示。

asynchronous io pthreads boost-asio c++98
1个回答
0
投票

我非常困惑,为什么使用Boost或C ++ 11(或同时使用两者)的任何人都将使用原始的pthread线程(请参阅例如C++ boost asynchronous timer to run in parallel with program以获取良好的并列)。

真正的问题可能是io_service用完了[[work(例如参见https://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/io_service__work.html)。

如果没有等待处理的异步操作,线程将退出。

另一个问题是准确性问题

timer.expires_at(timer.expires_at() + interval);

有些处理人员可能花费很长时间,以至于您安排下一个警报时,截止日期已经到期。最好使用

timer.expires_from_now(interval);

注意,这也与注释更匹配。注释已经受注释的困扰,因为它说“ 1秒”,但实际上它是一些定义的常数DB_WRITE_TIME

或以其他方式将计时器与其他处理程序分开,以确保准确的调度。

最后,由于没有任何关机,您才有了UB。静态实例永远不会被破坏,但值得一提的是,未连接的非分离线程永远不会被连接,从而在关机时会产生不确定的行为。

此问题实际上与此处报告的问题几乎相同,ALSO还详细解释了work警卫的工作方式:asio::io_service is ending immediately with work

这里是c ++ 11重写,其中包含必要的修复程序:

由于我现在注意到您是出于某种奇怪的原因而陷入c ++ 03领域的人,因此是Boost Thread版本:

C ++ 03演示/增强线程

Live On Coliru#include <boost/asio.hpp> #include <boost/make_shared.hpp> #include <boost/scoped_ptr.hpp> #include <boost/thread.hpp> #include <iostream> static const int DB_WRITE_TIME = 500; class Database { private: static boost::shared_ptr<Database> dbInstance; Database() : work(new io_service::work(io)), interval(750), timer(io, interval) { std::cout << "INSTANCE CREATED" << std::endl; } void on_timer_completed(const boost::system::error_code& ec) { std::cout << "[on_timer_completed] " << ec.message() << std::endl; if (!ec) { boost::posix_time::milliseconds interval(DB_WRITE_TIME); // Reschedule the timer timer.expires_from_now(interval); timer.async_wait(boost::bind(&Database::on_timer_completed, this, _1)); } } int buffer() { // DO BUFFER STUFF timer.expires_from_now(interval); timer.async_wait(boost::bind(&Database::on_timer_completed, this, _1)); // io_service.run() <-- uncommenting this results in the loop return 1; // rc ; } public: void do_stuff() { buffer(); // whatever it does } void teardown() { std::cout << "INSTANCE SHUTTING DOWN\n"; timer.cancel(); // stop timer loop work.reset(); // allows io.run() to exit if (timerThread.joinable()) { timerThread.join(); // releasing the bound shared_ptr } dbInstance.reset(); // releasing the instance } ~Database() { //sqlite3_close(db); std::cout << "INSTANCE DESTROYED\n"; } private: typedef boost::asio::io_service io_service; io_service io; boost::scoped_ptr<io_service::work> work; boost::posix_time::millisec interval; boost::asio::deadline_timer timer; boost::thread timerThread; void run_io() { std::cout << "ENTER IO THREAD" << std::endl; io.run(); std::cout << "LEAVE IO THREAD" << std::endl; } public: static Database &getInstance() { if (!dbInstance) { dbInstance.reset(new Database()); dbInstance->timerThread = boost::thread(boost::bind(&Database::run_io, dbInstance)); } return *dbInstance; } }; boost::shared_ptr<Database> Database::dbInstance; int main() { Database& db = Database::getInstance(); boost::this_thread::sleep_for(boost::chrono::seconds(1)); db.do_stuff(); boost::this_thread::sleep_for(boost::chrono::seconds(3)); // .... db.teardown(); }

打印

INSTANCE CREATED ENTER IO THREAD [on_timer_completed] Success [on_timer_completed] Success [on_timer_completed] Success [on_timer_completed] Success [on_timer_completed] Success INSTANCE SHUTTING DOWN [on_timer_completed] Operation canceled LEAVE IO THREAD INSTANCE DESTROYED

© www.soinside.com 2019 - 2024. All rights reserved.