1.1 --- a/libnotifier/lib/src/notifier.cc Mon Apr 03 16:41:11 2023 +0200
1.2 +++ b/libnotifier/lib/src/notifier.cc Mon Apr 03 19:35:35 2023 +0200
1.3 @@ -98,6 +98,7 @@
1.4 std::lock_guard<std::mutex> guard(_monitored_lock);
1.5
1.6 _monitored.erase(object);
1.7 + object->handler = NULL;
1.8 }
1.9
1.10 /* Subscribe to notification events on an object. */
1.11 @@ -148,6 +149,7 @@
1.12 NotifierResource *resource = reinterpret_cast<NotifierResource *>(object->handler);
1.13
1.14 _monitored.erase(object);
1.15 + object->handler = NULL;
1.16 return resource->remove(this);
1.17 }
1.18
1.19 @@ -157,7 +159,7 @@
1.20 {
1.21 /* Enter critical section to access the queue. */
1.22
1.23 - std::lock_guard<std::mutex> guard(_affected_lock);
1.24 + std::unique_lock<std::mutex> guard(_affected_lock);
1.25
1.26 /* Ensure that a queue entry exists for the object. */
1.27
1.28 @@ -169,9 +171,19 @@
1.29 _affected.insert(object);
1.30 }
1.31
1.32 - /* Notify any waiting caller that at least one notification is available. */
1.33 + /* Notify all waiting callers that at least one notification is available. */
1.34 +
1.35 + _condition.notify_all();
1.36 +}
1.37 +
1.38 +/* Update the notifiable object when being notified. */
1.39
1.40 - _condition.notify_one();
1.41 +void ObjectNotifier::update(notifiable_t *object)
1.42 +{
1.43 + object->notifications = object->pending_notifications;
1.44 + object->values = object->pending_values;
1.45 +
1.46 + object->pending_notifications = 0;
1.47 }
1.48
1.49 /* Wait for notification events on objects, returning each object that has a
1.50 @@ -200,6 +212,9 @@
1.51 _condition.wait(guard);
1.52 }
1.53
1.54 + /* Synchronise the notification flags and values. */
1.55 +
1.56 + update(*object);
1.57 return L4_EOK;
1.58 }
1.59
1.60 @@ -207,10 +222,43 @@
1.61
1.62 long ObjectNotifier::wait_object(notifiable_t *object)
1.63 {
1.64 - if (object->handler == NULL)
1.65 - return -L4_EINVAL;
1.66 + /* Enter critical section to access the queue. */
1.67 +
1.68 + std::unique_lock<std::mutex> guard(_affected_lock);
1.69 +
1.70 + while (1)
1.71 + {
1.72 + /* With pending notifications, find any for the specified object. */
1.73 +
1.74 + NotifiableObjects::iterator it = _affected.find(object);
1.75 +
1.76 + if (it != _affected.end())
1.77 + {
1.78 + /* Remove the object from the queue. */
1.79 +
1.80 + NotifiableObjectQueue::iterator itq;
1.81
1.82 - reinterpret_cast<NotifierResource *>(object->handler)->wait();
1.83 + for (itq = _queued.begin(); itq != _queued.end(); itq++)
1.84 + {
1.85 + if (*itq == object)
1.86 + {
1.87 + _queued.erase(itq);
1.88 + break;
1.89 + }
1.90 + }
1.91 +
1.92 + _affected.erase(it);
1.93 + break;
1.94 + }
1.95 +
1.96 + /* Otherwise, wait for notifications. */
1.97 +
1.98 + _condition.wait(guard);
1.99 + }
1.100 +
1.101 + /* Synchronise the notification flags and values. */
1.102 +
1.103 + update(object);
1.104 return L4_EOK;
1.105 }
1.106
1.107 @@ -227,7 +275,6 @@
1.108 void NotifierResource::close()
1.109 {
1.110 _release();
1.111 - _object->handler = NULL;
1.112 }
1.113
1.114 /* Object-specific resource methods. */
1.115 @@ -284,8 +331,8 @@
1.116 {
1.117 /* Update the notifiable object. */
1.118
1.119 - _object->notifications |= flags;
1.120 - _object->values = values;
1.121 + _object->pending_notifications |= flags;
1.122 + _object->pending_values = values;
1.123
1.124 _notify();
1.125 return L4_EOK;
1.126 @@ -297,14 +344,6 @@
1.127
1.128 std::lock_guard<std::mutex> guard(_lock);
1.129
1.130 - /* Record a pending notification which persists if nothing is waiting. */
1.131 -
1.132 - _pending = true;
1.133 -
1.134 - /* Notify any party waiting specifically on this object. */
1.135 -
1.136 - _condition.notify_one();
1.137 -
1.138 /* Register the notification with all notifier objects. */
1.139
1.140 ObjectNotifiers::iterator it;
1.141 @@ -325,22 +364,5 @@
1.142 (*it)->release(_object);
1.143 }
1.144
1.145 -/* Wait for notification events on a specific object. */
1.146 -
1.147 -long NotifierResource::wait()
1.148 -{
1.149 - /* Enter critical section for the resource. */
1.150 -
1.151 - std::unique_lock<std::mutex> guard(_lock);
1.152 -
1.153 - /* Wait for the notification condition. */
1.154 -
1.155 - if (!_pending)
1.156 - _condition.wait(guard);
1.157 -
1.158 - _pending = false;
1.159 - return L4_EOK;
1.160 -}
1.161 -
1.162 /* vim: tabstop=2 expandtab shiftwidth=2
1.163 */