• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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