Skip to content

Commit

Permalink
Add monitor_manager
Browse files Browse the repository at this point in the history
  • Loading branch information
tekezo committed Sep 23, 2023
1 parent 3bd215a commit 5ccf213
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
19 changes: 18 additions & 1 deletion include/pqrs/osx/frontmost_application_monitor/monitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "application.hpp"
#include "impl/impl.h"
#include "monitor_manager.hpp"
#include <nod/nod.hpp>
#include <pqrs/dispatcher.hpp>

Expand All @@ -25,12 +26,19 @@ class monitor final : public dispatcher::extra::dispatcher_client {
monitor(const monitor&) = delete;

monitor(std::weak_ptr<dispatcher::dispatcher> weak_dispatcher) : dispatcher_client(weak_dispatcher) {
std::lock_guard<std::mutex> guard(global_monitor_manager_mutex_);

monitor_manager::get_global_monitor_manager()->insert(this);
}

virtual ~monitor(void) {
std::lock_guard<std::mutex> guard(global_monitor_manager_mutex_);

detach_from_dispatcher([this] {
stop();
});

monitor_manager::get_global_monitor_manager()->erase(this);
}

void async_start(void) {
Expand All @@ -57,9 +65,16 @@ class monitor final : public dispatcher::extra::dispatcher_client {
static void static_cpp_callback(const char* bundle_identifier,
const char* file_path,
void* context) {
std::lock_guard<std::mutex> guard(global_monitor_manager_mutex_);

auto m = reinterpret_cast<monitor*>(context);
if (m) {
m->cpp_callback(bundle_identifier, file_path);
// `static_cpp_callback` may be called even after the monitor instance has been deleted,
// so we need to check whether monitor is still alive.
if (monitor_manager::get_global_monitor_manager()->contains(m)) {
m->cpp_callback(bundle_identifier,
file_path);
}
}
}

Expand All @@ -77,6 +92,8 @@ class monitor final : public dispatcher::extra::dispatcher_client {
frontmost_application_changed(application_ptr);
});
}

static inline std::mutex global_monitor_manager_mutex_;
};
} // namespace frontmost_application_monitor
} // namespace osx
Expand Down
51 changes: 51 additions & 0 deletions include/pqrs/osx/frontmost_application_monitor/monitor_manager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

// (C) Copyright Takayama Fumihiko 2023.
// Distributed under the Boost Software License, Version 1.0.
// (See https://www.boost.org/LICENSE_1_0.txt)

#include "application.hpp"
#include "impl/impl.h"
#include <nod/nod.hpp>
#include <pqrs/dispatcher.hpp>

namespace pqrs {
namespace osx {
namespace frontmost_application_monitor {
class monitor;

// Manage valid frontmost_application_monitor::monitor instances with monitor_manager because
// the callbacks implemented in PQRSOSXFrontmostApplicationMonitor.swift are not cleanly consistent with the lifetime of monitor.
class monitor_manager final {
public:
static std::shared_ptr<monitor_manager> get_global_monitor_manager(void) {
if (!monitor_manager_) {
monitor_manager_ = std::make_shared<monitor_manager>();
}

return monitor_manager_;
}

monitor_manager(void) {
}

bool contains(const monitor* monitor_pointer) const {
return monitor_pointers_.contains(monitor_pointer);
}

void insert(const monitor* monitor_pointer) {
monitor_pointers_.insert(monitor_pointer);
}

void erase(const monitor* monitor_pointer) {
monitor_pointers_.erase(monitor_pointer);
}

private:
static inline std::shared_ptr<monitor_manager> monitor_manager_;

std::unordered_set<const monitor*> monitor_pointers_;
};
} // namespace frontmost_application_monitor
} // namespace osx
} // namespace pqrs

0 comments on commit 5ccf213

Please sign in to comment.