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_notifications = 0; 47 notify_values_t pending_values = NOTIFY_VALUES_NULL; 48 49 /* Endpoints associated with monitored objects. */ 50 51 l4_cap_idx_t endpoint = L4_INVALID_CAP; 52 53 bool is_null() { return l4_is_invalid_cap(endpoint); } 54 }; 55 56 57 58 /* Collection types. */ 59 60 typedef std::map<notifiable_t *, ObjectNotificationState> ObjectNotificationStates; 61 typedef std::map<notifiable_t *, std::mutex> ObjectStateLocks; 62 63 64 65 /* An object for monitoring object event notifications. */ 66 67 class ObjectNotifier 68 { 69 protected: 70 /* General state access locking. */ 71 72 std::mutex _state_lock; 73 74 /* Object-specific state locking. */ 75 76 ObjectStateLocks _object_locks; 77 78 /* Notification state. */ 79 80 ObjectNotificationStates _state; 81 82 /* Notifier thread details. */ 83 84 l4_cap_idx_t _thread = L4_INVALID_CAP; 85 bool _started = false; 86 87 /* Convenience method to access object state. */ 88 89 virtual ObjectNotificationState &object_state(notifiable_t *object, bool create); 90 91 /* Helper methods. */ 92 93 virtual void _notify(notifiable_t *object, notify_flags_t flags, 94 notify_values_t values) = 0; 95 96 virtual bool _transfer(ObjectNotificationState &state, notifiable_t *object); 97 98 public: 99 virtual ~ObjectNotifier(); 100 101 /* Local operations. */ 102 103 virtual long start(); 104 105 virtual long subscribe(notifiable_t *object, notify_flags_t flags); 106 107 virtual long unsubscribe(notifiable_t *object); 108 109 /* Event handling support. */ 110 111 virtual void mainloop(); 112 }; 113 114 115 116 /* An object monitoring notifications for a collection of different objects. */ 117 118 class GeneralObjectNotifier : public ObjectNotifier 119 { 120 protected: 121 /* Locking to protect pending notification members and to coordinate access 122 to notifications. */ 123 124 std::mutex _general_lock; 125 126 /* General lock synchronisation. */ 127 128 std::condition_variable _general_condition; 129 130 /* Objects affected by notifications. */ 131 132 std::list<notifiable_t *> _affected; 133 134 /* Helper methods. */ 135 136 virtual void _notify(notifiable_t *object, notify_flags_t flags, 137 notify_values_t values); 138 139 virtual bool _retrieve(notifiable_t **object); 140 141 virtual bool _retrieve_for_object(notifiable_t *object); 142 143 public: 144 virtual long wait(notifiable_t **object); 145 }; 146 147 148 149 /* An object monitoring notifications for specific objects. */ 150 151 class SpecificObjectNotifier : public ObjectNotifier 152 { 153 protected: 154 /* Helper methods. */ 155 156 virtual void _notify(notifiable_t *object, notify_flags_t flags, 157 notify_values_t values); 158 159 public: 160 virtual long wait_object(notifiable_t *object); 161 }; 162 163 164 165 /* Helper functions. */ 166 167 SpecificObjectNotifier *notifier_get_task_notifier(); 168 169 GeneralObjectNotifier *notifier_get_local_notifier(); 170 171 // vim: tabstop=4 expandtab shiftwidth=4