Skip to content

Commit

Permalink
Lazy initialization of global static objects
Browse files Browse the repository at this point in the history
  • Loading branch information
gansm committed Aug 6, 2023
1 parent 5132007 commit 9d02d65
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 116 deletions.
1 change: 1 addition & 0 deletions final/eventloop/eventloop_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <cstddef>
#include <system_error>

#include "final/eventloop/eventloop_functions.h"
#include "final/ftypes.h"

namespace finalcut
Expand Down
2 changes: 0 additions & 2 deletions final/eventloop/eventloop_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
#error "Only <final/final.h> can be included directly."
#endif

#include "final/eventloop/eventloop_functions.h"

namespace finalcut
{

Expand Down
107 changes: 71 additions & 36 deletions final/eventloop/kqueue_timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@
namespace finalcut
{

// struct forward declaration
struct TimerNode;

// Using-declaration
using TimerNodesList = std::vector<TimerNode>;
using KEventList = std::vector<struct kevent>;


//----------------------------------------------------------------------
static auto getKqueue() -> int
{
Expand All @@ -66,6 +74,22 @@ constexpr auto durationToMilliseconds (std::chrono::nanoseconds duration) -> int
return int(std::chrono::duration_cast<std::chrono::milliseconds>(duration).count());
}

//----------------------------------------------------------------------
static auto getTimerNodes() -> TimerNodesList&
{
// Encapsulate global list object
static const auto& timer_nodes = std::make_unique<TimerNodesList>();
return *timer_nodes;
}

//----------------------------------------------------------------------
static auto getKEvents() -> KEventList&
{
// Encapsulate global list object
static const auto& time_events = std::make_unique<KEventList>();
return *time_events;
}


//----------------------------------------------------------------------
// struct TimerNode
Expand All @@ -87,9 +111,6 @@ struct TimerNode
KqueueTimer* timer_monitor{};
};

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


//----------------------------------------------------------------------
// class KqueueHandler
Expand All @@ -116,6 +137,7 @@ class KqueueHandler final

// Check active events in the event list
struct timespec timeout{0, 0}; // Do not wait
auto& time_events = getKEvents();
auto data = time_events.data();
const auto size = time_events.size();
const auto n = ::kevent(getKqueue(), nullptr, 0, data, size, &timeout);
Expand All @@ -133,6 +155,7 @@ class KqueueHandler final
{
return item.timer_id == ident;
};
auto& timer_nodes = getTimerNodes();
const auto iter = std::find_if( timer_nodes.begin()
, timer_nodes.end()
, is_timer_id );
Expand Down Expand Up @@ -167,6 +190,44 @@ class KqueueHandler final
};


//----------------------------------------------------------------------
// struct KqueueHandlerInstaller
//----------------------------------------------------------------------

struct KqueueHandlerInstaller final
{
// constructor
KqueueHandlerInstaller()
{
// Creates a new kernel event queue
if ( getKqueue() != -1 )
return;

// Could not get kqueue
const int error = errno;
std::error_code err_code{error, std::generic_category()};
std::system_error sys_err{err_code, strerror(error)};
throw sys_err;
}

// destructor
~KqueueHandlerInstaller()
{
::close(getKqueue());
}
};

//----------------------------------------------------------------------
static auto startKqueueHandlerInstaller() -> KqueueHandlerInstaller*
{
static const auto& kqueue_handler = std::make_unique<KqueueHandlerInstaller>();
return kqueue_handler.get();
}

// static class attributes
KqueueHandlerInstaller* KqueueTimer::kqueue_handler_installer{};


//----------------------------------------------------------------------
// class KqueueTimer
//----------------------------------------------------------------------
Expand All @@ -175,11 +236,15 @@ class KqueueHandler final
//----------------------------------------------------------------------
KqueueTimer::KqueueTimer (EventLoop* eloop)
: TimerMonitorImpl(eloop)
{ }
{
kqueue_handler_installer = startKqueueHandlerInstaller();
}

//----------------------------------------------------------------------
KqueueTimer::~KqueueTimer() noexcept // destructor
{
auto& timer_nodes{getTimerNodes()};
auto& time_events{getKEvents()};
auto iter{timer_nodes.begin()};

while ( iter != timer_nodes.end() )
Expand Down Expand Up @@ -216,8 +281,8 @@ void KqueueTimer::init (handler_t hdl, void* uc)
setUserContext (uc);
timer_id = getTimerID();
timer_handler = std::move(hdl);
time_events.emplace_back();
timer_nodes.emplace_back(timer_id, this);
getKEvents().emplace_back();
getTimerNodes().emplace_back(timer_id, this);
setInitialized();
}

Expand Down Expand Up @@ -245,36 +310,6 @@ void KqueueTimer::trigger (short return_events)
Monitor::trigger(return_events);
}


//----------------------------------------------------------------------
// struct KqueueHandlerInstaller
//----------------------------------------------------------------------

struct KqueueHandlerInstaller final
{
// constructor
KqueueHandlerInstaller()
{
// Creates a new kernel event queue
if ( getKqueue() != -1 )
return;

// Could not get kqueue
const int error = errno;
std::error_code err_code{error, std::generic_category()};
std::system_error sys_err{err_code, strerror(error)};
throw sys_err;
}

// destructor
~KqueueHandlerInstaller()
{
::close(getKqueue());
}
};

KqueueHandlerInstaller Installer{};

} // namespace finalcut

#endif // defined(USE_KQUEUE_TIMER)
4 changes: 2 additions & 2 deletions final/eventloop/monitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class Monitor
void setInitialized();

// Inquiry
auto isInitialized() -> bool;
auto isInitialized() const -> bool;

// Methods
virtual void trigger (short);
Expand Down Expand Up @@ -196,7 +196,7 @@ inline void Monitor::setInitialized()
{ monitor_initialized = true; }

//----------------------------------------------------------------------
inline auto Monitor::isInitialized() -> bool
inline auto Monitor::isInitialized() const -> bool
{ return monitor_initialized; }

} // namespace finalcut
Expand Down
Loading

0 comments on commit 9d02d65

Please sign in to comment.