1.1 --- a/libfsclient/include/fsclient/notifier.h Wed Jul 07 00:28:19 2021 +0200
1.2 +++ b/libfsclient/include/fsclient/notifier.h Fri Jul 09 00:15:29 2021 +0200
1.3 @@ -67,15 +67,19 @@
1.4
1.5 /* Local operations. */
1.6
1.7 + virtual long start();
1.8 +
1.9 virtual long subscribe(file_t *file, notify_flags_t flags);
1.10
1.11 virtual long unsubscribe(file_t *file);
1.12
1.13 - virtual void mainloop();
1.14 + virtual long wait(file_t **file);
1.15 +
1.16 + virtual long wait_file(file_t *file);
1.17
1.18 - virtual long start();
1.19 + /* Event handling support. */
1.20
1.21 - virtual long wait(file_t **file);
1.22 + virtual void mainloop();
1.23 };
1.24
1.25
2.1 --- a/libfsclient/lib/src/file.cc Wed Jul 07 00:28:19 2021 +0200
2.2 +++ b/libfsclient/lib/src/file.cc Fri Jul 09 00:15:29 2021 +0200
2.3 @@ -394,18 +394,9 @@
2.4
2.5 long file_notify_wait_file(file_t *file)
2.6 {
2.7 - file_t *affected;
2.8 -
2.9 - do
2.10 - {
2.11 - long err = file_notify_wait_files(&affected);
2.12 + FileNotifier *notifier = get_notifier();
2.13
2.14 - if (err)
2.15 - return err;
2.16 - }
2.17 - while (affected != file);
2.18 -
2.19 - return L4_EOK;
2.20 + return notifier->wait_file(file);
2.21 }
2.22
2.23 /* Wait for notification events on files. */
3.1 --- a/libfsclient/lib/src/notifier.cc Wed Jul 07 00:28:19 2021 +0200
3.2 +++ b/libfsclient/lib/src/notifier.cc Fri Jul 09 00:15:29 2021 +0200
3.3 @@ -100,10 +100,18 @@
3.4 {
3.5 std::unique_lock<std::mutex> guard(_lock);
3.6
3.7 - /* Record the flags for the file object. */
3.8 + /* Record the flags for the file object. Where no flags are already recorded,
3.9 + the new flags will be recorded and the file object queued. Otherwise, the
3.10 + new flags will be combined with the recorded flags. */
3.11 +
3.12 + notify_flags_t recorded = _affected_flags[file];
3.13
3.14 - _affected_flags[file] = _affected_flags[file] | flags;
3.15 - _affected.push_back(file);
3.16 + _affected_flags[file] = recorded | flags;
3.17 +
3.18 + /* Add a file queue entry for any files without recorded notifications. */
3.19 +
3.20 + if (!recorded)
3.21 + _affected.push_back(file);
3.22
3.23 /* Notify any waiting caller. */
3.24
3.25 @@ -195,17 +203,53 @@
3.26
3.27 while (1)
3.28 {
3.29 - if (!_affected.empty())
3.30 + /* Obtain queued files until one is found that still has events recorded
3.31 + for it. (Waiting for events specific to one file will remove recorded
3.32 + events but not any file queue entries.) */
3.33 +
3.34 + while (!_affected.empty())
3.35 {
3.36 *file = _affected.front();
3.37 _affected.pop_front();
3.38
3.39 - (*file)->notifications = _affected_flags[*file];
3.40 - _affected_flags.erase(*file);
3.41 + notify_flags_t recorded = _affected_flags[*file];
3.42 +
3.43 + if (recorded)
3.44 + {
3.45 + (*file)->notifications = recorded;
3.46 + _affected_flags.erase(*file);
3.47 + return L4_EOK;
3.48 + }
3.49 + }
3.50 +
3.51 + /* No queued events. */
3.52 +
3.53 + _notified.wait(guard);
3.54 + }
3.55 +
3.56 + return L4_EOK;
3.57 +}
3.58 +
3.59 +/* Wait for notifications from a single file. */
3.60 +
3.61 +long FileNotifier::wait_file(file_t *file)
3.62 +{
3.63 + std::unique_lock<std::mutex> guard(_lock);
3.64 +
3.65 + while (1)
3.66 + {
3.67 + notify_flags_t recorded = _affected_flags[file];
3.68 +
3.69 + if (recorded)
3.70 + {
3.71 + file->notifications = recorded;
3.72 + _affected_flags.erase(file);
3.73 return L4_EOK;
3.74 }
3.75 - else
3.76 - _notified.wait(guard);
3.77 +
3.78 + /* No recorded events for the file. */
3.79 +
3.80 + _notified.wait(guard);
3.81 }
3.82
3.83 return L4_EOK;