Skip to content

Commit

Permalink
expanded documentation, added Doxygen to build system
Browse files Browse the repository at this point in the history
  • Loading branch information
astro-friedel committed Dec 13, 2023
1 parent 0ed4740 commit 4818bf8
Show file tree
Hide file tree
Showing 22 changed files with 4,756 additions and 678 deletions.
20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ option(YGG_BUILD_THIRDPARTY_GTEST "Use gtest installation in 'thirdpart/gtest' b
option(YGG_BUILD_ASAN "Build with address sanitizer (gcc/clang)" OFF)
option(YGG_BUILD_UBSAN "Build with undefined behavior sanitizer (gcc/clang)" OFF)
option(YGG_ENABLE_INSTRUMENTATION_OPT "Build yggdrasil with -march or -mcpu options" ON)
option(YGG_BUILD_DOCS "Build documentation (requires Doxygen)" OFF)

message(STATUS "CMAKE_CXX_FLAGS = ${CMAKE_CXX_FLAGS}")

Expand Down Expand Up @@ -188,6 +189,25 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "In-source build prohibited.")
endif("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")

if(YGG_BUILD_DOCS)
find_package(Doxygen)
if(NOT Doxygen_FOUND)
message(WARNING "Doxygen not found, documentation will not be produced.")
set(YGG_BUILD_DOCS OFF CACHE BOOL "")
else()
set(DOXYGEN_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/doc CACHE INTERNAL "")
set(DOXYGEN_INPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "")
file(MAKE_DIRECTORY ${DOXYGEN_BUILD_DIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
add_custom_target(docs
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM)
install(DIRECTORY ${DOXYGEN_BUILD_DIR}
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/doc/ygginterrfacecpp
OPTIONAL)
endif()
endif()

add_definitions(-DRAPIDJSON_YGGDRASIL)
add_definitions(-DRAPIDJSON_HAS_STDSTRING)
Expand Down
2,664 changes: 2,664 additions & 0 deletions Doxyfile.in

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions src/YggInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -919,3 +919,56 @@ class YggJSONObjectInput : public YggInput {
}

};

/*! \mainpage
*
* The Ygg Interface library provides a communication framework for Yggdrasil components to use to send
* messages and data between them. It provides C, C++, Fortran, and Python bindings to the core C++ library,
* allowing it to be used by a wide range of code.
*
* \section install_section Installation
*
* The Ygg Interface has a few optional dependencies:
* - ZeroMQ - required to build the ZMQ communicators
* - OpemMP - used to parallelize some of the code
* - MPI - required to build the MPI based communicators
* - Python3 - required to build the Python bindings to this library
* - Doxygen - required to build the documentation
*
* Ygg Interface uses cmake as the build system. To build this project first clone the repository
*
* git clone https://github.com/astro-friedel/yggcpp.git
*
* then
*
* cd yggcpp
* mkdir build
* cd build
* cmake .. <OPTIONS>
* cmake --build . -j<X>
* cmake --install .
*
* where &lt;OPTIONS> is a set of flags and arguments for cmake, and &lt;X> gives the number of parallel processes to use for compiling. Common options are
*
* | Option | Description | Default |
* | :---------------------- | :----------------------------------- | :------ |
* | CMAKE_BUILD_TYPE | The type of build. One of Debug, Release, RelWithDebInfo, MinSizeRel | Debug |
* | CMAKE_INSTALL_PREFIX | The root path to install the library and headers in | System dependent |
* | ENABLE_ZMQ | If ON, build the ZeroMQ based communicators, requires ZeroMQ is already installed. | ON |
* | YGGDRASIL_DISABLE_PYTHON_C_API | If ON, do not build the Python C API | OFF |
* | USING_IPC | If ON, default to using IPC queues | OFF |
* | BUILD_CPP_LIBRARY | If ON, build the C++ interface library | ON |
* | BUILD_PYTHON_LIBRARY | If ON, build the independent Python interface library | OFF |
* | YGG_PYTHON_LIBRARY_WRAP | If ON, build the Python interface library by wrapping the C++ module | ON |
* | YGG_BUILD_DOCS | If ON, then build the documentation | OFF |
* | YGG_BUILD_TESTS | If ON, then build the test suite | OFF |
* | YGG_BUILD_THIRDPARTY_GTEST | If ON, then use the included gtest with the test suite | ON |
* | YGG_ENABLE_COVERAGE | If ON, enable test coverage reporting | OFF |
* | YGG_BUILD_ASAN | If ON, then build with an address sanitizer (gcc/clang only) | OFF |
* | YGG_BUILD_UBSAN | If ON, build with a undefined behavior sanitizer (gcc/clang only) | OFF |
* | YGG_ENABLE_INSTRUMENTATION_OPT | If ON, add the build options -march or -mcpu | ON |
*
* Note that options must be preceeded by a -D, e.g.
*
* -DCMAKE_BUILD_TYPE=Release
*/
169 changes: 109 additions & 60 deletions src/communicators/AsyncComm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,134 @@
#include <atomic>

namespace YggInterface {
namespace communicator {

namespace communicator {
/**
* @brief Asynchronous backlog class for holding data to be transmitted
*/
class AsyncBacklog {
public:
AsyncBacklog(const AsyncBacklog&) = delete;
AsyncBacklog& operator=(const AsyncBacklog&) = delete;
public:
AsyncBacklog(Comm_t* parent);
~AsyncBacklog();
bool on_thread(Comm_t* parent);
int send();
long recv();
Comm_t* comm;
std::mutex comm_mutex;
std::atomic_bool opened;
std::atomic_bool closing;
std::atomic_bool locked;
std::vector<utils::Header> backlog;
std::thread backlog_thread;
/**
* @brief Create a new instance
* @param[in] parent The parent communicator
*/
explicit AsyncBacklog(Comm_t* parent);
~AsyncBacklog();
/**
* @brief Function to run in a thread which sends/receives messages
* @param[in] parent The parent communicator
* @return Always returns false, when the thread is shut down.
*/
bool on_thread(Comm_t* parent);
/**
* @brief Send a message from the backlog
* @return The length of data sent, in bytes.
*/
int send();
/**
* @brief Receive message into the backlog
* @return The length of data received, in bytes.
*/
long recv();
Comm_t* comm; /**< parent communicator */
std::mutex comm_mutex; /**< communicator lock */
std::atomic_bool opened; /**< whether the communicator is open */
std::atomic_bool closing; /**< whether the communicator is shutting down */
std::atomic_bool locked; /**< whether the communicator is locked */
std::vector<utils::Header> backlog; /**< messages to be processed */
std::thread backlog_thread; /**< thread for sending/receiving messages */
};


/**
* @brief Lock guard/mutex for asynchronous communication with a AsyncBacklog class.
*/
class AsyncLockGuard {
public:
AsyncLockGuard(const AsyncLockGuard&) = delete;
AsyncLockGuard& operator=(const AsyncLockGuard&) = delete;
public:
AsyncLockGuard(AsyncBacklog* backlog, bool dont_lock=false);
~AsyncLockGuard();
bool locked;
AsyncBacklog* backlog;
/**
* @brief Create an instance
* @param[in] backlog Instance of the AsyncBacklog class being used for communication
* @param[in] dont_lock If true, then immediately lock the mutex.
*/
explicit AsyncLockGuard(AsyncBacklog* backlog, bool dont_lock=false);
~AsyncLockGuard();
bool locked; /**< indicates whether the lock is currently enabled */
AsyncBacklog* backlog; /**< the AsyncBacklog instance to work with */
};

/**
* Asynchonous communication class.
* @brief Asynchonous communication class.
**/
class AsyncComm : public CommBase<AsyncBacklog> {
public:
/**
* Constructor
* @param name The name of the communicator
* @param address The address to associate with the communicator,
* if the address is nullptr, then an address will be created.
* @param direction Enumerated direction for communicator
* @param flgs Bitwise flags describing the communicator
* @param type Enumerated communicator type
**/
explicit AsyncComm(const std::string name,
utils::Address& address,
const DIRECTION direction = NONE, int flgs = 0,
const COMM_TYPE type = DEFAULT_COMM);
explicit AsyncComm(const std::string nme,
const DIRECTION dirn, int flgs = 0,
const COMM_TYPE type = DEFAULT_COMM);
explicit AsyncComm(utils::Address &addr,
const DIRECTION dirn, int flgs = 0,
const COMM_TYPE type = DEFAULT_COMM);
/**
* @brief Constructor
* @param[in] name The name of the communicator
* @param[in] address The address to associate with the communicator,
* if the address is nullptr, then an address will be created.
* @param[in] direction Enumerated direction for communicator
* @param[in] flgs Bitwise flags describing the communicator
* @param[in] type Enumerated communicator type
* @see utils::Address
**/
explicit AsyncComm(const std::string& name,
utils::Address& address,
const DIRECTION direction = NONE, int flgs = 0,
const COMM_TYPE type = DEFAULT_COMM);
/**
* @brief Constructor
* @param[in] name The name of the communicator
* @param[in] direction Enumerated direction for communicator
* @param[in] flgs Bitwise flags describing the communicator
* @param[in] type Enumerated communicator type
**/
explicit AsyncComm(const std::string& name,
const DIRECTION direction, int flgs = 0,
const COMM_TYPE type = DEFAULT_COMM);
/**
* @brief Constructor
* @param[in] address The address to associate with the communicator,
* if the address is nullptr, then an address will be created.
* @param[in] direction Enumerated direction for communicator
* @param[in] flgs Bitwise flags describing the communicator
* @param[in] type Enumerated communicator type
* @see utils::Address
**/
explicit AsyncComm(utils::Address &address,
const DIRECTION direction, int flgs = 0,
const COMM_TYPE type = DEFAULT_COMM);

/**
* Get the default communications type
* @return Enumeration of the default communications type
*/
static COMM_TYPE defaultCommType() { return DEFAULT_COMM; }

/** \copydoc YggInterface::communicator::Comm_t::comm_nmsg */
int comm_nmsg(DIRECTION dir=NONE) const override;
/** \copydoc YggInterface::communicator::Comm_t::getMetadata */
YggInterface::utils::Metadata& getMetadata(DIRECTION dir) override;
/** \copydoc YggInterface::communicator::Comm_t::set_timeout_recv */
void set_timeout_recv(int new_timeout) override;
/** \copydoc YggInterface::communicator::Comm_t::get_timeout_recv */
int get_timeout_recv() override;

// \copydoc Comm_t::defaultCommType
static COMM_TYPE defaultCommType() { return DEFAULT_COMM; }

// \copydoc Comm_t::comm_nmsg
int comm_nmsg(DIRECTION dir=NONE) const override;
// \copydoc Comm_t::getMetadata
YggInterface::utils::Metadata& getMetadata(const DIRECTION dir=NONE) override;
// \copydoc Comm_t::set_timeout_recv
void set_timeout_recv(int new_timeout) override;
// \copydoc Comm_t::get_timeout_recv
int get_timeout_recv() override;

using Comm_t::send;
using Comm_t::recv;

protected:
int send_single(utils::Header& header) override;
long recv_single(utils::Header& header) override;
bool create_header_send(utils::Header& header) override;
Comm_t* create_worker(utils::Address& address,
const DIRECTION& dir, int flgs) override;

/** \copydoc YggInterface::communicator::Comm_t::send_single */
int send_single(utils::Header& header) override;
/** \copydoc YggInterface::communicator::Comm_t::recv_single */
long recv_single(utils::Header& header) override;
/** \copydoc YggInterface::communicator::Comm_t::create_header_send */
bool create_header_send(utils::Header& header) override;
/** \copydoc YggInterface::communicator::Comm_t::create_worker */
Comm_t* create_worker(utils::Address& address,
const DIRECTION dir, int flgs) override;

};

}
Expand Down
32 changes: 23 additions & 9 deletions src/communicators/ClientComm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,43 @@ namespace YggInterface {
namespace communicator {

/**
* Client communicator class, associated with a ServerComm. Actual communicator type
* @brief Client communicator class, associated with a ServerComm.
* Actual communicator type
* is determined at compile time based on available packages. It will be either
* an IPCComm or ZMQComm
*/
class ClientComm : public RPCComm {
public:
/**
* Constructor
* @param name The name of the communicator
* @param address The address to associate with the communicator, if address is nullptr
* @brief Constructor
* @param[in] name The name of the communicator
* @param[in] address The address to associate with the communicator, if address is nullptr
* then an address will be created.
* @param flgs Bitwise flags describing the communicator
* @param[in] flgs Bitwise flags describing the communicator
* @see utils::Address
*/
explicit ClientComm(const std::string& name,
utils::Address &address,
int flgs = 0, const COMM_TYPE type = CLIENT_COMM);
utils::Address &address,
int flgs = 0, const COMM_TYPE type = CLIENT_COMM);
ADD_CONSTRUCTORS_RPC(ClientComm, CLIENT_COMM)

/**
* Destructor
*/
~ClientComm() override = default;
/** \copydoc YggInterface::communicator::Comm_t::set_timeout_recv */
void set_timeout_recv(int new_timeout) override;
/** \copydoc YggInterface::communicator::Comm_t::get_timeout_recv */
int get_timeout_recv() override;
/**
* @brief Connect the client to the server
* @param[in] header The header to use
* @param[in] async_comm The communicator to use
* @return True if successful
* @see utils::Header
*/
virtual bool signon(const utils::Header& header,
Comm_t* async_comm=nullptr);
Comm_t* async_comm=nullptr);

using RPCComm::send;
using RPCComm::recv;
Expand All @@ -40,10 +51,13 @@ class ClientComm : public RPCComm {
protected:
#endif
void init();
/** \copydoc YggInterface::communicator::Comm_t::create_worker_send */
Comm_t* create_worker_send(utils::Header& head) override;
/** \copydoc YggInterface::communicator::Comm_t::create_worker_recv */
Comm_t* create_worker_recv(utils::Header& head) override;
/** \copydoc YggInterface::communicator::Comm_t::create_header_send */
bool create_header_send(utils::Header& header) override;
/*! \copydoc Comm_t::recv_single */
/** \copydoc YggInterface::communicator::Comm_t::recv_single */
long recv_single(utils::Header& header) override;

#ifndef YGG_TEST
Expand Down
Loading

0 comments on commit 4818bf8

Please sign in to comment.