Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
[submodule "third_party/thread-pool"]
path = third_party/thread-pool
url = https://github.com/bshoshany/thread-pool/
[submodule "third_party/spdlog"]
path = third_party/spdlog
url = https://github.com/gabime/spdlog.git
branch = v1.x
[submodule "third_party/doxygen-awesome-css"]
path = third_party/doxygen-awesome-css
url = https://github.com/jothepro/doxygen-awesome-css.git
[submodule "third_party/json"]
path = third_party/json
url = https://github.com/nlohmann/json.git
125 changes: 90 additions & 35 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,62 +11,80 @@ elseif(MSVC)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
endif()

find_package(nlohmann_json CONFIG QUIET)
if (NOT nlohmann_json_FOUND)
include(FetchContent)
FetchContent_Declare(
nlohmann_json OVERRIDE_FIND_PACKAGE
URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz
)
FetchContent_MakeAvailable(nlohmann_json)
# -----------------------------------------------------------------------------
# Dependencies
# -----------------------------------------------------------------------------

option(flow-core_US_EXTERNAL_JSON "Use an external JSON library" OFF)

if (flow-core_US_EXTERNAL_JSON)
find_package(nlohmann_json 3.11.3 REQUIRED)
endif()

add_subdirectory(third_party)

add_library(${PROJECT_NAME} SHARED
# -----------------------------------------------------------------------------
# Library
# -----------------------------------------------------------------------------

set(flow-core_HEADERS_DIR "${CMAKE_CURRENT_LIST_DIR}/include")
file(GLOB flow-core_HEADERS "${flow-core_HEADERS_DIR}/flow/core/*.hpp")
file(GLOB thread_pool_HEADERS "${thread_pool_SOURCE_DIR}/include/*.hpp")
list(APPEND ${flow-core_HEADERS} ${thread_pool_HEADERS})

add_library(flow-core SHARED
src/Connection.cpp
src/Connections.cpp
src/Env.cpp
src/Graph.cpp
src/Log.cpp
src/Node.cpp
src/NodeFactory.cpp
src/Port.cpp
src/TypeConversion.cpp
src/UUID.cpp

${flow-core_HEADERS}
)

target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${thread_pool_SOURCE_DIR}/include)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/flow/core)
add_library(flow-core::flow-core ALIAS flow-core)

target_include_directories(flow-core
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
${thread_pool_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/include/flow/core
)

if(MSVC)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
target_compile_options(${PROJECT_NAME} PRIVATE /W4)
target_link_libraries(${PROJECT_NAME} PUBLIC
nlohmann_json::nlohmann_json
spdlog::spdlog_header_only
)
elseif(APPLE)
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_link_libraries(${PROJECT_NAME} PUBLIC
"-framework CoreFoundation"
pthread

nlohmann_json::nlohmann_json
spdlog::spdlog_header_only
)
target_compile_options(flow-core PRIVATE /W4)
target_link_libraries(flow-core PUBLIC nlohmann_json::nlohmann_json)
else()
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_link_libraries(${PROJECT_NAME} PUBLIC
dl
pthread
uuid

nlohmann_json::nlohmann_json
spdlog::spdlog_header_only
)
target_compile_options(flow-core PRIVATE -Wall -Wextra -Wpedantic -Werror)
if(APPLE)
target_link_libraries(flow-core PUBLIC
"-framework CoreFoundation"
pthread

nlohmann_json::nlohmann_json
)
else()
target_link_libraries(flow-core PUBLIC
dl
pthread
uuid

nlohmann_json::nlohmann_json
)
endif()
endif()

# -----------------------------------------------------------------------------
# Tests
# -----------------------------------------------------------------------------

if (flow-core_BUILD_TESTS)
enable_testing()

Expand All @@ -85,3 +103,40 @@ if (flow-core_BUILD_TESTS)

add_subdirectory(tests)
endif()

# -----------------------------------------------------------------------------
# Install
# -----------------------------------------------------------------------------

if(flow-core_INSTALL)
set(export_destination "${CMAKE_INSTALL_LIBDIR}/cmake/flow-core")

# Install required headers
install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(DIRECTORY ${thread_pool_SOURCE_DIR}/include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")

install(TARGETS flow-core
EXPORT flow-core
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

export(TARGETS flow-core
NAMESPACE flow-core::
FILE "${CMAKE_CURRENT_BINARY_DIR}/flow-coreTargets.cmake"
)
install(EXPORT flow-core DESTINATION ${export_destination} NAMESPACE flow-core:: FILE "flow-coreTargets.cmake")

include(CMakePackageConfigHelpers)
configure_package_config_file(
"${CMAKE_CURRENT_LIST_DIR}/cmake/flow-coreConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/flow-coreConfig.cmake"
INSTALL_DESTINATION ${export_destination}
)

install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/flow-coreConfig.cmake"
DESTINATION ${export_destination}
)
endif()
8 changes: 8 additions & 0 deletions cmake/flow-coreConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)
find_dependency(Threads)

include("${CMAKE_CURRENT_LIST_DIR}/flow-coreTargets.cmake")

check_required_components(flow-core)
137 changes: 131 additions & 6 deletions include/flow/core/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "Connections.hpp"
#include "Core.hpp"
#include "Event.hpp"
#include "IndexableName.hpp"
#include "Node.hpp"

Expand All @@ -14,51 +15,175 @@

FLOW_NAMESPACE_START

/**
* @brief The core of the engine, holds nodes and their connections.
*/
class Graph
{
public:
/**
* @brief Alias for the function type pass to the Visit method.
*/
using VisitorFunction = std::function<void(const SharedNode&)>;

/**
* @brief Constructs a graph.
* @param name The name of the graph.
* @param env The shared environment.
*/
Graph(const std::string& name, std::shared_ptr<Env> env);

/**
* @brief Get a reference to the UUID of the Graph.
* @returns The UUID of the graph.
*/
const UUID& ID() const noexcept { return _id; }

/**
* @brief Runs compute on the source nodes of the graph, starting the flow.
*
* @details Finds all of the source nodes of the graph, and runs compute. The compute of the source nodes will then
* propagate through the rest of the graph and execute the entire flow.
*/
void Run();

/**
* @brief Visits each node int he graph breadth-wise.
* @param visitor The visitor function to run when visiting each node.
*
* @note This also visits orphan nodes.
*/
void Visit(const VisitorFunction& visitor);

/**
* @brief Adds a new node to the graph.
* @param node The node to be added.
*/
void AddNode(SharedNode node);

/**
* @brief Removes a given node form the graph.
* @param node The node to remove.
*/
void RemoveNode(const SharedNode& node);

/**
* @brief Removes a node from the graph by its UUID.
* @param uuid The UUID of the node.
*/
void RemoveNodeByID(const UUID& uuid);

/**
* @brief Get a node by its UUID.
* @param uuid The UUID of the node.
* @returns The node if found, nullptr otherwise.
*/
[[nodiscard]] SharedNode GetNode(const UUID& uuid) const;

/**
* @brief Get all connections for the graph.
* @returns All connections that have been made within the graph.
*/
[[nodiscard]] const Connections& GetConnections() const noexcept { return _connections; }

/**
* @brief Gets the size of the graph.
* @returns The total number of nodes in the graph.
*/
[[nodiscard]] std::size_t Size() const noexcept { return _nodes.size(); }

/**
* @brief Get the number of connections in the graph.
* @returns The total number of connections that have been made in the graph.
*/
[[nodiscard]] std::size_t ConnectionCount() const noexcept { return _connections.Size(); }

/**
* @brief Get the friendly name of the graph.
* @returns The set name of the graph.
*/
[[nodiscard]] const std::string& GetName() const noexcept { return _name; }

/**
* @brief Get a reference to the shared environment.
* @returns The shared environment pointer.
*/
[[nodiscard]] const std::shared_ptr<Env>& GetEnv() const noexcept { return _env; }

/**
* @brief Get all source nodes in the graph.
* @details Gets all source nodes. A source node is a node that has no or only output connections.
* @returns A list of all source nodes.
*/
[[nodiscard]] std::vector<SharedNode> GetSourceNodes() const;

/**
* @brief Get all leaf nodes in the graph.
* @details Gets all leaf nodes. A leaf node is a node that has at least one connection, and only input connections.
* @returns A list of all leaf nodes.
*/
[[nodiscard]] std::vector<SharedNode> GetLeafNodes() const;

/**
* @brief Get all orphan nodes in the graph.
* @details Gets all orphan nodes. A orphan node is a node that has no connections.
* @returns A list of all orphan nodes.
*/
[[nodiscard]] std::vector<SharedNode> GetOrphanNodes() const;

/**
* @brief Removes all connections and nodes from the graph.
*/
void Clear() noexcept { _connections.Clear(), _nodes.clear(); }

SharedConnection ConnectNodes(const UUID& in, const IndexableName& in_port_key, const UUID& out,
const IndexableName& out_port_key);

void DisconnectNodes(const UUID& in, const IndexableName& in_port_key, const UUID& out,
const IndexableName& out_port_key);

/**
* @brief Connects 2 nodes by their IDs and Port keys.
*
* @param start The node which has the output port.
* @param start_key The Port key of the output port on the starting node.
* @param end The node which takes in data as input.
* @param end_key The Port key of the input node on the end node.
*
* @returns The created connection.
*/
SharedConnection ConnectNodes(const UUID& start, const IndexableName& start_key, const UUID& end,
const IndexableName& end_key);

/**
* @brief Disconnects 2 nodes by their IDs and Port keys.
*
* @param start The node which has the output port.
* @param start_key The Port key of the output port on the starting node.
* @param end The node which takes in data as input.
* @param end_key The Port key of the input node on the end node.
*/
void DisconnectNodes(const UUID& start, const IndexableName& start_key, const UUID& end,
const IndexableName& end_key);

/**
* @brief Propagates data through the connections of the given ID.
*
* @param id The ID of the connection where the data came from.
* @param key The name of the port from which data is flowing.
* @param data The data to propagate.
*/
void PropagateConnectionsData(const UUID& id, const IndexableName& key, SharedNodeData data);

/**
* @brief Sets the name of the graph.
* @param new_name The new Name of the graph.
*/
void SetName(std::string new_name) noexcept { _name = std::move(new_name); }

friend void to_json(json& j, const Graph& g);
friend void from_json(const json& j, Graph& g);

public:
/**
* @brief Event run on Graph errors being thrown.
*/
EventDispatcher<const std::exception&> OnError;

protected:
mutable std::mutex _nodes_mutex;

Expand Down
Loading