C++ Boost异步定时器与程序并行运行

C++ Boost异步定时器与程序并行运行,c++,asynchronous,boost,c++98,asio,C++,Asynchronous,Boost,C++98,Asio,注意:这是针对C++98的 我正在尝试开发一个简单的计时器/计数器,它在我的主程序的后台运行 我以前没有使用过异步定时器,我一直在尝试按照boost教程来做,但它们似乎仍然阻止了我的主要功能。我已经从boost网站稍作修改,改为实验版 基本上,通过下面的程序,我想做的是: 干管 执行计数为5的testRun 在测试运行计数的同时,在主屏幕中打印测试ABC。 main.cpp 我希望我的输出是什么样子的: 为了解构手头的任务,我将从一个简单的C++98实现开始 我们将它清理为现代C++,然后用As

注意:这是针对C++98的

我正在尝试开发一个简单的计时器/计数器,它在我的主程序的后台运行

我以前没有使用过异步定时器,我一直在尝试按照boost教程来做,但它们似乎仍然阻止了我的主要功能。我已经从boost网站稍作修改,改为实验版

基本上,通过下面的程序,我想做的是:

干管 执行计数为5的testRun 在测试运行计数的同时,在主屏幕中打印测试ABC。 main.cpp

我希望我的输出是什么样子的:


为了解构手头的任务,我将从一个简单的C++98实现开始

我们将它清理为现代C++,然后用Asio替换。< /P> 您将看到Asio不需要线程,这很好。但是我们必须及时工作,用C++ 98代替现代C++。 最后,您将看到加入现代C++的所有理由,以及如何组织代码,这样您就可以轻松地管理复杂性。 C++98 下面是我如何用c++98编写的:

C++11 <>以上确实不是C++。在C语言中使用printf实际上是一样的,但更方便。下面是C++11如何改进的:

std::thread,std::atomic_bool,std::chono,std::this_thread,std::to_string,std::mutex/lock_guard,更好的初始化。 这在我看来是不言自明的。整个计划现在归结为:

int main() {
    boost::asio::io_context io;

    interval_timer abc { io, 200ms, [] {
        std::cout << "TEST_ABC" << std::endl;
        return true;
    } };

    interval_timer counter { io, 1s, [&abc, current=0]() mutable {
        std::cout << "COUNTER AT " << ++current << std::endl;

        if (current < 5)
            return true;

        abc.stop();
        return false;
    } };

    abc.run();
    counter.run();

    io.run();
}
回到C++98 没有lambda的。好的,我们可以使用boost::bind,也可以自己编写一些类。你选择了你的毒药,我选择了一种混合物:

绑定,因为它是我们20年前谈论的那个时代的工具 对回调使用虚拟方法而不是std::函数。 lambda捕获已替换为显式成员变量。 这一切都变得不那么优雅,但基本上可以识别为相同的东西:

这里也可以应用与前面的run_for相同的转换,但是我们现在必须链接Boost Chrono,因为std::Chrono不存在:,仍然是56 LoC


为了解构手头的任务,我将从一个简单的C++98实现开始

我们将它清理为现代C++,然后用Asio替换。< /P> 您将看到Asio不需要线程,这很好。但是我们必须及时工作,用C++ 98代替现代C++。 最后,您将看到加入现代C++的所有理由,以及如何组织代码,这样您就可以轻松地管理复杂性。 C++98 下面是我如何用c++98编写的:

C++11 <>以上确实不是C++。在C语言中使用printf实际上是一样的,但更方便。下面是C++11如何改进的:

std::thread,std::atomic_bool,std::chono,std::this_thread,std::to_string,std::mutex/lock_guard,更好的初始化。 这在我看来是不言自明的。整个计划现在归结为:

int main() {
    boost::asio::io_context io;

    interval_timer abc { io, 200ms, [] {
        std::cout << "TEST_ABC" << std::endl;
        return true;
    } };

    interval_timer counter { io, 1s, [&abc, current=0]() mutable {
        std::cout << "COUNTER AT " << ++current << std::endl;

        if (current < 5)
            return true;

        abc.stop();
        return false;
    } };

    abc.run();
    counter.run();

    io.run();
}
回到C++98 没有lambda的。好的,我们可以使用boost::bind,也可以自己编写一些类。你选择了你的毒药,我选择了一种混合物:

绑定,因为它是我们20年前谈论的那个时代的工具 对回调使用虚拟方法而不是std::函数。 lambda捕获已替换为显式成员变量。 这一切都变得不那么优雅,但基本上可以识别为相同的东西:

这里也可以应用与前面的run_for相同的转换,但是我们现在必须链接Boost Chrono,因为std::Chrono不存在:,仍然是56 LoC


这回答了你的问题吗@TedKleinBergman no.这是C++11标准。不幸的是,我需要C++98。但或多或少这是同一个问题。您的代码挂起在io_service::run上,直到所有处理程序都被处理。只需通过boost::thread th&testRun;在后台启动testRun;,在返回0之前添加th.join。这是否回答了您的问题@TedKleinBergman no.这是C++11标准。不幸的是,我需要C++98。但或多或少这是同一个问题。您的代码挂起在io_service::run上,直到所有处理程序都被处理。只需通过boost::thread th&testRun;在后台启动testRun;,在返回0之前添加th.join。非常感谢!非常感谢。非常感谢!非常感谢。
 TEST ABC 
0
 PRINT 
1
 PRINT 
2
 PRINT 
3
 PRINT 
4
 PRINT 
 PRINT 
Final count is 5

#include <pthread.h>
#include <iostream>
#include <sstream>
#include <unistd.h>

static pthread_mutex_t s_mutex = {};
static bool s_running = true;

static bool is_running(bool newvalue) {
    pthread_mutex_lock(&s_mutex);
    bool snapshot = s_running;
    s_running = newvalue;
    pthread_mutex_unlock(&s_mutex);
    return snapshot;
}

static bool is_running() {
    pthread_mutex_lock(&s_mutex);
    bool snapshot = s_running;
    pthread_mutex_unlock(&s_mutex);
    return snapshot;
}

static void output(std::string const& msg) {
    pthread_mutex_lock(&s_mutex);
    std::cout << msg << "\n";
    pthread_mutex_unlock(&s_mutex);
}

static void* count_thread_func(void*) {
    for (int i = 0; i < 5; ++i) {
        ::sleep(1);
        std::ostringstream oss;
        oss << "COUNTER AT " << (i+1);
        output(oss.str());
    }
    is_running(false);
    return NULL;
}

int main() {
    pthread_t thr = {0};
    pthread_create(&thr, NULL, &count_thread_func, NULL);

    while (is_running()) {
        ::usleep(200000);
        output("TEST_ABC");
    }

    pthread_join(thr, NULL);
}
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 1
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 2
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 3
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 4
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 5
TEST_ABC
#include <thread>
#include <iostream>
#include <chrono>
#include <mutex>
#include <atomic>
using std::chrono::milliseconds;
using std::chrono::seconds;

static std::mutex s_mutex;
static std::atomic_bool s_running {true};

static void output(std::string const& msg) {
    std::lock_guard<std::mutex> lk(s_mutex);
    std::cout << msg << "\n";
}

static void count_thread_func() {
    for (int i = 0; i < 5; ++i) {
        std::this_thread::sleep_for(seconds(1));
        output("COUNTER AT " + std::to_string(i+1));
    }

    s_running = false;
}

int main() {
    std::thread th(count_thread_func);

    while (s_running) {
        std::this_thread::sleep_for(milliseconds(200));
        output("TEST_ABC");
    }

    th.join();
}
// simple wrapper that makes it easier to repeat on fixed intervals
struct interval_timer {
    interval_timer(boost::asio::io_context& io, Clock::duration i, Callback cb)
        : interval(i), callback(cb), timer(io)
    {}

    void run() {
        timer.expires_from_now(interval);
        timer.async_wait([=](error_code ec) {
            if (!ec && callback())
                run();
        });
    }

    void stop() {
        timer.cancel();
    }

  private:
    Clock::duration const interval; 
    Callback callback;
    boost::asio::high_resolution_timer timer;
};
int main() {
    boost::asio::io_context io;

    interval_timer abc { io, 200ms, [] {
        std::cout << "TEST_ABC" << std::endl;
        return true;
    } };

    interval_timer counter { io, 1s, [&abc, current=0]() mutable {
        std::cout << "COUNTER AT " << ++current << std::endl;

        if (current < 5)
            return true;

        abc.stop();
        return false;
    } };

    abc.run();
    counter.run();

    io.run();
}
#include <boost/asio.hpp>
#include <iostream>
#include <chrono>
#include <functional>
using namespace std::chrono_literals;
using Clock = std::chrono::high_resolution_clock;
using Callback = std::function<void()>;
using boost::system::error_code;

// simple wrapper that makes it easier to repeat on fixed intervals
struct interval_timer {
    interval_timer(boost::asio::io_context& io, Clock::duration i, Callback cb)
        : interval(i), callback(cb), timer(io)
    { run(); }

  private:
    void run() {
        timer.expires_from_now(interval);
        timer.async_wait([=](error_code ec) {
            if (!ec) {
                callback();
                run();
            }
        });
    }

    Clock::duration const interval; 
    Callback callback;
    boost::asio::high_resolution_timer timer;
};

int main() {
    boost::asio::io_context io;

    interval_timer abc { io, 200ms, [] {
        std::cout << "TEST_ABC" << std::endl;
    } };

    interval_timer counter { io, 1s, [current=0]() mutable {
        std::cout << "COUNTER AT " << ++current << std::endl;
    } };

    io.run_for(5s);
}
#include <boost/asio.hpp>
#include <iostream>
#include <boost/bind.hpp>
using boost::posix_time::seconds;
using boost::posix_time::millisec;
typedef boost::posix_time::microsec_clock Clock;
using boost::system::error_code;

// simple wrapper that makes it easier to repeat on fixed intervals
struct interval_timer {
    interval_timer(boost::asio::io_context& io, millisec i)
        : interval(i), timer(io)
    { run(); }

    virtual bool callback() = 0;

    void run() {
        timer.expires_from_now(interval);
        timer.async_wait(boost::bind(&interval_timer::on_timer, this, boost::asio::placeholders::error()));
    }

    void stop() {
        timer.cancel();
    }

  private:
    void on_timer(error_code ec) {
        if (!ec && callback())
            run();
    }
    millisec const interval; 
    boost::asio::deadline_timer timer;
};

int main() {
    boost::asio::io_context io;

    struct abc_timer : interval_timer {
        abc_timer(boost::asio::io_context& io, millisec i) : interval_timer(io, i) {}
        virtual bool callback() {
            std::cout << "TEST_ABC" << std::endl;
            return true;
        }
    } abc(io, millisec(200));

    struct counter_timer : interval_timer {
        counter_timer(boost::asio::io_context& io, millisec i, interval_timer& abc)
            : interval_timer(io, i), abc(abc), current(0) {}

        virtual bool callback() {
            std::cout << "COUNTER AT " << ++current << std::endl;

            if (current < 5)
                return true;

            abc.stop();
            return false;
        }
      private:
        interval_timer& abc;
        int current;
    } counter(io, millisec(1000), abc);

    io.run();
}
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 1
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 2
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 3
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 4
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
TEST_ABC
COUNTER AT 5