iceoryx_hoofs  2.0.2
named_pipe.hpp
1 // Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // SPDX-License-Identifier: Apache-2.0
16 #ifndef IOX_HOOFS_POSIX_WRAPPER_NAMED_PIPE_HPP
17 #define IOX_HOOFS_POSIX_WRAPPER_NAMED_PIPE_HPP
18 
19 #include "iceoryx_hoofs/concurrent/lockfree_queue.hpp"
20 #include "iceoryx_hoofs/cxx/string.hpp"
21 #include "iceoryx_hoofs/design_pattern/creation.hpp"
22 #include "iceoryx_hoofs/internal/posix_wrapper/ipc_channel.hpp"
23 #include "iceoryx_hoofs/internal/posix_wrapper/shared_memory_object.hpp"
24 #include "iceoryx_hoofs/internal/units/duration.hpp"
25 #include "iceoryx_hoofs/posix_wrapper/semaphore.hpp"
26 
27 #include <cstdint>
28 
29 namespace iox
30 {
31 namespace posix
32 {
33 class NamedPipe : public DesignPattern::Creation<NamedPipe, IpcChannelError>
34 {
35  public:
36  // no system restrictions at all, except available memory. MAX_MESSAGE_SIZE and MAX_NUMBER_OF_MESSAGES can be
37  // increased as long as there is enough memory available
38  static constexpr uint64_t MAX_MESSAGE_SIZE = 4U * 1024U;
39  static constexpr uint64_t MAX_NUMBER_OF_MESSAGES = 10U;
40 
41  static constexpr uint64_t NULL_TERMINATOR_SIZE = 0U;
42  static constexpr units::Duration CYCLE_TIME = units::Duration::fromMilliseconds(10);
43  static constexpr const char NAMED_PIPE_PREFIX[] = "iox_np_";
44 
47 
48  NamedPipe(const NamedPipe&) = delete;
49  NamedPipe& operator=(const NamedPipe&) = delete;
50 
53  NamedPipe() noexcept;
54 
55  NamedPipe(NamedPipe&& rhs) noexcept;
56  NamedPipe& operator=(NamedPipe&& rhs) noexcept;
57  ~NamedPipe() noexcept;
58 
61  cxx::expected<IpcChannelError> destroy() noexcept;
62 
66  static cxx::expected<bool, IpcChannelError> unlinkIfExists(const IpcChannelName_t& name) noexcept;
67 
70  cxx::expected<bool, IpcChannelError> isOutdated() noexcept;
71 
74  cxx::expected<IpcChannelError> trySend(const std::string& message) const noexcept;
75 
80  cxx::expected<IpcChannelError> send(const std::string& message) const noexcept;
81 
86  cxx::expected<IpcChannelError> timedSend(const std::string& message, const units::Duration& timeout) const noexcept;
87 
90  cxx::expected<std::string, IpcChannelError> tryReceive() const noexcept;
91 
95  cxx::expected<std::string, IpcChannelError> receive() const noexcept;
96 
100  cxx::expected<std::string, IpcChannelError> timedReceive(const units::Duration& timeout) const noexcept;
101 
102  private:
103  friend class DesignPattern::Creation<NamedPipe, IpcChannelError>;
104 
111  NamedPipe(const IpcChannelName_t& name,
112  const IpcChannelSide channelSide,
113  const size_t maxMsgSize = MAX_MESSAGE_SIZE,
114  const uint64_t maxMsgNumber = MAX_NUMBER_OF_MESSAGES) noexcept;
115 
116  template <typename Prefix>
117  static IpcChannelName_t convertName(const Prefix& p, const IpcChannelName_t& name) noexcept;
118 
119  private:
120  cxx::optional<SharedMemoryObject> m_sharedMemory;
121 
122  class NamedPipeData
123  {
124  public:
125  NamedPipeData(bool& isInitialized, IpcChannelError& error, const uint64_t maxMsgNumber) noexcept;
126  NamedPipeData(const NamedPipeData&) = delete;
127  NamedPipeData(NamedPipeData&& rhs) = delete;
128  ~NamedPipeData() noexcept;
129 
130  NamedPipeData& operator=(const NamedPipeData&) = delete;
131  NamedPipeData& operator=(NamedPipeData&& rhs) = delete;
132 
133  Semaphore& sendSemaphore() noexcept;
134  Semaphore& receiveSemaphore() noexcept;
135 
136  bool waitForInitialization() const noexcept;
137  bool hasValidState() const noexcept;
138 
139  MessageQueue_t messages;
140 
141  private:
142  static constexpr uint64_t SEND_SEMAPHORE = 0U;
143  static constexpr uint64_t RECEIVE_SEMAPHORE = 1U;
144 
145  static constexpr uint64_t INVALID_DATA = 0xBAADF00DAFFEDEAD;
146  static constexpr uint64_t VALID_DATA = 0xBAD0FF1CEBEEFBEE;
147  static constexpr units::Duration WAIT_FOR_INIT_TIMEOUT = units::Duration::fromSeconds(1);
148  static constexpr units::Duration WAIT_FOR_INIT_SLEEP_TIME = units::Duration::fromMilliseconds(1);
149 
150  std::atomic<uint64_t> initializationGuard{INVALID_DATA};
151  using semaphoreMemory_t = uint8_t[sizeof(Semaphore)];
152  alignas(Semaphore) semaphoreMemory_t semaphores[2U];
153  };
154 
155 
156  NamedPipeData* m_data = nullptr;
157 };
158 } // namespace posix
159 } // namespace iox
160 
161 #endif
This pattern can be used if you write an abstraction where you have to throw an exception in the cons...
Definition: creation.hpp:99
bool isInitialized() const noexcept
returns true if the object was constructed successfully, otherwise false
string implementation with some adjustments in the API, because we are not allowed to throw exception...
Definition: string.hpp:90
Definition: named_pipe.hpp:34
cxx::expected< IpcChannelError > send(const std::string &message) const noexcept
sends a message via the named pipe. if the pipe is full this call is blocking until the message could...
NamedPipe() noexcept
For compatibility with IpcChannel alias, default ctor which creates an uninitialized NamedPipe.
cxx::expected< IpcChannelError > trySend(const std::string &message) const noexcept
tries to send a message via the named pipe. if the pipe is full IpcChannelError::TIMEOUT is returned
cxx::expected< IpcChannelError > timedSend(const std::string &message, const units::Duration &timeout) const noexcept
sends a message via the named pipe.
cxx::expected< std::string, IpcChannelError > timedReceive(const units::Duration &timeout) const noexcept
receives a message via the named pipe.
static cxx::expected< bool, IpcChannelError > unlinkIfExists(const IpcChannelName_t &name) noexcept
removes a named pipe artifact from the system
cxx::expected< std::string, IpcChannelError > tryReceive() const noexcept
tries to receive a message via the named pipe. if the pipe is empty IpcChannelError::TIMEOUT is retur...
cxx::expected< std::string, IpcChannelError > receive() const noexcept
receives a message via the named pipe. if the pipe is empty this call is blocking until a message was...
cxx::expected< bool, IpcChannelError > isOutdated() noexcept
for compatibility with IpcChannelError
cxx::expected< IpcChannelError > destroy() noexcept
destroys an initialized named pipe.
Posix semaphore C++ Wrapping class.
Definition: semaphore.hpp:82
building block to easily create free function for logging in a library context
Definition: lockfree_queue.hpp:29