source/base: Support floating sources

This allows the source to stay attached to the event loop even if all of
the source handles are unreferenced.

Change-Id: I81e97674869ceba3e71479efa6ce38a67c0ba5c7
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/sdeventplus/source/base.cpp b/src/sdeventplus/source/base.cpp
index 6b80430..f4ed15b 100644
--- a/src/sdeventplus/source/base.cpp
+++ b/src/sdeventplus/source/base.cpp
@@ -92,6 +92,20 @@
                         event.getSdEvent(), get(), static_cast<int>(enabled));
 }
 
+bool Base::get_floating() const
+{
+    return internal::callCheck("sd_event_source_get_floating",
+                               &internal::SdEvent::sd_event_source_get_floating,
+                               event.getSdEvent(), get());
+}
+
+void Base::set_floating(bool b) const
+{
+    internal::callCheck("sd_event_source_set_floating",
+                        &internal::SdEvent::sd_event_source_set_floating,
+                        event.getSdEvent(), get(), static_cast<int>(b));
+}
+
 Base::Base(const Event& event, sd_event_source* source, std::false_type) :
     event(event), source(std::move(source), event.getSdEvent(), true)
 {
diff --git a/src/sdeventplus/source/base.hpp b/src/sdeventplus/source/base.hpp
index 2e4f48a..0807fb1 100644
--- a/src/sdeventplus/source/base.hpp
+++ b/src/sdeventplus/source/base.hpp
@@ -123,6 +123,22 @@
      */
     void set_enabled(Enabled enabled) const;
 
+    /** @brief Determines the floating nature of the source
+     *
+     *  @throws SdEventError for underlying sd_event errors
+     *  @return The enabled status of the source
+     */
+    bool get_floating() const;
+
+    /** @brief Sets the floating nature of the source
+     *         If set to true, the source will continue to run after the
+     *         destruction of this handle.
+     *
+     *  @param[in] b - Whether or not the source should float
+     *  @throws SdEventError for underlying sd_event errors
+     */
+    void set_floating(bool b) const;
+
   protected:
     Event event;
 
diff --git a/test/source/base.cpp b/test/source/base.cpp
index 43e70ff..1b2ed1e 100644
--- a/test/source/base.cpp
+++ b/test/source/base.cpp
@@ -426,6 +426,37 @@
     EXPECT_THROW(base->set_enabled(Enabled::OneShot), SdEventError);
 }
 
+TEST_F(BaseMethodTest, GetFloatingSuccess)
+{
+    EXPECT_CALL(mock, sd_event_source_get_floating(expected_source))
+        .WillOnce(Return(2));
+    EXPECT_TRUE(base->get_floating());
+    EXPECT_CALL(mock, sd_event_source_get_floating(expected_source))
+        .WillOnce(Return(0));
+    EXPECT_FALSE(base->get_floating());
+}
+
+TEST_F(BaseMethodTest, GetFloatingError)
+{
+    EXPECT_CALL(mock, sd_event_source_get_floating(expected_source))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->get_floating(), SdEventError);
+}
+
+TEST_F(BaseMethodTest, SetFloatingSuccess)
+{
+    EXPECT_CALL(mock, sd_event_source_set_floating(expected_source, 1))
+        .WillOnce(Return(0));
+    base->set_floating(true);
+}
+
+TEST_F(BaseMethodTest, SetFloatingError)
+{
+    EXPECT_CALL(mock, sd_event_source_set_floating(expected_source, 1))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->set_floating(true), SdEventError);
+}
+
 } // namespace
 } // namespace source
 } // namespace sdeventplus