xref: /openbmc/sdbusplus/include/sdbusplus/asio/sd_event.hpp (revision 06f265f6f18e22b1fb68761edb50ecd6722c2a47)
17f664254SPatrick Williams /*
27f664254SPatrick Williams // Copyright (c) 2018 Intel Corporation
37f664254SPatrick Williams //
47f664254SPatrick Williams // Licensed under the Apache License, Version 2.0 (the "License");
57f664254SPatrick Williams // you may not use this file except in compliance with the License.
67f664254SPatrick Williams // You may obtain a copy of the License at
77f664254SPatrick Williams //
87f664254SPatrick Williams //      http://www.apache.org/licenses/LICENSE-2.0
97f664254SPatrick Williams //
107f664254SPatrick Williams // Unless required by applicable law or agreed to in writing, software
117f664254SPatrick Williams // distributed under the License is distributed on an "AS IS" BASIS,
127f664254SPatrick Williams // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137f664254SPatrick Williams // See the License for the specific language governing permissions and
147f664254SPatrick Williams // limitations under the License.
157f664254SPatrick Williams */
167f664254SPatrick Williams #pragma once
177f664254SPatrick Williams 
187f664254SPatrick Williams #include <systemd/sd-event.h>
197f664254SPatrick Williams 
2038ab5ecfSEd Tanous #include <boost/asio/io_context.hpp>
2138ab5ecfSEd Tanous #include <boost/asio/posix/stream_descriptor.hpp>
22*93f5e283SPeter Foley #include <boost/asio/post.hpp>
2338ab5ecfSEd Tanous #include <boost/system/error_code.hpp>
247f664254SPatrick Williams 
257f664254SPatrick Williams namespace sdbusplus
267f664254SPatrick Williams {
277f664254SPatrick Williams 
287f664254SPatrick Williams namespace asio
297f664254SPatrick Williams {
307f664254SPatrick Williams /* A simple class to integrate the sd_event_loop into the boost::asio io_context
317f664254SPatrick Williams  * in case a boost::asio user needs sd_events
327f664254SPatrick Williams  */
337f664254SPatrick Williams class sd_event_wrapper
347f664254SPatrick Williams {
357f664254SPatrick Williams   public:
sd_event_wrapper(boost::asio::io_context & io)367f664254SPatrick Williams     sd_event_wrapper(boost::asio::io_context& io) :
377f664254SPatrick Williams         evt(nullptr), descriptor(io), io(io)
387f664254SPatrick Williams     {
397f664254SPatrick Williams         sd_event_default(&evt);
407f664254SPatrick Williams         if (evt)
417f664254SPatrick Williams         {
427f664254SPatrick Williams             descriptor.assign(sd_event_get_fd(evt));
437f664254SPatrick Williams             async_run();
447f664254SPatrick Williams         }
457f664254SPatrick Williams     }
sd_event_wrapper(sd_event * evt,boost::asio::io_context & io)467f664254SPatrick Williams     sd_event_wrapper(sd_event* evt, boost::asio::io_context& io) :
477f664254SPatrick Williams         evt(evt), descriptor(io), io(io)
487f664254SPatrick Williams     {
497f664254SPatrick Williams         if (evt)
507f664254SPatrick Williams         {
517f664254SPatrick Williams             sd_event_ref(evt);
527f664254SPatrick Williams             descriptor.assign(sd_event_get_fd(evt));
537f664254SPatrick Williams             async_run();
547f664254SPatrick Williams         }
557f664254SPatrick Williams     }
~sd_event_wrapper()567f664254SPatrick Williams     ~sd_event_wrapper()
577f664254SPatrick Williams     {
587f664254SPatrick Williams         // sd_event really wants to close the descriptor on its own
597f664254SPatrick Williams         // so this class must merely release it
607f664254SPatrick Williams         descriptor.release();
617f664254SPatrick Williams         sd_event_unref(evt);
627f664254SPatrick Williams     }
637f664254SPatrick Williams     // process one event step in the queue
647f664254SPatrick Williams     // return true if the queue is still alive
run()657f664254SPatrick Williams     void run()
667f664254SPatrick Williams     {
677f664254SPatrick Williams         int ret;
687f664254SPatrick Williams         int state = sd_event_get_state(evt);
697f664254SPatrick Williams         switch (state)
707f664254SPatrick Williams         {
717f664254SPatrick Williams             case SD_EVENT_INITIAL:
727f664254SPatrick Williams                 ret = sd_event_prepare(evt);
737f664254SPatrick Williams                 if (ret > 0)
747f664254SPatrick Williams                 {
757f664254SPatrick Williams                     async_run();
767f664254SPatrick Williams                 }
777f664254SPatrick Williams                 else if (ret == 0)
787f664254SPatrick Williams                 {
797f664254SPatrick Williams                     async_wait();
807f664254SPatrick Williams                 }
817f664254SPatrick Williams                 break;
827f664254SPatrick Williams             case SD_EVENT_ARMED:
837f664254SPatrick Williams                 ret = sd_event_wait(evt, 0);
847f664254SPatrick Williams                 if (ret >= 0)
857f664254SPatrick Williams                 {
867f664254SPatrick Williams                     async_run();
877f664254SPatrick Williams                 }
887f664254SPatrick Williams                 break;
897f664254SPatrick Williams             case SD_EVENT_PENDING:
907f664254SPatrick Williams                 ret = sd_event_dispatch(evt);
917f664254SPatrick Williams                 if (ret > 0)
927f664254SPatrick Williams                 {
937f664254SPatrick Williams                     async_run();
947f664254SPatrick Williams                 }
957f664254SPatrick Williams                 break;
967f664254SPatrick Williams             case SD_EVENT_FINISHED:
977f664254SPatrick Williams                 break;
987f664254SPatrick Williams             default:
997f664254SPatrick Williams                 // throw something?
1007f664254SPatrick Williams                 // doing nothing will break out of the async loop
1017f664254SPatrick Williams                 break;
1027f664254SPatrick Williams         }
1037f664254SPatrick Williams     }
get() const1047f664254SPatrick Williams     sd_event* get() const
1057f664254SPatrick Williams     {
1067f664254SPatrick Williams         return evt;
1077f664254SPatrick Williams     }
1087f664254SPatrick Williams 
1097f664254SPatrick Williams   private:
async_run()1107f664254SPatrick Williams     void async_run()
1117f664254SPatrick Williams     {
112936cb89eSEd Tanous         boost::asio::post(io, [this]() { run(); });
1137f664254SPatrick Williams     }
async_wait()1147f664254SPatrick Williams     void async_wait()
1157f664254SPatrick Williams     {
1167f664254SPatrick Williams         descriptor.async_wait(boost::asio::posix::stream_descriptor::wait_read,
1177f664254SPatrick Williams                               [this](const boost::system::error_code& error) {
1187f664254SPatrick Williams                                   if (!error)
1197f664254SPatrick Williams                                   {
1207f664254SPatrick Williams                                       run();
1217f664254SPatrick Williams                                   }
1227f664254SPatrick Williams                               });
1237f664254SPatrick Williams     }
1247f664254SPatrick Williams     sd_event* evt;
1257f664254SPatrick Williams     boost::asio::posix::stream_descriptor descriptor;
1267f664254SPatrick Williams     boost::asio::io_context& io;
1277f664254SPatrick Williams };
1287f664254SPatrick Williams 
1297f664254SPatrick Williams } // namespace asio
1307f664254SPatrick Williams 
1317f664254SPatrick Williams } // namespace sdbusplus
132