Repository: LadybirdBrowser/ladybird
File: Libraries/LibWebView/EventLoop/EventLoopImplementationMacOS.mm (Objective-C++)

Code before:

EventLoopImplementationMacOS::EventLoopImplementationMacOS()
    : m_impl(adopt_own(*new Impl))
{
    m_impl->run_loop = CFRunLoopGetCurrent();
    CFRunLoopSourceContext ctx {};
    ctx.info = this;
    ctx.perform = [](void* info) {
        auto& self = *static_cast<EventLoopImplementationMacOS*>(info);
        self.m_impl->deferred_source_pending = false;
        self.m_thread_event_queue.process();
    };
    m_impl->deferred_source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &ctx);
    CFRunLoopAddSource(m_impl->run_loop, m_impl->deferred_source, kCFRunLoopCommonModes);
}

EventLoopImplementationMacOS::~EventLoopImplementationMacOS()
{
    if (m_impl->deferred_source) {
        CFRunLoopRemoveSource(m_impl->run_loop, m_impl->deferred_source, kCFRunLoopCommonModes);
        CFRelease(m_impl->deferred_source);
    }
}

NonnullOwnPtr<Core::EventLoopImplementation> EventLoopManagerMacOS::make_implementation()
{
    return EventLoopImplementationMacOS::create();
}

intptr_t EventLoopManagerMacOS::register_timer(Core::EventReceiver& receiver, int interval_milliseconds, bool should_reload)
{
    auto& thread_data = ThreadData::the();

    auto timer_id = thread_data.timer_id_allocator.allocate();
    auto weak_receiver = receiver.make_weak_ptr();

    auto interval_seconds = static_cast<double>(interval_milliseconds) / 1000.0;
    auto first_fire_time = CFAbsoluteTimeGetCurrent() + interval_seconds;

    auto* timer = CFRunLoopTimerCreateWithHandler(
        kCFAllocatorDefault, first_fire_time, should_reload ? interval_seconds : 0, 0, 0,
        ^(CFRunLoopTimerRef) {
            auto receiver = weak_receiver.strong_ref();
            if (!receiver) {
                return;
            }

            Core::TimerEvent event;
            receiver->dispatch_event(event);
        });


Review comment (bug):
This feels more appropriate to be in `Impl`'s constructor/destructor instead:
(let's also avoid shorthand names like `ctx`, we call related types `context` everywhere else in this file):

```c++
struct EventLoopImplementationMacOS::Impl {
    Impl()
        : run_loop(CFRunLoopGetCurrent())
    {
        CFRunLoopSourceContext context {};
        context.info = this;
        context.perform = [](void* info) {
            auto& self = *static_cast<EventLoopImplementationMacOS*>(info);
            self.m_impl->deferred_source_pending = false;
            self.m_thread_event_queue.process();
        };

        deferred_source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
        CFRunLoopAddSource(run_loop, deferred_source, kCFRunLoopCommonModes);
    }

    ~Impl()
    {
        CFRunLoopRemoveSource(run_loop, deferred_source, kCFRunLoopCommonModes);
        CFRelease(deferred_source);
    }

    CFRunLoopRef run_loop { nullptr };
    CFRunLoopSourceRef deferred_source { nullptr };
    Atomic<bool> deferred_source_pending { false };
};

EventLoopImplementationMacOS::EventLoopImplementationMacOS()
    : m_impl(make<Impl>())
{
}

EventLoopImplementationMacOS::~EventLoopImplementationMacOS() = default;
```

Code after:
        context.info = &event_loop_implementation;
        context.perform = [](void* info) {
            auto& self = *static_cast<EventLoopImplementationMacOS*>(info);
            self.m_impl->deferred_source_pending = false;
            self.m_thread_event_queue.process();
        };

        deferred_source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
        CFRunLoopAddSource(run_loop, deferred_source, kCFRunLoopCommonModes);
    }

    ~Impl()
    {
        CFRunLoopRemoveSource(run_loop, deferred_source, kCFRunLoopCommonModes);
        CFRelease(deferred_source);
    }

    CFRunLoopRef run_loop { nullptr };
    CFRunLoopSourceRef deferred_source { nullptr };
    Atomic<bool> deferred_source_pending { false };
};

EventLoopImplementationMacOS::EventLoopImplementationMacOS()
    : m_impl(make<Impl>(*this))
{
}

EventLoopImplementationMacOS::~EventLoopImplementationMacOS() = default;

NonnullOwnPtr<Core::EventLoopImplementation> EventLoopManagerMacOS::make_implementation()
{
    return EventLoopImplementationMacOS::create();
}

intptr_t EventLoopManagerMacOS::register_timer(Core::EventReceiver& receiver, int interval_milliseconds, bool should_reload)
{
    auto& thread_data = ThreadData::the();

    auto timer_id = thread_data.timer_id_allocator.allocate();
    auto weak_receiver = receiver.make_weak_ptr();

    auto interval_seconds = static_cast<double>(interval_milliseconds) / 1000.0;
    auto first_fire_time = CFAbsoluteTimeGetCurrent() + interval_seconds;

    auto* timer = CFRunLoopTimerCreateWithHandler(
        kCFAllocatorDefault, first_fire_time, should_reload ? interval_seconds : 0, 0, 0,
        ^(CFRunLoopTimerRef) {
            auto receiver = weak_receiver.strong_ref();
            if (!receiver) {
                return;
            }