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