source: Add class
diff --git a/.gitignore b/.gitignore
index 971e588..99b73dc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,3 +45,4 @@
 /test/event
 /test/exception
 /test/sdref
+/test/source
diff --git a/src/Makefile.am b/src/Makefile.am
index f1516ba..8c48eeb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,6 +14,9 @@
 nobase_include_HEADERS += sdeventplus/exception.hpp
 libsdeventplus_la_SOURCES += sdeventplus/exception.cpp
 
+nobase_include_HEADERS += sdeventplus/source.hpp
+libsdeventplus_la_SOURCES += sdeventplus/source.cpp
+
 nobase_include_HEADERS += sdeventplus/internal/sdevent.hpp
 libsdeventplus_la_SOURCES += sdeventplus/internal/sdevent.cpp
 
diff --git a/src/sdeventplus/internal/sdevent.hpp b/src/sdeventplus/internal/sdevent.hpp
index 129e67f..fd4bd77 100644
--- a/src/sdeventplus/internal/sdevent.hpp
+++ b/src/sdeventplus/internal/sdevent.hpp
@@ -16,6 +16,11 @@
     virtual sd_event *sd_event_unref(sd_event *event) const = 0;
 
     virtual int sd_event_loop(sd_event *event) const = 0;
+
+    virtual sd_event_source *
+        sd_event_source_ref(sd_event_source *source) const = 0;
+    virtual sd_event_source *
+        sd_event_source_unref(sd_event_source *source) const = 0;
 };
 
 class SdEventImpl : public SdEventInterface
@@ -45,6 +50,16 @@
     {
         return ::sd_event_loop(event);
     }
+
+    sd_event_source *sd_event_source_ref(sd_event_source *source) const override
+    {
+        return ::sd_event_source_ref(source);
+    }
+    sd_event_source *
+        sd_event_source_unref(sd_event_source *source) const override
+    {
+        return ::sd_event_source_unref(source);
+    }
 };
 
 extern SdEventImpl sdevent_impl;
diff --git a/src/sdeventplus/source.cpp b/src/sdeventplus/source.cpp
new file mode 100644
index 0000000..eb3c903
--- /dev/null
+++ b/src/sdeventplus/source.cpp
@@ -0,0 +1,21 @@
+#include <sdeventplus/source.hpp>
+#include <type_traits>
+
+namespace sdeventplus
+{
+
+Source::Source(sd_event_source* source, SdEventInterface* intf) :
+    intf(intf), source(source, &SdEventInterface::sd_event_source_ref,
+                       &SdEventInterface::sd_event_source_unref, intf)
+{
+}
+
+Source::Source(sd_event_source* source, std::false_type,
+               SdEventInterface* intf) :
+    intf(intf),
+    source(source, &SdEventInterface::sd_event_source_ref,
+           &SdEventInterface::sd_event_source_unref, std::false_type(), intf)
+{
+}
+
+} // namespace sdeventplus
diff --git a/src/sdeventplus/source.hpp b/src/sdeventplus/source.hpp
new file mode 100644
index 0000000..9921a88
--- /dev/null
+++ b/src/sdeventplus/source.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <sdeventplus/internal/sdevent.hpp>
+#include <sdeventplus/internal/sdref.hpp>
+#include <type_traits>
+
+namespace sdeventplus
+{
+
+class Source
+{
+  public:
+    Source(sd_event_source* source, SdEventInterface* intf = &sdevent_impl);
+    Source(sd_event_source* source, std::false_type,
+           SdEventInterface* intf = &sdevent_impl);
+
+  private:
+    SdEventInterface* intf;
+    SdRef<sd_event_source> source;
+};
+
+} // namespace sdeventplus
diff --git a/src/sdeventplus/test/sdevent.hpp b/src/sdeventplus/test/sdevent.hpp
index 7cea28d..c43b983 100644
--- a/src/sdeventplus/test/sdevent.hpp
+++ b/src/sdeventplus/test/sdevent.hpp
@@ -16,6 +16,11 @@
     MOCK_CONST_METHOD1(sd_event_unref, sd_event *(sd_event *));
 
     MOCK_CONST_METHOD1(sd_event_loop, int(sd_event *));
+
+    MOCK_CONST_METHOD1(sd_event_source_ref,
+                       sd_event_source *(sd_event_source *));
+    MOCK_CONST_METHOD1(sd_event_source_unref,
+                       sd_event_source *(sd_event_source *));
 };
 
 } // namespace sdeventplus
diff --git a/test/Makefile.am b/test/Makefile.am
index 7efd9b2..7534c42 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -24,3 +24,7 @@
 check_PROGRAMS += sdref
 sdref_SOURCES = sdref.cpp
 sdref_LDADD = $(gtest_ldadd)
+
+check_PROGRAMS += source
+source_SOURCES = source.cpp
+source_LDADD = $(gtest_ldadd)
diff --git a/test/source.cpp b/test/source.cpp
new file mode 100644
index 0000000..4fa87ab
--- /dev/null
+++ b/test/source.cpp
@@ -0,0 +1,40 @@
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <sdeventplus/source.hpp>
+#include <sdeventplus/test/sdevent.hpp>
+
+namespace sdeventplus
+{
+namespace
+{
+
+using testing::Return;
+
+class SourceTest : public testing::Test
+{
+  protected:
+    testing::StrictMock<SdEventMock> mock;
+    sd_event_source *const expected_source =
+        reinterpret_cast<sd_event_source *>(1234);
+};
+
+TEST_F(SourceTest, NewSourceRef)
+{
+    EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+        .WillOnce(Return(expected_source));
+    Source source(expected_source, &mock);
+
+    EXPECT_CALL(mock, sd_event_source_unref(expected_source))
+        .WillOnce(Return(nullptr));
+}
+
+TEST_F(SourceTest, NewSourceNoRef)
+{
+    Source source(expected_source, std::false_type(), &mock);
+
+    EXPECT_CALL(mock, sd_event_source_unref(expected_source))
+        .WillOnce(Return(nullptr));
+}
+
+} // namespace
+} // namespace sdeventplus