Skip to content

Commit

Permalink
Encapsulate the signal handler function for posix timers in a class
Browse files Browse the repository at this point in the history
  • Loading branch information
gansm committed Jul 24, 2023
1 parent f3d1943 commit 84a8dcc
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 45 deletions.
37 changes: 22 additions & 15 deletions examples/eventloop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,21 @@

#include <final/final.h>

finalcut::EventLoop Loop{};

struct termios OriginalTermIoSettings{};
struct Global
{
static struct termios original_term_io_settings; // global termios object
};

// static class attribute
struct termios Global::original_term_io_settings{};


//----------------------------------------------------------------------
void onExit()
{
// Restore terminal control
tcsetattr (STDIN_FILENO, TCSAFLUSH, &OriginalTermIoSettings);
tcsetattr (STDIN_FILENO, TCSAFLUSH, &Global::original_term_io_settings);
std::cout << "Bye!" << std::endl;
}

Expand All @@ -48,17 +54,18 @@ void onExit()

auto main() -> int
{
finalcut::TimerMonitor timer1{&Loop};
finalcut::TimerMonitor timer2{&Loop};
finalcut::SignalMonitor sig_int_monitor{&Loop};
finalcut::SignalMonitor sig_abrt_monitor{&Loop};
finalcut::IoMonitor stdin_monitor{&Loop};
finalcut::EventLoop loop{};
finalcut::TimerMonitor timer1{&loop};
finalcut::TimerMonitor timer2{&loop};
finalcut::SignalMonitor sig_int_monitor{&loop};
finalcut::SignalMonitor sig_abrt_monitor{&loop};
finalcut::IoMonitor stdin_monitor{&loop};

// Save terminal setting and set terminal to raw mode
// (no echo, no line buffering).
tcgetattr (STDIN_FILENO, &OriginalTermIoSettings);
tcgetattr (STDIN_FILENO, &Global::original_term_io_settings);
atexit (onExit);
struct termios new_term_io_settings{OriginalTermIoSettings};
struct termios new_term_io_settings{Global::original_term_io_settings};
new_term_io_settings.c_lflag &= ~(ECHO | ICANON);
tcsetattr (STDIN_FILENO, TCSAFLUSH, &new_term_io_settings);

Expand Down Expand Up @@ -86,20 +93,20 @@ auto main() -> int
, std::chrono::nanoseconds{ 1'000'000'000 } );

sig_int_monitor.init ( SIGINT
, [] (const finalcut::Monitor*, short)
, [&loop] (const finalcut::Monitor*, short)
{
std::cout << "Signal SIGINT received."
<< std::endl;
Loop.leave();
loop.leave();
}
, nullptr );

sig_abrt_monitor.init ( SIGABRT
, [] (const finalcut::Monitor*, short)
, [&loop] (const finalcut::Monitor*, short)
{
std::cout << "Signal SIGABRT received."
<< std::endl;
Loop.leave();
loop.leave();
}
, nullptr );

Expand All @@ -124,5 +131,5 @@ auto main() -> int
stdin_monitor.resume();

// Monitoring
return Loop.run();
return loop.run();
}
8 changes: 6 additions & 2 deletions final/eventloop/kqueue_timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ struct TimerNode

static std::vector<TimerNode> timer_nodes{};
static std::vector<struct kevent> time_events{};
static std::mutex timer_nodes_mutex{};


//----------------------------------------------------------------------
Expand All @@ -99,7 +98,8 @@ static std::mutex timer_nodes_mutex{};
class KqueueHandler
{
public:
void operator () (Monitor* monitor, short revents) const
// Overloaded operator
void operator () (Monitor* monitor, short revents)
{
std::lock_guard<std::mutex> lock_guard(timer_nodes_mutex);

Expand Down Expand Up @@ -149,6 +149,10 @@ class KqueueHandler
kqueue_timer_ptr->timer_handler(monitor, revents);
}
}

private:
// Data members
std::mutex timer_nodes_mutex{};
};


Expand Down
3 changes: 1 addition & 2 deletions final/eventloop/monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ namespace finalcut
// class monitor_error
//----------------------------------------------------------------------

monitor_error::~monitor_error()
{ }
monitor_error::~monitor_error() = default;


//----------------------------------------------------------------------
Expand Down
65 changes: 46 additions & 19 deletions final/eventloop/posix_timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ struct TimerNode
};

static std::list<TimerNode> timer_nodes{};
static std::mutex timer_nodes_mutex{};


//----------------------------------------------------------------------
Expand All @@ -86,32 +85,60 @@ static std::mutex timer_nodes_mutex{};
, static_cast<long>(duration.count()) };
}


//----------------------------------------------------------------------
// class SigAlrmHandler
//----------------------------------------------------------------------
static void onSigAlrm (int, siginfo_t* signal_info, void*)
{
const auto& timer_id = *static_cast<const timer_t*>(signal_info->si_value.sival_ptr);
std::lock_guard<std::mutex> lock_guard(timer_nodes_mutex);

for (const auto& timer_node : timer_nodes)
{
if ( timer_id != timer_node.timer_id )
continue;
class SigAlrmHandler
{
public:
// Using-declaration
using HandlerReturnType = void (*)(int, siginfo_t*, void*);

if ( timer_node.timer_monitor->isActive() )
// Overloaded operators
void operator () (int, siginfo_t* signal_info, void*)
{
// The event loop is notified by write access to the pipe
uint64_t buffer{1U};
auto successful = ::write (timer_node.fd, &buffer, sizeof(buffer)) > 0;
const auto& timer_id = *static_cast<const timer_t*>(signal_info->si_value.sival_ptr);
std::lock_guard<std::mutex> lock_guard(timer_nodes_mutex);

if ( ! successful )
for (const auto& timer_node : timer_nodes)
{
// Possible error handling
if ( timer_id != timer_node.timer_id )
continue;

if ( timer_node.timer_monitor->isActive() )
{
// The event loop is notified by write access to the pipe
uint64_t buffer{1U};
auto successful = ::write (timer_node.fd, &buffer, sizeof(buffer)) > 0;

if ( ! successful )
{
// Possible error handling
}
}

break;
}
}

break;
}
}
operator HandlerReturnType () const noexcept
{
// Converts a member function pointer to a function pointer
return invoke;
};

private:
// Method
static void invoke (int, siginfo_t* signal_info, void*)
{
return SigAlrmHandler{}.operator()(0, signal_info, nullptr);
}

// Data members
std::mutex timer_nodes_mutex{};
};


//----------------------------------------------------------------------
Expand Down Expand Up @@ -240,7 +267,7 @@ class SigAlrmHandlerInstaller
{
struct sigaction signal_handle{};
sigemptyset(&signal_handle.sa_mask);
signal_handle.sa_sigaction = onSigAlrm;
signal_handle.sa_sigaction = SigAlrmHandler();
signal_handle.sa_flags = SA_SIGINFO;

if ( sigaction(SIGALRM, &signal_handle, &original_signal_handle) != -1 )
Expand Down
19 changes: 13 additions & 6 deletions final/eventloop/timer_monitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ namespace finalcut
class TimerMonitorImpl : public Monitor
{
public:
// Using-declaration
using Monitor::Monitor;

// Constructor
explicit TimerMonitorImpl (EventLoop* eloop)
: Monitor(eloop)
Expand Down Expand Up @@ -108,8 +111,8 @@ class PosixTimer : public TimerMonitorImpl
, std::chrono::nanoseconds ) override;
void trigger(short) override;

private:
#if defined(USE_POSIX_TIMER)
private:
// Data members
timer_t timer_id{};
std::array<int, 2> alarm_pipe_fd{NO_FILE_DESCRIPTOR, NO_FILE_DESCRIPTOR};
Expand All @@ -136,18 +139,18 @@ class KqueueTimer : public TimerMonitorImpl
, std::chrono::nanoseconds ) override;
void trigger(short) override;

private:
#if defined(USE_KQUEUE_TIMER)
// Constants
static constexpr int NO_TIMER_ID{-1};

// Data members
private:
struct TimerSpec
{
int period_ms{};
int first_ms{};
};

// Constants
static constexpr int NO_TIMER_ID{-1};

// Data members
int timer_id{NO_TIMER_ID};
bool first_interval{true};
TimerSpec timer_spec{};
Expand Down Expand Up @@ -182,6 +185,10 @@ struct TimerClass
class TimerMonitor final : public TimerClass::type
{
public:
// Using-declarations
using base_class = TimerClass::type;
using base_class::base_class;

TimerMonitor() = delete;

// Disable copy constructor
Expand Down
2 changes: 1 addition & 1 deletion final/input/fmouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class FMouseGPM final : public FMouse
};

// Method
auto gpmEvent (bool = true) const -> gpmEventType;
auto gpmEvent (bool = true) const -> gpmEventType;

// Data member
Gpm_Event gpm_ev{};
Expand Down

0 comments on commit 84a8dcc

Please sign in to comment.