source/base: Make callback handling generic
diff --git a/src/sdeventplus/source/base.cpp b/src/sdeventplus/source/base.cpp
index 32e6edf..d63a03e 100644
--- a/src/sdeventplus/source/base.cpp
+++ b/src/sdeventplus/source/base.cpp
@@ -1,9 +1,6 @@
-#include <cerrno>
-#include <cstdio>
#include <functional>
#include <sdeventplus/exception.hpp>
#include <sdeventplus/internal/sdevent.hpp>
-#include <sdeventplus/internal/utils.hpp>
#include <sdeventplus/source/base.hpp>
#include <type_traits>
#include <utility>
@@ -53,22 +50,10 @@
}
}
-static int prepare_callback(sd_event_source*, void* userdata)
-{
- if (userdata == nullptr)
- {
- fprintf(stderr, "sdeventplus: prepare_callback: Missing userdata\n");
- return -EINVAL;
- }
- Base* base = reinterpret_cast<Base*>(userdata);
- return internal::performCallback("prepare_callback", base->get_prepare(),
- std::ref(*base));
-}
-
void Base::set_prepare(Callback&& callback)
{
int r = event.getSdEvent()->sd_event_source_set_prepare(
- source.get(), callback ? prepare_callback : nullptr);
+ source.get(), callback ? prepareCallback : nullptr);
if (r < 0)
{
prepare = nullptr;
@@ -179,6 +164,12 @@
return *this;
}
+int Base::prepareCallback(sd_event_source* source, void* userdata)
+{
+ return sourceCallback<Callback, Base, &Base::get_prepare>("prepareCallback",
+ source, userdata);
+}
+
void Base::set_userdata()
{
event.getSdEvent()->sd_event_source_set_userdata(source.get(), this);
diff --git a/src/sdeventplus/source/base.hpp b/src/sdeventplus/source/base.hpp
index 9253b71..d37102b 100644
--- a/src/sdeventplus/source/base.hpp
+++ b/src/sdeventplus/source/base.hpp
@@ -1,9 +1,12 @@
#pragma once
+#include <cerrno>
#include <cstdint>
+#include <cstdio>
#include <functional>
#include <sdeventplus/event.hpp>
#include <sdeventplus/internal/sdref.hpp>
+#include <sdeventplus/internal/utils.hpp>
#include <systemd/sd-bus.h>
#include <type_traits>
@@ -25,7 +28,6 @@
const char* get_description() const;
void set_description(const char* description) const;
void set_prepare(Callback&& callback);
- const Callback& get_prepare() const;
int get_pending() const;
int64_t get_priority() const;
void set_priority(int64_t priority) const;
@@ -48,10 +50,28 @@
Base(Base&& other);
Base& operator=(Base&& other);
+ const Callback& get_prepare() const;
+
+ template <typename Callback, class Source,
+ const Callback& (Source::*getter)() const, typename... Args>
+ static int sourceCallback(const char* name, sd_event_source*,
+ void* userdata, Args... args)
+ {
+ if (userdata == nullptr)
+ {
+ fprintf(stderr, "sdeventplus: %s: Missing userdata\n", name);
+ return -EINVAL;
+ }
+ Source* source = reinterpret_cast<Source*>(userdata);
+ return internal::performCallback(name, (source->*getter)(),
+ std::ref(*source), args...);
+ }
+
private:
Callback prepare;
void set_userdata();
+ static int prepareCallback(sd_event_source* source, void* userdata);
};
} // namespace source
diff --git a/test/source/base.cpp b/test/source/base.cpp
index 435b6f2..bc0eec0 100644
--- a/test/source/base.cpp
+++ b/test/source/base.cpp
@@ -36,6 +36,8 @@
Base(event, source, std::false_type())
{
}
+
+ using Base::get_prepare;
};
class BaseTest : public testing::Test
@@ -76,7 +78,7 @@
return ret;
}
- void set_prepare_placeholder(Base& base)
+ void set_prepare_placeholder(BaseImpl& base)
{
EXPECT_CALL(mock, sd_event_source_set_prepare(base.get(), testing::_))
.WillOnce(Return(0));