1 /* 2 * Generic object event notification support. 3 * 4 * Copyright (C) 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #pragma once 23 24 #include <condition_variable> 25 #include <list> 26 #include <map> 27 #include <mutex> 28 29 #include <fsclient/file.h> 30 #include <systypes/base.h> 31 32 33 34 /* Object-specific notification details. */ 35 36 class ObjectNotificationState 37 { 38 public: 39 /* Synchronisation primitives for state access and notification. */ 40 41 std::mutex lock; 42 std::condition_variable condition; 43 44 /* Pending notifications for monitored objects. */ 45 46 notify_flags_t pending = 0; 47 48 /* Endpoints associated with monitored objects. */ 49 50 l4_cap_idx_t endpoint = L4_INVALID_CAP; 51 52 bool is_null() { return l4_is_invalid_cap(endpoint); } 53 }; 54 55 56 57 /* Collection types. */ 58 59 typedef std::map<notifiable_t *, ObjectNotificationState> ObjectNotificationStates; 60 typedef std::map<notifiable_t *, std::mutex> ObjectStateLocks; 61 62 63 64 /* An object for monitoring object event notifications. */ 65 66 class ObjectNotifier 67 { 68 protected: 69 /* General state access locking. */ 70 71 std::mutex _state_lock; 72 73 /* Object-specific state locking. */ 74 75 ObjectStateLocks _object_locks; 76 77 /* Notification state. */ 78 79 ObjectNotificationStates _state; 80 81 /* Notifier thread details. */ 82 83 l4_cap_idx_t _thread = L4_INVALID_CAP; 84 bool _started = false; 85 86 /* Convenience method to access object state. */ 87 88 virtual ObjectNotificationState &object_state(notifiable_t *object, bool create); 89 90 /* Helper methods. */ 91 92 virtual void _notify(notifiable_t *object, notify_flags_t flags) = 0; 93 94 virtual bool _transfer(ObjectNotificationState &state, notifiable_t *object); 95 96 public: 97 virtual ~ObjectNotifier(); 98 99 /* Local operations. */ 100 101 virtual long start(); 102 103 virtual long subscribe(notifiable_t *object, notify_flags_t flags); 104 105 virtual long unsubscribe(notifiable_t *object); 106 107 /* Event handling support. */ 108 109 virtual void mainloop(); 110 }; 111 112 113 114 /* An object monitoring notifications for a collection of different objects. */ 115 116 class GeneralObjectNotifier : public ObjectNotifier 117 { 118 protected: 119 /* Locking to protect pending notification members and to coordinate access 120 to notifications. */ 121 122 std::mutex _general_lock; 123 124 /* General lock synchronisation. */ 125 126 std::condition_variable _general_condition; 127 128 /* Objects affected by notifications. */ 129 130 std::list<notifiable_t *> _affected; 131 132 /* Helper methods. */ 133 134 virtual void _notify(notifiable_t *object, notify_flags_t flags); 135 136 virtual bool _retrieve(notifiable_t **object); 137 138 virtual bool _retrieve_for_object(notifiable_t *object); 139 140 public: 141 virtual long wait(notifiable_t **object); 142 }; 143 144 145 146 /* An object monitoring notifications for specific objects. */ 147 148 class SpecificObjectNotifier : public ObjectNotifier 149 { 150 protected: 151 /* Helper methods. */ 152 153 virtual void _notify(notifiable_t *object, notify_flags_t flags); 154 155 public: 156 virtual long wait_object(notifiable_t *object); 157 }; 158 159 160 161 /* Helper functions. */ 162 163 SpecificObjectNotifier *notifier_get_task_notifier(); 164 165 GeneralObjectNotifier *notifier_get_local_notifier(); 166 167 // vim: tabstop=4 expandtab shiftwidth=4