commit:     a2036911b69c3e05d1cc5f5bd7c90784b9a72fc3
Author:     Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Tue Nov 18 18:45:05 2025 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Tue Nov 18 18:45:05 2025 +0000
URL:        https://gitweb.gentoo.org/proj/steve.git/commit/?id=a2036911

Support polling

Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>

 steve.cxx | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/steve.cxx b/steve.cxx
index 81e88f4..713137f 100644
--- a/steve.cxx
+++ b/steve.cxx
@@ -17,6 +17,7 @@
 #include <deque>
 #include <unordered_map>
 
+#include <sys/poll.h>
 #include <unistd.h>
 
 #include <cuse_lowlevel.h>
@@ -39,6 +40,21 @@ struct steve_read_waiter {
        uint64_t pid;
 };
 
+struct steve_poll_waiter {
+       fuse_pollhandle *poll_handle;
+       uint64_t pid;
+
+       steve_poll_waiter(fuse_pollhandle *new_poll_handle, uint64_t new_pid)
+               : poll_handle(new_poll_handle), pid(new_pid) {}
+
+       steve_poll_waiter(const steve_poll_waiter &) = delete;
+       steve_poll_waiter& operator=(const steve_poll_waiter &) = delete;
+
+       ~steve_poll_waiter() {
+               fuse_pollhandle_destroy(poll_handle);
+       }
+};
+
 struct steve_process {
        unsigned int tokens_held{0};
 };
@@ -48,6 +64,7 @@ struct steve_state {
        unsigned int jobs;
        unsigned int tokens;
        std::deque<steve_read_waiter> read_waiters;
+       std::deque<steve_poll_waiter> poll_waiters;
        std::unordered_map<uint64_t, steve_process> processes;
 };
 
@@ -103,6 +120,16 @@ static void steve_wake_waiters(steve_state *state)
                fuse_reply_buf(read_waiter->req, "+", 1);
                state->read_waiters.pop_front();
        }
+
+       if (state->tokens > 0) {
+               for (auto &poll_waiter : state->poll_waiters) {
+                       if (state->verbose)
+                               printf("Notifying PID %ld about POLLIN, %d 
tokens left, %d tokens held by process\n",
+                                               poll_waiter.pid, state->tokens, 
state->processes[poll_waiter.pid].tokens_held);
+                       fuse_lowlevel_notify_poll(poll_waiter.poll_handle);
+               }
+               state->poll_waiters.clear();
+       }
 }
 
 static void steve_check_processes(steve_state *state)
@@ -248,6 +275,28 @@ static void steve_write(
        steve_wake_waiters(state);
 }
 
+static void steve_poll(
+       fuse_req_t req, struct fuse_file_info *fi, struct fuse_pollhandle *ph)
+{
+       steve_state *state = static_cast<steve_state *>(fuse_req_userdata(req));
+       int events = fi->poll_events & (POLLIN | POLLOUT);
+
+       if (state->verbose)
+               printf("PID %ld requested poll, %d tokens available, %d tokens 
held by process\n",
+                               fi->fh, state->tokens, 
state->processes[fi->fh].tokens_held);
+
+       /* check if we have tokens to reclaim */
+       if (state->tokens == 0)
+               steve_check_processes(state);
+       /* POLLOUT is always possible, POLLIN only if we have any tokens */
+       if (state->tokens == 0) {
+               state->poll_waiters.emplace_back(ph, fi->fh);
+               events &= ~POLLIN;
+       }
+
+       fuse_reply_poll(req, events);
+}
+
 static const struct cuse_lowlevel_ops steve_ops = {
        .init = steve_init,
        .destroy = steve_destroy,
@@ -255,6 +304,7 @@ static const struct cuse_lowlevel_ops steve_ops = {
        .read = steve_read,
        .write = steve_write,
        .release = steve_release,
+       .poll = steve_poll,
 };
 
 int main(int argc, char **argv)

Reply via email to