(작성중) sdbus addwatch
2026. 4. 22. 17:59#pragma once
#include <sdbus-c++/sdbus-c++.h>
#include <unordered_map>
#include <string>
#include <functional>
#include <iostream>
class ServiceWatcher
{
public:
using AppearedCallback = std::function<void(const std::string& name,
const std::string& newOwner)>;
using DisappearedCallback = std::function<void(const std::string& name,
const std::string& oldOwner)>;
explicit ServiceWatcher(sdbus::IConnection& conn)
: conn_(conn)
{}
// ✅ sender 감시 추가
void watch(const std::string& sender,
AppearedCallback onAppeared,
DisappearedCallback onDisappeared)
{
// 이미 감시 중이면 무시
if (slots_.count(sender)) {
std::cout << "[Watcher] Already watching: " << sender << "\n";
return;
}
const std::string matchRule =
"type='signal',"
"sender='org.freedesktop.DBus',"
"interface='org.freedesktop.DBus',"
"member='NameOwnerChanged',"
"arg0='" + sender + "'";
// ✅ return_slot으로 slot 반환받아 map에 보관
auto slot = conn_.addMatch(
matchRule,
[sender, onAppeared, onDisappeared](sdbus::Message msg) {
std::string name, oldOwner, newOwner;
msg >> name >> oldOwner >> newOwner;
if (oldOwner.empty() && !newOwner.empty()) {
if (onAppeared)
onAppeared(name, newOwner);
} else if (!oldOwner.empty() && newOwner.empty()) {
if (onDisappeared)
onDisappeared(name, oldOwner);
}
},
sdbus::return_slot // ✅ slot 반환 받기
);
slots_.emplace(sender, std::move(slot));
std::cout << "[Watcher] Started watching: " << sender << "\n";
}
// ✅ sender 감시 해제
void unwatch(const std::string& sender)
{
auto it = slots_.find(sender);
if (it == slots_.end()) {
std::cout << "[Watcher] Not watching: " << sender << "\n";
return;
}
// slot 소멸 → match rule 자동 해제
slots_.erase(it);
std::cout << "[Watcher] Stopped watching: " << sender << "\n";
}
// ✅ 현재 감시 중인 sender 목록
std::vector<std::string> watchList() const
{
std::vector<std::string> list;
for (const auto& [sender, _] : slots_) {
list.push_back(sender);
}
return list;
}
// ✅ 모든 감시 해제
void unwatchAll()
{
slots_.clear();
std::cout << "[Watcher] All watches cleared\n";
}
private:
sdbus::IConnection& conn_;
// sender → slot (slot 소멸 시 match rule 자동 해제)
std::unordered_map<std::string, sdbus::Slot> slots_;
};
#include <sdbus-c++/sdbus-c++.h>
#include <iostream>
class ServiceWatcher
{
public:
ServiceWatcher(sdbus::IConnection& conn,
std::string watchedService)
: conn_(conn)
, watchedService_(std::move(watchedService))
{
// NameOwnerChanged 시그널 match rule 등록
const std::string matchRule =
"type='signal',"
"sender='org.freedesktop.DBus',"
"interface='org.freedesktop.DBus',"
"member='NameOwnerChanged',"
"arg0='" + watchedService_ + "'";
// ✅ v2.0.0: addMatch (floating - connection 수명에 묶임)
conn_.addMatch(
matchRule,
[this](sdbus::Message msg) {
onNameOwnerChanged(msg);
}
);
std::cout << "[Watcher] Watching: " << watchedService_ << "\n";
}
private:
void onNameOwnerChanged(sdbus::Message& msg)
{
std::string name, oldOwner, newOwner;
msg >> name >> oldOwner >> newOwner;
if (oldOwner.empty() && !newOwner.empty()) {
// ✅ 서비스 등장
onServiceAppeared(name, newOwner);
} else if (!oldOwner.empty() && newOwner.empty()) {
// ✅ 서비스 사라짐
onServiceDisappeared(name, oldOwner);
}
}
void onServiceAppeared(const std::string& name,
const std::string& newOwner)
{
std::cout << "[Watcher] Appeared : " << name
<< " (owner: " << newOwner << ")\n";
// 여기서 원하는 작업 수행
}
void onServiceDisappeared(const std::string& name,
const std::string& oldOwner)
{
std::cout << "[Watcher] Disappeared: " << name
<< " (was: " << oldOwner << ")\n";
// 여기서 원하는 작업 수행
}
sdbus::IConnection& conn_;
std::string watchedService_;
};
int main()
{
auto conn = sdbus::createSessionBusConnection();
// ✅ org.example.Calculator 서비스를 감시
ServiceWatcher watcher{*conn, "org.example.Calculator"};
std::cout << "Watching for service...\n";
conn->enterEventLoop();
return 0;
}