블라드, 우수한 게시물을! 코드가 컴파일되고 아름답게 작동합니다. 나는 소프트웨어 워치 독 타이머를 구현했다.
- 포인터 감쇠를 방지하려면 신호를 boost :: shared_ptr에 저장하고 이것을 타이머 클래스의 약한 포인터 대신 스레드 작업자에게 전달하십시오. 이렇게하면 스레드 작업자가 친구 구조체가 될 필요가 없으므로 신호가 메모리에 있음을 보장 할 수 있습니다.
- _is_periodic 매개 변수를 추가하여 호출자가 작업자 스레드가 주기적인지 또는 만료 후에 종료되는지 여부를 선택할 수있게합니다.
- 스레드 안전 액세스를 허용하기 위해 boost :: atomic에 _is_active, _interval 및 _is_periodic을 저장하십시오.
- 뮤텍스 잠금 범위를 좁히십시오.
- timer를 "실행"하여 만료 신호를 내지 않도록 reset() 메서드를 추가합니다. 이러한 변화와
적용 :
#include <atomic>
#include <boost/signals2.hpp>
#include <boost/thread.hpp>
class IntervalThread
{
using interval_signal = boost::signals2::signal<void(void)>;
public:
using interval_slot_t = interval_signal::slot_type;
IntervalThread(const int interval_ms = 60)
: _interval_ms(interval_ms),
_is_active(false),
_is_periodic(false),
_signal_expired(new interval_signal()) {};
inline ~IntervalThread(void) { stop(); };
boost::signals2::connection connect(const interval_slot_t &subscriber)
{
// thread-safe: signals2 obtains a mutex on connect()
return _signal_expired->connect(subscriber);
};
void start(void)
{
if (is_active())
return; // Already executed.
if (get_interval_ms() <= 0)
return;
boost::lock_guard<boost::mutex> lock(_timer_thread_guard);
_timer_thread.interrupt();
_timer_thread.join();
_timer_thread = boost::thread(timer_worker(),
static_cast<int>(get_interval_ms()),
static_cast<bool>(is_periodic()),
_signal_expired);
_is_active = true;
};
void reset(void)
{
if (is_active())
stop();
start();
}
void stop(void)
{
if (!is_active())
return; // Already executed.
boost::lock_guard<boost::mutex> lock(_timer_thread_guard);
_timer_thread.interrupt();
_timer_thread.join();
_is_active = false;
};
inline bool is_active(void) const { return _is_active; };
inline int get_interval_ms(void) const { return _interval_ms; };
void set_interval_ms(const int interval_ms)
{
if (interval_ms <= 0 || get_interval_ms() == interval_ms)
return;
// Cache timer activity state.
const bool was_active = is_active();
// Initialize timer with new interval.
if (was_active)
stop();
_interval_ms = interval_ms;
if (was_active)
start();
};
inline bool is_periodic(void) const { return _is_periodic; }
inline void set_periodic(const bool is_periodic = true) { _is_periodic = is_periodic; }
private:
// The timer worker for the interval thread.
struct timer_worker {
void operator()(const int interval_ms, const bool is_periodic, boost::shared_ptr<interval_signal> signal_expired)
{
boost::posix_time::milliseconds duration(interval_ms);
try {
do {
boost::this_thread::sleep<boost::posix_time::milliseconds>(duration);
{
boost::this_thread::disable_interruption di;
signal_expired->operator()();
}
} while (is_periodic);
} catch (const boost::thread_interrupted &) {
// IntervalThread start(), stop() and reset() throws boost::this_thread::interrupt,
// which is expected since this thread is interrupted. No action neccessary.
}
};
};
std::atomic<int> _interval_ms; // Interval, in ms
std::atomic<bool> _is_active; // Is the timed interval active?
std::atomic<bool> _is_periodic; // Is the timer periodic?
boost::mutex _timer_thread_guard;
boost::thread _timer_thread;
// The signal to call on interval expiration.
boost::shared_ptr<interval_signal> _signal_expired;
};
그냥'timed_join' *이 *은'푸()가'생각대로 제한 시간에 도달하면 스레드의 실행이 아론이 물어 봤다 멈추지 않을 것입니다, 명확하게 에 대한. 대신, 호출자는 단지 타임 아웃에 도달했을 때'Foo()'쓰레드가 계속 실행 중임을 알 것이다. – pilcrow