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 class ThreadNotification { 35 public: 36 using native_handle_type = backend::NativeThreadNotificationHandle; 37 38 ThreadNotification(); 39 ~ThreadNotification(); 40 ThreadNotification(const ThreadNotification&) = delete; 41 ThreadNotification(ThreadNotification&&) = delete; 42 ThreadNotification& operator=(const ThreadNotification&) = delete; 43 ThreadNotification& operator=(ThreadNotification&&) = delete; 44 45 // Blocks indefinitely until the thread is notified, i.e. until the 46 // notification latch can be cleared because it was set. 47 // 48 // Clears the notification latch. 49 // 50 // IMPORTANT: This should only be used by a single consumer thread. 51 void acquire(); 52 53 // Returns whether the thread has been notified, i.e. whether the notificion 54 // latch was set and resets the latch regardless. 55 // 56 // Clears the notification latch. 57 // 58 // Returns true if the thread was notified, meaning the the internal latch was 59 // reset successfully. 60 // 61 // IMPORTANT: This should only be used by a single consumer thread. 62 bool try_acquire(); 63 64 // Notifies the thread in a saturating manner, setting the notification latch. 65 // 66 // Raising the notification multiple time without it being acquired by the 67 // consuming thread is equivalent to raising the notification once to the 68 // thread. The notification is latched in case the thread was not waiting at 69 // the time. 70 // 71 // This is IRQ and thread safe. 72 void release(); 73 74 native_handle_type native_handle(); 75 76 private: 77 // This may be a wrapper around a native type with additional members. 78 backend::NativeThreadNotification native_type_; 79 }; 80 81 } // namespace pw::sync 82 83 #include "pw_sync_backend/thread_notification_inline.h" 84