1 // Copyright 2021 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include "pw_sync_backend/thread_notification_native.h" 17 18 namespace pw::sync { 19 20 /// The `ThreadNotification` is a synchronization primitive that can be used to 21 /// permit a SINGLE thread to block and consume a latching, saturating 22 /// notification from multiple notifiers. 23 /// 24 /// IMPORTANT: This is a single consumer/waiter, multiple producer/notifier API! 25 /// The acquire APIs must only be invoked by a single consuming thread. As a 26 /// result, having multiple threads receiving notifications via the acquire API 27 /// is unsupported. 28 /// 29 /// This is effectively a subset of a binary semaphore API, except that only a 30 /// single thread can be notified and block at a time. 31 /// 32 /// The single consumer aspect of the API permits the use of a smaller and/or 33 /// faster native APIs such as direct thread signaling. 34 /// 35 /// The `ThreadNotification` is initialized to being empty (latch is not set). 36 class ThreadNotification { 37 public: 38 using native_handle_type = backend::NativeThreadNotificationHandle; 39 40 ThreadNotification(); 41 ~ThreadNotification(); 42 ThreadNotification(const ThreadNotification&) = delete; 43 ThreadNotification(ThreadNotification&&) = delete; 44 ThreadNotification& operator=(const ThreadNotification&) = delete; 45 ThreadNotification& operator=(ThreadNotification&&) = delete; 46 47 /// Blocks indefinitely until the thread is notified, i.e. until the 48 /// notification latch can be cleared because it was set. 49 /// 50 /// Clears the notification latch. 51 /// 52 /// @b IMPORTANT: This should only be used by a single consumer thread. 53 void acquire(); 54 55 /// Returns whether the thread has been notified, i.e. whether the notificion 56 /// latch was set and resets the latch regardless. 57 /// 58 /// Clears the notification latch. 59 /// 60 /// Returns true if the thread was notified, meaning the the internal latch 61 /// was reset successfully. 62 /// 63 /// @b IMPORTANT: This should only be used by a single consumer thread. 64 bool try_acquire(); 65 66 /// Notifies the thread in a saturating manner, setting the notification 67 /// latch. 68 /// 69 /// Raising the notification multiple time without it being acquired by the 70 /// consuming thread is equivalent to raising the notification once to the 71 /// thread. The notification is latched in case the thread was not waiting at 72 /// the time. 73 /// 74 /// This is IRQ and thread safe. 75 void release(); 76 77 native_handle_type native_handle(); 78 79 private: 80 /// This may be a wrapper around a native type with additional members. 81 backend::NativeThreadNotification native_type_; 82 }; 83 84 } // namespace pw::sync 85 86 #include "pw_sync_backend/thread_notification_inline.h" 87