gpt4 book ai didi

C++回调定时器实现

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:04:56 24 4
gpt4 key购买 nike

我找到了回调计时器的以下实现,可在我的 C++ 应用程序中使用。但是,此实现要求我“加入”来自 start 调用者的线程,这有效地阻止了 start 函数的调用者。

我真正喜欢做的是以下内容。

  1. 有人可以多次调用 foo(data) 并将它们存储在数据库中。
  2. 每当调用 foo(data) 时,它都会启动一个计时器,持续几秒钟。
  3. 当计时器倒计时时,foo(data) 可以被多次调用可以存储时间和多个项目,但在计时器完成之前不会调用删除
  4. 每当计时器到时,“删除”函数被调用一次以从中删除所有记录分贝。

基本上我希望能够完成一项任务,然后等待几秒钟,然后在几秒钟后批量执行单个批处理任务 B。

class CallBackTimer {

public:

/**
* Constructor of the CallBackTimer
*/
CallBackTimer() :_execute(false) { }

/**
* Destructor
*/
~CallBackTimer() {
if (_execute.load(std::memory_order_acquire)) {
stop();
};
}

/**
* Stops the timer
*/
void stop() {
_execute.store(false, std::memory_order_release);
if (_thd.joinable()) {
_thd.join();
}
}

/**
* Start the timer function
* @param interval Repeating duration in milliseconds, 0 indicates the @func will run only once
* @param delay Time in milliseconds to wait before the first callback
* @param func Callback function
*/
void start(int interval, int delay, std::function<void(void)> func) {
if(_execute.load(std::memory_order_acquire)) {
stop();
};
_execute.store(true, std::memory_order_release);


_thd = std::thread([this, interval, delay, func]() {
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
if (interval == 0) {
func();
stop();
} else {
while (_execute.load(std::memory_order_acquire)) {
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
}
}
});

}

/**
* Check if the timer is currently running
* @return bool, true if timer is running, false otherwise.
*/
bool is_running() const noexcept {
return ( _execute.load(std::memory_order_acquire) && _thd.joinable() );
}


private:
std::atomic<bool> _execute;
std::thread _thd;

};

我尝试使用 thread.detach() 修改上述代码。但是,我在无法从数据库中写入(删除)的分离线程中运行问题..

感谢任何帮助和建议!

最佳答案

您可以使用 std::async 而不是使用线程。以下类将在添加最后一个字符串后 4 秒按顺序处理排队的字符串。一次只会启动 1 个异步任务,std::aysnc 会为您处理所有线程。

如果在类被销毁时队列中有未处理的项目,那么异步任务会停止而不等待,并且不会处理这些项目(但如果这不是您想要的行为,这很容易改变)。

#include <iostream>
#include <string>
#include <future>
#include <mutex>
#include <chrono>
#include <queue>

class Batcher
{
public:
Batcher()
: taskDelay( 4 ),
startTime( std::chrono::steady_clock::now() ) // only used for debugging
{
}

void queue( const std::string& value )
{
std::unique_lock< std::mutex > lock( mutex );
std::cout << "queuing '" << value << " at " << std::chrono::duration_cast< std::chrono::milliseconds >( std::chrono::steady_clock::now() - startTime ).count() << "ms\n";
work.push( value );
// increase the time to process the queue to "now + 4 seconds"
timeout = std::chrono::steady_clock::now() + taskDelay;
if ( !running )
{
// launch a new asynchronous task which will process the queue
task = std::async( std::launch::async, [this]{ processWork(); } );
running = true;
}
}

~Batcher()
{
std::unique_lock< std::mutex > lock( mutex );
// stop processing the queue
closing = true;
bool wasRunning = running;
condition.notify_all();
lock.unlock();
if ( wasRunning )
{
// wait for the async task to complete
task.wait();
}
}

private:
std::mutex mutex;
std::condition_variable condition;
std::chrono::seconds taskDelay;
std::chrono::steady_clock::time_point timeout;
std::queue< std::string > work;
std::future< void > task;
bool closing = false;
bool running = false;
std::chrono::steady_clock::time_point startTime;

void processWork()
{
std::unique_lock< std::mutex > lock( mutex );
// loop until std::chrono::steady_clock::now() > timeout
auto wait = timeout - std::chrono::steady_clock::now();
while ( !closing && wait > std::chrono::seconds( 0 ) )
{
condition.wait_for( lock, wait );
wait = timeout - std::chrono::steady_clock::now();
}
if ( !closing )
{
std::cout << "processing queue at " << std::chrono::duration_cast< std::chrono::milliseconds >( std::chrono::steady_clock::now() - startTime ).count() << "ms\n";
while ( !work.empty() )
{
std::cout << work.front() << "\n";
work.pop();
}
std::cout << std::flush;
}
else
{
std::cout << "aborting queue processing at " << std::chrono::duration_cast< std::chrono::milliseconds >( std::chrono::steady_clock::now() - startTime ).count() << "ms with " << work.size() << " remaining items\n";
}
running = false;
}
};

int main()
{
Batcher batcher;
batcher.queue( "test 1" );
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
batcher.queue( "test 2" );
std::this_thread::sleep_for( std::chrono::seconds( 1 ) );
batcher.queue( "test 3" );
std::this_thread::sleep_for( std::chrono::seconds( 2 ) );
batcher.queue( "test 4" );
std::this_thread::sleep_for( std::chrono::seconds( 5 ) );
batcher.queue( "test 5" );
}

关于C++回调定时器实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52214038/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com