forked from Kistler-Group/sdbus-cpp
Added ability to integrate with foreign event loops
This commit is contained in:
committed by
Stanislav Angelovič
parent
e30ce194ab
commit
0440dcb15b
@ -46,6 +46,13 @@ namespace sdbus {
|
|||||||
class IConnection
|
class IConnection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct PollData
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
short int events;
|
||||||
|
uint64_t timeout_usec;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~IConnection() = default;
|
virtual ~IConnection() = default;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -103,6 +110,41 @@ namespace sdbus {
|
|||||||
* @throws sdbus::Error in case of failure
|
* @throws sdbus::Error in case of failure
|
||||||
*/
|
*/
|
||||||
virtual void addObjectManager(const std::string& objectPath) = 0;
|
virtual void addObjectManager(const std::string& objectPath) = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Returns parameters you can pass to poll
|
||||||
|
*
|
||||||
|
* To integrate sdbus with your app's own custom event handling system
|
||||||
|
* (without the requirement of an extra thread), you can use this
|
||||||
|
* method to query which file descriptors, poll events and timeouts you
|
||||||
|
* should add to your app's poll call in your main event loop. If these
|
||||||
|
* file descriptors signal, then you should call processPendingRequest
|
||||||
|
* to process the event. This means that all of sdbus's callbacks will
|
||||||
|
* arrive on your app's main event thread (opposed to on a thread created
|
||||||
|
* by sdbus-c++). If you are unsure what this all means then use
|
||||||
|
* enterProcessingLoop() or enterProcessingLoopAsync() instead.
|
||||||
|
*
|
||||||
|
* To integrate sdbus-c++ into a gtk app, pass the file descriptor returned
|
||||||
|
* by this method to g_main_context_add_poll.
|
||||||
|
*
|
||||||
|
* @throws sdbus::Error in case of failure
|
||||||
|
*/
|
||||||
|
virtual PollData getProcessLoopPollData() = 0;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Process a pending request
|
||||||
|
*
|
||||||
|
* Processes a single dbus event. All of sdbus-c++'s callbacks will be called
|
||||||
|
* from within this method. This method should ONLY be used in conjuction
|
||||||
|
* with getProcessLoopPollData(). enterProcessingLoop() and
|
||||||
|
* enterProcessingLoopAsync() will call this method for you, so there is no
|
||||||
|
* need to call it when using these. If you are unsure what this all means then
|
||||||
|
* don't use this method.
|
||||||
|
*
|
||||||
|
* @returns true if an event was processed
|
||||||
|
* @throws sdbus::Error in case of failure
|
||||||
|
*/
|
||||||
|
virtual bool processPendingRequest() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -108,6 +108,20 @@ void Connection::leaveProcessingLoop()
|
|||||||
joinWithProcessingLoop();
|
joinWithProcessingLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sdbus::IConnection::PollData Connection::getProcessLoopPollData()
|
||||||
|
{
|
||||||
|
sdbus::IConnection::PollData pollData;
|
||||||
|
ISdBus::PollData sdbusPollData;
|
||||||
|
auto r = iface_->sd_bus_get_poll_data(bus_.get(), &sdbusPollData);
|
||||||
|
SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus poll data", -r);
|
||||||
|
|
||||||
|
pollData.fd = sdbusPollData.fd;
|
||||||
|
pollData.events = sdbusPollData.events;
|
||||||
|
pollData.timeout_usec = sdbusPollData.timeout_usec;
|
||||||
|
|
||||||
|
return pollData;
|
||||||
|
}
|
||||||
|
|
||||||
const ISdBus& Connection::getSdBusInterface() const
|
const ISdBus& Connection::getSdBusInterface() const
|
||||||
{
|
{
|
||||||
return *iface_.get();
|
return *iface_.get();
|
||||||
@ -345,15 +359,12 @@ bool Connection::waitForNextRequest()
|
|||||||
assert(bus != nullptr);
|
assert(bus != nullptr);
|
||||||
assert(loopExitFd_ != 0);
|
assert(loopExitFd_ != 0);
|
||||||
|
|
||||||
ISdBus::PollData sdbusPollData;
|
auto sdbusPollData = getProcessLoopPollData();
|
||||||
auto r = iface_->sd_bus_get_poll_data(bus, &sdbusPollData);
|
|
||||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus poll data", -r);
|
|
||||||
|
|
||||||
struct pollfd fds[] = {{sdbusPollData.fd, sdbusPollData.events, 0}, {loopExitFd_, POLLIN, 0}};
|
struct pollfd fds[] = {{sdbusPollData.fd, sdbusPollData.events, 0}, {loopExitFd_, POLLIN, 0}};
|
||||||
auto fdsCount = sizeof(fds)/sizeof(fds[0]);
|
auto fdsCount = sizeof(fds)/sizeof(fds[0]);
|
||||||
|
|
||||||
auto timeout = sdbusPollData.timeout_usec == (uint64_t) -1 ? (uint64_t)-1 : (sdbusPollData.timeout_usec+999)/1000;
|
auto timeout = sdbusPollData.timeout_usec == (uint64_t) -1 ? (uint64_t)-1 : (sdbusPollData.timeout_usec+999)/1000;
|
||||||
r = poll(fds, fdsCount, timeout);
|
auto r = poll(fds, fdsCount, timeout);
|
||||||
|
|
||||||
if (r < 0 && errno == EINTR)
|
if (r < 0 && errno == EINTR)
|
||||||
return true; // Try again
|
return true; // Try again
|
||||||
|
@ -57,6 +57,8 @@ namespace sdbus { namespace internal {
|
|||||||
void enterProcessingLoop() override;
|
void enterProcessingLoop() override;
|
||||||
void enterProcessingLoopAsync() override;
|
void enterProcessingLoopAsync() override;
|
||||||
void leaveProcessingLoop() override;
|
void leaveProcessingLoop() override;
|
||||||
|
bool processPendingRequest() override;
|
||||||
|
sdbus::IConnection::PollData getProcessLoopPollData() override;
|
||||||
|
|
||||||
void addObjectManager(const std::string& objectPath) override;
|
void addObjectManager(const std::string& objectPath) override;
|
||||||
SlotPtr addObjectManager(const std::string& objectPath, void* /*dummy*/) override;
|
SlotPtr addObjectManager(const std::string& objectPath, void* /*dummy*/) override;
|
||||||
@ -99,7 +101,6 @@ namespace sdbus { namespace internal {
|
|||||||
void finishHandshake(sd_bus* bus);
|
void finishHandshake(sd_bus* bus);
|
||||||
static int createProcessingLoopExitDescriptor();
|
static int createProcessingLoopExitDescriptor();
|
||||||
static void closeProcessingLoopExitDescriptor(int fd);
|
static void closeProcessingLoopExitDescriptor(int fd);
|
||||||
bool processPendingRequest();
|
|
||||||
bool waitForNextRequest();
|
bool waitForNextRequest();
|
||||||
static std::string composeSignalMatchFilter( const std::string& objectPath
|
static std::string composeSignalMatchFilter( const std::string& objectPath
|
||||||
, const std::string& interfaceName
|
, const std::string& interfaceName
|
||||||
|
Reference in New Issue
Block a user