1.1 --- a/libnotifier/include/notifier/notifier.h Mon Apr 03 16:41:11 2023 +0200
1.2 +++ b/libnotifier/include/notifier/notifier.h Mon Apr 03 19:35:35 2023 +0200
1.3 @@ -65,6 +65,8 @@
1.4
1.5 virtual long unsubscribe(notifiable_t *object);
1.6
1.7 + virtual void update(notifiable_t *object);
1.8 +
1.9 virtual long wait(notifiable_t **object);
1.10
1.11 virtual long wait_object(notifiable_t *object);
1.12 @@ -99,10 +101,6 @@
1.13 ObjectNotifiers _notifiers;
1.14 notifiable_t *_object;
1.15
1.16 - /* Pending notification status. */
1.17 -
1.18 - bool _pending = false;
1.19 -
1.20 /* Utility methods. */
1.21
1.22 virtual void _notify();
1.23 @@ -139,8 +137,6 @@
1.24 virtual long add(ObjectNotifier *notifier, notify_flags_t flags);
1.25
1.26 virtual long remove(ObjectNotifier *notifier);
1.27 -
1.28 - virtual long wait();
1.29 };
1.30
1.31
2.1 --- a/libnotifier/lib/src/notifier.cc Mon Apr 03 16:41:11 2023 +0200
2.2 +++ b/libnotifier/lib/src/notifier.cc Mon Apr 03 19:35:35 2023 +0200
2.3 @@ -98,6 +98,7 @@
2.4 std::lock_guard<std::mutex> guard(_monitored_lock);
2.5
2.6 _monitored.erase(object);
2.7 + object->handler = NULL;
2.8 }
2.9
2.10 /* Subscribe to notification events on an object. */
2.11 @@ -148,6 +149,7 @@
2.12 NotifierResource *resource = reinterpret_cast<NotifierResource *>(object->handler);
2.13
2.14 _monitored.erase(object);
2.15 + object->handler = NULL;
2.16 return resource->remove(this);
2.17 }
2.18
2.19 @@ -157,7 +159,7 @@
2.20 {
2.21 /* Enter critical section to access the queue. */
2.22
2.23 - std::lock_guard<std::mutex> guard(_affected_lock);
2.24 + std::unique_lock<std::mutex> guard(_affected_lock);
2.25
2.26 /* Ensure that a queue entry exists for the object. */
2.27
2.28 @@ -169,9 +171,19 @@
2.29 _affected.insert(object);
2.30 }
2.31
2.32 - /* Notify any waiting caller that at least one notification is available. */
2.33 + /* Notify all waiting callers that at least one notification is available. */
2.34 +
2.35 + _condition.notify_all();
2.36 +}
2.37 +
2.38 +/* Update the notifiable object when being notified. */
2.39
2.40 - _condition.notify_one();
2.41 +void ObjectNotifier::update(notifiable_t *object)
2.42 +{
2.43 + object->notifications = object->pending_notifications;
2.44 + object->values = object->pending_values;
2.45 +
2.46 + object->pending_notifications = 0;
2.47 }
2.48
2.49 /* Wait for notification events on objects, returning each object that has a
2.50 @@ -200,6 +212,9 @@
2.51 _condition.wait(guard);
2.52 }
2.53
2.54 + /* Synchronise the notification flags and values. */
2.55 +
2.56 + update(*object);
2.57 return L4_EOK;
2.58 }
2.59
2.60 @@ -207,10 +222,43 @@
2.61
2.62 long ObjectNotifier::wait_object(notifiable_t *object)
2.63 {
2.64 - if (object->handler == NULL)
2.65 - return -L4_EINVAL;
2.66 + /* Enter critical section to access the queue. */
2.67 +
2.68 + std::unique_lock<std::mutex> guard(_affected_lock);
2.69 +
2.70 + while (1)
2.71 + {
2.72 + /* With pending notifications, find any for the specified object. */
2.73 +
2.74 + NotifiableObjects::iterator it = _affected.find(object);
2.75 +
2.76 + if (it != _affected.end())
2.77 + {
2.78 + /* Remove the object from the queue. */
2.79 +
2.80 + NotifiableObjectQueue::iterator itq;
2.81
2.82 - reinterpret_cast<NotifierResource *>(object->handler)->wait();
2.83 + for (itq = _queued.begin(); itq != _queued.end(); itq++)
2.84 + {
2.85 + if (*itq == object)
2.86 + {
2.87 + _queued.erase(itq);
2.88 + break;
2.89 + }
2.90 + }
2.91 +
2.92 + _affected.erase(it);
2.93 + break;
2.94 + }
2.95 +
2.96 + /* Otherwise, wait for notifications. */
2.97 +
2.98 + _condition.wait(guard);
2.99 + }
2.100 +
2.101 + /* Synchronise the notification flags and values. */
2.102 +
2.103 + update(object);
2.104 return L4_EOK;
2.105 }
2.106
2.107 @@ -227,7 +275,6 @@
2.108 void NotifierResource::close()
2.109 {
2.110 _release();
2.111 - _object->handler = NULL;
2.112 }
2.113
2.114 /* Object-specific resource methods. */
2.115 @@ -284,8 +331,8 @@
2.116 {
2.117 /* Update the notifiable object. */
2.118
2.119 - _object->notifications |= flags;
2.120 - _object->values = values;
2.121 + _object->pending_notifications |= flags;
2.122 + _object->pending_values = values;
2.123
2.124 _notify();
2.125 return L4_EOK;
2.126 @@ -297,14 +344,6 @@
2.127
2.128 std::lock_guard<std::mutex> guard(_lock);
2.129
2.130 - /* Record a pending notification which persists if nothing is waiting. */
2.131 -
2.132 - _pending = true;
2.133 -
2.134 - /* Notify any party waiting specifically on this object. */
2.135 -
2.136 - _condition.notify_one();
2.137 -
2.138 /* Register the notification with all notifier objects. */
2.139
2.140 ObjectNotifiers::iterator it;
2.141 @@ -325,22 +364,5 @@
2.142 (*it)->release(_object);
2.143 }
2.144
2.145 -/* Wait for notification events on a specific object. */
2.146 -
2.147 -long NotifierResource::wait()
2.148 -{
2.149 - /* Enter critical section for the resource. */
2.150 -
2.151 - std::unique_lock<std::mutex> guard(_lock);
2.152 -
2.153 - /* Wait for the notification condition. */
2.154 -
2.155 - if (!_pending)
2.156 - _condition.wait(guard);
2.157 -
2.158 - _pending = false;
2.159 - return L4_EOK;
2.160 -}
2.161 -
2.162 /* vim: tabstop=2 expandtab shiftwidth=2
2.163 */
3.1 --- a/libsystypes/include/systypes/base.h Mon Apr 03 16:41:11 2023 +0200
3.2 +++ b/libsystypes/include/systypes/base.h Mon Apr 03 19:35:35 2023 +0200
3.3 @@ -76,7 +76,9 @@
3.4 {
3.5 notifiable_base_t *base; /* access to the specific object */
3.6 notify_flags_t notifications; /* essential notifications */
3.7 + notify_flags_t pending_notifications;
3.8 notify_values_t values; /* signal-specific values */
3.9 + notify_values_t pending_values;
3.10 void *handler; /* associated notification handler */
3.11
3.12 } notifiable_t;