aboutsummaryrefslogtreecommitdiff
path: root/pw_sync/public/pw_sync/thread_notification.h
blob: 85e6e1b6ba795cf16dc391a7edf68f28ee9ffeeb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once

#include "pw_sync_backend/thread_notification_native.h"

namespace pw::sync {

/// The `ThreadNotification` is a synchronization primitive that can be used to
/// permit a SINGLE thread to block and consume a latching, saturating
/// notification from multiple notifiers.
///
/// IMPORTANT: This is a single consumer/waiter, multiple producer/notifier API!
/// The acquire APIs must only be invoked by a single consuming thread. As a
/// result, having multiple threads receiving notifications via the acquire API
/// is unsupported.
///
/// This is effectively a subset of a binary semaphore API, except that only a
/// single thread can be notified and block at a time.
///
/// The single consumer aspect of the API permits the use of a smaller and/or
/// faster native APIs such as direct thread signaling.
///
/// The `ThreadNotification` is initialized to being empty (latch is not set).
class ThreadNotification {
 public:
  using native_handle_type = backend::NativeThreadNotificationHandle;

  ThreadNotification();
  ~ThreadNotification();
  ThreadNotification(const ThreadNotification&) = delete;
  ThreadNotification(ThreadNotification&&) = delete;
  ThreadNotification& operator=(const ThreadNotification&) = delete;
  ThreadNotification& operator=(ThreadNotification&&) = delete;

  /// Blocks indefinitely until the thread is notified, i.e. until the
  /// notification latch can be cleared because it was set.
  ///
  /// Clears the notification latch.
  ///
  /// @b IMPORTANT: This should only be used by a single consumer thread.
  void acquire();

  /// Returns whether the thread has been notified, i.e. whether the notificion
  /// latch was set and resets the latch regardless.
  ///
  /// Clears the notification latch.
  ///
  /// Returns true if the thread was notified, meaning the the internal latch
  /// was reset successfully.
  ///
  /// @b IMPORTANT: This should only be used by a single consumer thread.
  bool try_acquire();

  /// Notifies the thread in a saturating manner, setting the notification
  /// latch.
  ///
  /// Raising the notification multiple time without it being acquired by the
  /// consuming thread is equivalent to raising the notification once to the
  /// thread. The notification is latched in case the thread was not waiting at
  /// the time.
  ///
  /// This is IRQ and thread safe.
  void release();

  native_handle_type native_handle();

 private:
  /// This may be a wrapper around a native type with additional members.
  backend::NativeThreadNotification native_type_;
};

}  // namespace pw::sync

#include "pw_sync_backend/thread_notification_inline.h"