Skip to content

Commit

Permalink
Merge pull request #840 from ApexAI/iox-#449-prepare-PoshRuntime-for-…
Browse files Browse the repository at this point in the history
…mock

Iox #449 prepare posh runtime for mock
  • Loading branch information
elBoberido authored Jun 10, 2021
2 parents 7697383 + a7f2210 commit eb02564
Show file tree
Hide file tree
Showing 19 changed files with 848 additions and 671 deletions.
7 changes: 7 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ The following doxygen comments are required for public API headers:
/// @return description
```

For overrides of virtual methods the `copydoc` tag can be used:

```cpp
/// @copydoc BaseClass::method
/// @note Optional describe some specifics to the override
```

A good example for code formatting and doxygen structure is at [swe_docu_guidelines.md (WIP)](./doc/aspice_swe3_4/swe_docu_guidelines.md)

## Folder structure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ class ExampleDerivedClass : public ExampleBaseClass<T>
/// @param[in] b Description of input parameter b
ExampleDerivedClass(const uint64_t a, const uint64_t b) noexcept;

/// @copydoc ExampleBaseClass<T>::doSomething
/// @note Optional short description of the override
uint32_t doSomething(const uint32_t a) const noexcept override;

/// @copydoc ExampleBaseClass<T>::doSomethingWithOverload()
/// @note Optional short description of the override
uint32_t doSomethingWithOverload() const noexcept override;

/// @copydoc ExampleBaseClass<T>::doSomethingWithOverload(uint32_t,uint32_t)
/// @note Optional short description of the override
uint32_t doSomethingWithOverload(const uint32_t a, const uint32_t b) const noexcept override;

/// @brief Short description
void simpleMethod() const noexcept;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,36 @@ class ExampleBaseClass
/// @brief Short description
/// @details Detailed description
/// @param[in] input Description of input parameter
ExampleBaseClass(const uint32_t input);
ExampleBaseClass(const uint32_t input) noexcept;

/// @brief Short description
ExampleBaseClass() = default;

virtual ~ExampleBaseClass() = default;

/// @brief Short description
/// @return description of return value
uint32_t getMemberVariable() const noexcept;

/// @brief Short description
/// @return description of return value
uint32_t simplerMethod() const noexcept;

/// @brief Short description
/// @param[in] a Description of parameter
/// @return description of return value
virtual uint32_t doSomething(uint32_t a) const noexcept;

/// @brief Short description
/// @return description of return value
virtual uint32_t doSomethingWithOverload() const noexcept;

/// @brief Short description
/// @param[in] a Description of parameter
/// @param[in] b Description of parameter
/// @return description of return value
virtual uint32_t doSomethingWithOverload(uint32_t a, uint32_t b) const noexcept;

private:
/// @brief Short description
uint32_t m_memberVariable{0U};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


template <typename T>
inline ExampleBaseClass<T>::ExampleBaseClass(const uint32_t input)
inline ExampleBaseClass<T>::ExampleBaseClass(const uint32_t input) noexcept
: m_memberVariable(input)
{
// example code
Expand All @@ -38,4 +38,25 @@ inline uint32_t ExampleBaseClass<T>::simplerMethod() const noexcept
return 99U;
}

template <typename T>
inline uint32_t ExampleBaseClass<T>::doSomething(uint32_t a) const noexcept
{
// example code
return a;
}

template <typename T>
inline uint32_t ExampleBaseClass<T>::doSomethingWithOverload() const noexcept
{
// example code
return 42U;
}

template <typename T>
inline uint32_t ExampleBaseClass<T>::doSomethingWithOverload(const uint32_t a, const uint32_t b) const noexcept
{
// example code
return 42U + a + b;
}

#endif // EXAMPLE_BASE_CLASS_INL_INCLUDED
11 changes: 7 additions & 4 deletions doc/aspice_swe3_4/swe_docu_guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ sudo apt install plantuml

## Howto document your code
The doxygen documentation consist of two parts, the documentation with specific tags in the code and a doxygen file which defines
the parameters for the generated files. Examples can be found in the subfolders.
the parameters for the generated files. Examples can be found in the subfolders.

Some general rules:
- the implementation documentation should never describe what happens, that does already the code for you. It should describe why it is implemented in the way it is.
- the implementation documentation should never describe what happens, that does already the code for you. It should describe why it is implemented in the way it is.
- every doxygen comment line always begin with `///`, no C-style comment blocks with `/**` allowed
- every doxygen tag always begin with `@` e.g. `@brief comment`, no `\` for tags allowed
- documentation is done in header files only
Expand All @@ -48,6 +48,9 @@ Some general rules:
A list of available doxygen tags can be found [here](https://www.doxygen.nl/manual/commands.html).
Here we provide a list with the most usual tags in iceoryx:
- `/// @brief` short description
- `/// @copydoc` used for overrides of virtual methods, see [iceoryx_derived_class.hpp](example/iceoryx_component/include/example_module/example_derived_class.hpp)
- `/// @copybrief` similar to `@copydoc` but copies only the brief description
- `/// @copydetail` similar to `@copydoc` but copies only the detailed description
- `/// @details` more text if needed
- `/// @note` place infos here if they are not that much important but good for explanation
- `/// @attention` give here important information to the user/developer, keep as short as possible
Expand Down Expand Up @@ -103,7 +106,7 @@ See the header files under iceoryx/doc/aspice_swe3_4/example.

### PlantUML

if you want to make complex aspects of your implementation visible, you can write PlantUML directly into the
if you want to make complex aspects of your implementation visible, you can write PlantUML directly into the
doxygen description of your class. An example can be found at [example_base_class.hpp](example/iceoryx_component/source/example_module/example_base_class.hpp)

Having PlantUML installed is not a must. If you want to use it you need to install it, and the variable `PLANTUML_JAR_PATH` needs to be set.
Expand All @@ -116,7 +119,7 @@ For good examples on PlantUML checkout https://plantuml.com.

### Pull-Request

In iceoryx Pull-Requests are pdf files generated and uploaded to the Github artifact store.
In iceoryx Pull-Requests are pdf files generated and uploaded to the Github artifact store.

If you want to download the pdf files from the Pull-Requests or master build you can do it by the following way:

Expand Down
1 change: 1 addition & 0 deletions iceoryx_examples/iceperf/iceperf_leader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <iomanip>
#include <iostream>
#include <vector>

//! [use constants instead of magic values]
constexpr const char APP_NAME[]{"iceperf-bench-leader"};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ namespace iox
error(POSH__RUNTIME_FACTORY_IS_NOT_SET) \
error(POSH__RUNTIME_IS_CREATED_MULTIPLE_TIMES) \
error(POSH__RUNTIME_PUBLISHER_PORT_NOT_UNIQUE) \
error(POSH__RUNTIME_PUBLISHER_PORT_CREATION_UNDEFINED_BEHAVIOR) \
error(POSH__RUNTIME_SUBSCRIBER_PORT_CREATION_UNDEFINED_BEHAVIOR) \
error(POSH__RUNTIME_PUBLISHER_PORT_CREATION_UNKNOWN_ERROR) \
error(POSH__RUNTIME_SUBSCRIBER_PORT_CREATION_UNKNOWN_ERROR) \
error(POSH__RUNTIME_ROUDI_PUBLISHER_LIST_FULL) \
error(POSH__RUNTIME_ROUDI_SUBSCRIBER_LIST_FULL) \
error(POSH__RUNTIME_ROUDI_CONDITION_VARIABLE_LIST_FULL) \
Expand All @@ -49,8 +49,7 @@ namespace iox
error(POSH__RUNTIME_ROUDI_GET_MW_INTERFACE_WRONG_IPC_MESSAGE_RESPONSE) \
error(POSH__RUNTIME_ROUDI_CREATE_NODE_WRONG_IPC_MESSAGE_RESPONSE) \
error(POSH__RUNTIME_ROUDI_GET_MW_APPLICATION_WRONG_IPC_MESSAGE_RESPONSE) \
error(POSH__RUNTIME_ROUDI_CONDITION_VARIABLE_CREATION_UNDEFINED_BEHAVIOR) \
error(POSH__RUNTIME_ROUDI_EVENT_VARIABLE_CREATION_UNDEFINED_BEHAVIOR) \
error(POSH__RUNTIME_ROUDI_CONDITION_VARIABLE_CREATION_UNKNOWN_ERROR) \
error(POSH__RUNTIME_APP_WITH_SAME_RUNTIME_NAME_STILL_RUNNING) \
error(POSH__RUNTIME_NO_WRITABLE_SHM_SEGMENT) \
error(POSH__RUNTIME_NO_NAME_PROVIDED) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,19 @@ namespace posix
/// #include "iceoryx_hoofs/internal/posix_wrapper/mutex.hpp"
///
/// int main() {
/// cxx::optional<posix::mutex> myMutex = posix::mutex::CreateMutex(false);
/// posix::mutex myMutex(false);
///
/// // always verify if the mutex could be created since we aren't
/// // throwing exceptions
/// if ( myMutex.has_value() ) {
/// myMutex->lock();
/// // ... do stuff
/// myMutex->unlock();
/// }
/// myMutex->lock();
/// // ... do stuff
/// myMutex->unlock();
///
/// {
/// // we need to use the dereferencing operator since myMutex is
/// // a mutex wrapped in an optional
/// std::lock_guard<posix::mutex> lock(*myMutex);
/// std::lock_guard<posix::mutex> lock(myMutex);
/// // ...
/// }
///
/// }
///
/// @endcode
/// @attention Errors in c'tor or d'tor can lead to a program termination!
///
class mutex
Expand Down
1 change: 1 addition & 0 deletions iceoryx_posh/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ add_library(iceoryx_posh
source/runtime/ipc_message.cpp
source/runtime/port_config_info.cpp
source/runtime/posh_runtime.cpp
source/runtime/posh_runtime_impl.cpp
source/runtime/posh_runtime_single_process.cpp
source/runtime/node.cpp
source/runtime/node_data.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// 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
//
// http://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.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_POSH_RUNTIME_POSH_RUNTIME_IMPL_HPP
#define IOX_POSH_RUNTIME_POSH_RUNTIME_IMPL_HPP

#include "iceoryx_hoofs/cxx/method_callback.hpp"
#include "iceoryx_hoofs/internal/concurrent/periodic_task.hpp"
#include "iceoryx_hoofs/internal/posix_wrapper/mutex.hpp"
#include "iceoryx_posh/internal/runtime/shared_memory_user.hpp"
#include "iceoryx_posh/runtime/posh_runtime.hpp"

namespace iox
{
namespace runtime
{
enum class RuntimeLocation
{
SEPARATE_PROCESS_FROM_ROUDI,
SAME_PROCESS_LIKE_ROUDI,
};

/// @brief The runtime that is needed for each application to communicate with the RouDi daemon
class PoshRuntimeImpl : public PoshRuntime
{
public:
PoshRuntimeImpl(const PoshRuntimeImpl&) = delete;
PoshRuntimeImpl& operator=(const PoshRuntimeImpl&) = delete;
PoshRuntimeImpl(PoshRuntimeImpl&&) = delete;
PoshRuntimeImpl& operator=(PoshRuntimeImpl&&) = delete;
virtual ~PoshRuntimeImpl() noexcept;

/// @copydoc PoshRuntime::findService
cxx::expected<InstanceContainer, FindServiceError>
findService(const capro::ServiceDescription& serviceDescription) noexcept override;

/// @copydoc PoshRuntime::offerService
bool offerService(const capro::ServiceDescription& serviceDescription) noexcept override;

/// @copydoc PoshRuntime::stopOfferService
void stopOfferService(const capro::ServiceDescription& serviceDescription) noexcept override;

/// @copydoc PoshRuntime::getMiddlewarePublisher
PublisherPortUserType::MemberType_t*
getMiddlewarePublisher(const capro::ServiceDescription& service,
const popo::PublisherOptions& publisherOptions = popo::PublisherOptions(),
const PortConfigInfo& portConfigInfo = PortConfigInfo()) noexcept override;

/// @copydoc PoshRuntime::getMiddlewareSubscriber
SubscriberPortUserType::MemberType_t*
getMiddlewareSubscriber(const capro::ServiceDescription& service,
const popo::SubscriberOptions& subscriberOptions = popo::SubscriberOptions(),
const PortConfigInfo& portConfigInfo = PortConfigInfo()) noexcept override;

/// @copydoc PoshRuntime::getMiddlewareInterface
popo::InterfacePortData* getMiddlewareInterface(const capro::Interfaces interface,
const NodeName_t& nodeName = {""}) noexcept override;

/// @copydoc PoshRuntime::getMiddlewareApplication
popo::ApplicationPortData* getMiddlewareApplication() noexcept override;

/// @copydoc PoshRuntime::getMiddlewareConditionVariable
popo::ConditionVariableData* getMiddlewareConditionVariable() noexcept override;

/// @copydoc PoshRuntime::createNode
NodeData* createNode(const NodeProperty& nodeProperty) noexcept override;

/// @copydoc PoshRuntime::getServiceRegistryChangeCounter
const std::atomic<uint64_t>* getServiceRegistryChangeCounter() noexcept override;

/// @copydoc PoshRuntime::sendRequestToRouDi
bool sendRequestToRouDi(const IpcMessage& msg, IpcMessage& answer) noexcept override;

protected:
friend class PoshRuntime;
friend class roudi::RuntimeTestInterface;

// Protected constructor for IPC setup
PoshRuntimeImpl(cxx::optional<const RuntimeName_t*> name,
const RuntimeLocation location = RuntimeLocation::SEPARATE_PROCESS_FROM_ROUDI) noexcept;

private:
cxx::expected<PublisherPortUserType::MemberType_t*, IpcMessageErrorType>
requestPublisherFromRoudi(const IpcMessage& sendBuffer) noexcept;

cxx::expected<SubscriberPortUserType::MemberType_t*, IpcMessageErrorType>
requestSubscriberFromRoudi(const IpcMessage& sendBuffer) noexcept;

cxx::expected<popo::ConditionVariableData*, IpcMessageErrorType>
requestConditionVariableFromRoudi(const IpcMessage& sendBuffer) noexcept;

mutable posix::mutex m_appIpcRequestMutex{false};

IpcRuntimeInterface m_ipcChannelInterface;
cxx::optional<SharedMemoryUser> m_ShmInterface;
popo::ApplicationPort m_applicationPort;

void sendKeepAliveAndHandleShutdownPreparation() noexcept;
static_assert(PROCESS_KEEP_ALIVE_INTERVAL > roudi::DISCOVERY_INTERVAL, "Keep alive interval too small");

// the m_keepAliveTask should always be the last member, so that it will be the first member to be destroyed
concurrent::PeriodicTask<cxx::MethodCallback<void>> m_keepAliveTask{
concurrent::PeriodicTaskAutoStart,
PROCESS_KEEP_ALIVE_INTERVAL,
"KeepAlive",
*this,
&PoshRuntimeImpl::sendKeepAliveAndHandleShutdownPreparation};
};

} // namespace runtime
} // namespace iox

#endif // IOX_POSH_RUNTIME_POSH_RUNTIME_IMPL_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,11 @@ class SharedMemoryUser
{
public:
/// @brief Constructor
/// @param[in] doMapSharedMemoryIntoThread used by roudi environment for testing. No mapping of memory if false
/// @param[in] topicSize size of the shared memory management segment
/// @param[in] segmentManagerAddr adress of the segment manager that does the final mapping of memory in the process
/// @param[in] segmentId of the relocatable shared memory segment
/// address space
SharedMemoryUser(const bool doMapSharedMemoryIntoThread,
const size_t topicSize,
SharedMemoryUser(const size_t topicSize,
const uint64_t segmentId,
const rp::BaseRelativePointer::offset_t segmentManagerAddressOffset);

Expand Down
Loading

0 comments on commit eb02564

Please sign in to comment.