# HG changeset patch # User Paul Boddie # Date 1626128771 -7200 # Node ID ac4025f8f4e03e5a49556f3a0fe36eed270c2508 # Parent 929003b4e133c8353335f2be79b3a0c308d3f8ab Tidied up the notification management, introducing C++ library data structures. diff -r 929003b4e133 -r ac4025f8f4e0 libfsserver/include/fsserver/notification.h --- a/libfsserver/include/fsserver/notification.h Mon Jul 12 23:18:16 2021 +0200 +++ b/libfsserver/include/fsserver/notification.h Tue Jul 13 00:26:11 2021 +0200 @@ -22,11 +22,29 @@ #pragma once #include +#include #include +/* Collection data types. */ + +typedef std::set NotifierSet; + +/* Notification endpoint details. */ + +class NotificationEndpoint +{ +public: + NotifierSet notifiers; + notify_flags_t flags, deferred; +}; + +typedef std::vector NotificationEndpointList; + + + /* Notification support, allowing pipe or file users to receive events due to activity on those objects. */ @@ -35,20 +53,16 @@ protected: /* Endpoint count. */ - unsigned int _max_endpoints; + unsigned int _min_endpoints; - /* Notification endpoints and flags, set up at initialisation for the - appropriate number of endpoints. */ + /* Notification endpoint details. */ - std::set *_notifiers; - notify_flags_t *_flags, *_deferred; + NotificationEndpointList _endpoints; virtual void release_notifiers(); public: - explicit NotificationSupport(unsigned int endpoints); - - virtual ~NotificationSupport(); + explicit NotificationSupport(unsigned int endpoints=0); virtual void notify(unsigned int endpoint, notify_flags_t flags); diff -r 929003b4e133 -r ac4025f8f4e0 libfsserver/include/fsserver/pipe_paging.h --- a/libfsserver/include/fsserver/pipe_paging.h Mon Jul 12 23:18:16 2021 +0200 +++ b/libfsserver/include/fsserver/pipe_paging.h Tue Jul 13 00:26:11 2021 +0200 @@ -55,7 +55,7 @@ /* Endpoint status. */ - unsigned int _endpoints = 2; + unsigned int _active_endpoints = 2; /* Common functionality. */ diff -r 929003b4e133 -r ac4025f8f4e0 libfsserver/lib/generic/notification.cc --- a/libfsserver/lib/generic/notification.cc Mon Jul 12 23:18:16 2021 +0200 +++ b/libfsserver/lib/generic/notification.cc Tue Jul 13 00:26:11 2021 +0200 @@ -29,39 +29,29 @@ /* Initialise endpoints and flags for notifications. */ NotificationSupport::NotificationSupport(unsigned int endpoints) -: _max_endpoints(endpoints) +: _min_endpoints(endpoints) { - _notifiers = new std::set[endpoints]; - _flags = new notify_flags_t[endpoints]; - _deferred = new notify_flags_t[endpoints]; - - for (unsigned int endpoint = 0; endpoint < _max_endpoints; endpoint++) - { - _flags[endpoint] = 0; - _deferred[endpoint] = 0; - } -} - -NotificationSupport::~NotificationSupport() -{ - delete _notifiers; - delete _flags; - delete _deferred; + _endpoints.resize(_min_endpoints); } /* Subscribe to an endpoint's notifications using a notification endpoint. */ void NotificationSupport::subscribe(unsigned int endpoint, l4_cap_idx_t notifier, notify_flags_t flags) { - _notifiers[endpoint].insert(notifier); - _flags[endpoint] = flags; + if (endpoint >= _endpoints.size()) + _endpoints.resize(endpoint + 1); + + NotificationEndpoint &ep = _endpoints[endpoint]; + + ep.notifiers.insert(notifier); + ep.flags = flags; /* Send deferred conditions held from before subscription occurred. */ - if (_deferred[endpoint]) + if (ep.deferred) { - notify(endpoint, _deferred[endpoint]); - _deferred[endpoint] = 0; + notify(endpoint, ep.deferred); + ep.deferred = 0; } } @@ -69,14 +59,22 @@ void NotificationSupport::unsubscribe(unsigned int endpoint, l4_cap_idx_t notifier) { - std::set::iterator it = _notifiers[endpoint].find(notifier); + if (endpoint >= _endpoints.size()) + return; - if (it != _notifiers[endpoint].end()) + NotificationEndpoint &ep = _endpoints[endpoint]; + NotifierSet::iterator it = ep.notifiers.find(notifier); + + if (it != ep.notifiers.end()) { - _notifiers[endpoint].erase(it); - _flags[endpoint] = 0; - _deferred[endpoint] = 0; + ep.notifiers.erase(it); ipc_cap_free_um(notifier); + + if (ep.notifiers.empty()) + { + ep.flags = 0; + ep.deferred = 0; + } } } @@ -84,32 +82,37 @@ void NotificationSupport::notify(unsigned int endpoint, notify_flags_t flags) { + if (endpoint >= _endpoints.size()) + return; + + NotificationEndpoint &ep = _endpoints[endpoint]; + /* Notify the endpoint or hold any notification for potential future subscription. */ - if (!_notifiers[endpoint].empty()) + if (!ep.notifiers.empty()) { - if (flags & _flags[endpoint]) + if (flags & ep.flags) { - std::set::iterator it; + NotifierSet::iterator it; - for (it = _notifiers[endpoint].begin(); it != _notifiers[endpoint].end(); it++) + for (it = ep.notifiers.begin(); it != ep.notifiers.end(); it++) { client_Notifier notifier(*it); - notifier.notify(flags & _flags[endpoint]); + notifier.notify(flags & ep.flags); } } } else - _deferred[endpoint] = flags; + ep.deferred = flags; } /* Notify the other endpoints. */ void NotificationSupport::notify_others(unsigned int endpoint, notify_flags_t flags) { - for (unsigned int i = 0; i < _max_endpoints; i++) + for (unsigned int i = 0; i < _endpoints.size(); i++) if (i != endpoint) notify(i, flags); } @@ -118,14 +121,17 @@ void NotificationSupport::release_notifiers() { - for (unsigned int endpoint = 0; endpoint < _max_endpoints; endpoint++) + for (unsigned int endpoint = 0; endpoint < _endpoints.size(); endpoint++) { - std::set::iterator it; + NotificationEndpoint &ep = _endpoints[endpoint]; + NotifierSet::iterator it; - for (it = _notifiers[endpoint].begin(); it != _notifiers[endpoint].end(); it++) + for (it = ep.notifiers.begin(); it != ep.notifiers.end(); it++) ipc_cap_free_um(*it); - _notifiers[endpoint].clear(); + ep.notifiers.clear(); + ep.flags = 0; + ep.deferred = 0; } } diff -r 929003b4e133 -r ac4025f8f4e0 libfsserver/lib/pipes/pipe_paging.cc --- a/libfsserver/lib/pipes/pipe_paging.cc Mon Jul 12 23:18:16 2021 +0200 +++ b/libfsserver/lib/pipes/pipe_paging.cc Tue Jul 13 00:26:11 2021 +0200 @@ -47,7 +47,7 @@ int PipePaging::closed() { - return _endpoints < 2; + return _active_endpoints < 2; } void PipePaging::discard_region(unsigned int i) @@ -66,14 +66,14 @@ void PipePaging::detach() { - if (!_endpoints) + if (!_active_endpoints) return; else - _endpoints--; + _active_endpoints--; /* Return if the other endpoint is attached. */ - if (_endpoints) + if (_active_endpoints) return; /* Discard all regions from the pipe. */