In this issue, we recommend CGraph’s DAG scheduling framework without third-party dependencies. The logic of sequential execution by dependent nodes and concurrent execution without dependent nodes is implemented.
Brief introduction
This project implements a set of cross-platform graph process calculation framework. Through the underlying scheduling of GPipeline (pipeline), the scheduling function of sequential execution of dependent elements and concurrent execution of non-dependent elements is realized.
Users only need to inherit the GNode (node) class, implement the run() method of the subclass, and set dependencies as needed to realize the graphical execution of the task.
At the same time, users can also control the conditional judgment, loop, and concurrent execution logic of the graph by setting various GGroups (groups) that contain multi-node information.
In addition, the functions of the above elements can be horizontally expanded by adding GAspect, or the functions of a single node can be enhanced by introducing various GAdapters (adapters).
Compilation Notes
- This project supports MacOS, Linux and Windows systems, and does not depend on any third party. Developers who use CLion as an IDE can open the CMakeLists.txt file as a project and compile it
- Linux environment developers, in the command line mode, enter the following command to compile:
$ git clone https://github.com/ChunelFeng/CGraph.git
$ cd CGraph
$ cmake . -Bbuild
$ cd build
$ make
- Provides a Docker image based on Ubuntu 20.04.3 LTS. Enter the following command to get and enter
$ docker pull chunelfeng/cenv # Obtain the docker image
$ docker run -it --name CGraphEnv chunelfeng/cenv # Obtain the docker image
Use the demo
MyNode1.h
#include "../../src/CGraph.h"
class MyNode1 : public CGraph::GNode {
public:
CStatus run () override {
CStatus status;
CGraph::CGRAPH_ECHO("[%s], enter MyNode1 run function. Sleep for 1 second ... ", this->getName().c_str());
CGRAPH_SLEEP_SECOND(1)
return status;
}
};
MyNode2.h
#include "../../src/CGraph.h"
class MyNode2 : public CGraph::GNode {
public:
CStatus run () override {
CStatus status;
CGraph::CGRAPH_ECHO("[%s], enter MyNode2 run function. Sleep for 2 second ... ", this->getName().c_str());
CGRAPH_SLEEP_SECOND(2)
return status;
}
};
demo.cpp
#include "MyGNode/MyNode1.h"
#include "MyGNode/MyNode2.h"
using namespace CGraph;
void tutorial_simple() {
/*Create a pipeline to set up and execute flow diagram information */
GPipelinePtr pipeline = GPipelineFactory::create();
GElementPtr a, b, c, d = nullptr;
/* Register the node, where MyNode1 and MyNode2 must be subclasses of GNode, otherwise they will not pass compilation.
* The run() execution content in MyNode1 is sleep(1s)
* The run() execution content in MyNode2 is sleep(2s) */
CStatus status = pipeline->registerGElement<MyNode1>(&a, {}, "nodeA"); // Register node information named nodeA with no execution dependencies in the pipeline
status += pipeline->registerGElement<MyNode2>(&b, {a}, "nodeB"); // Register the node named nodeB that depends on the node executed by a in the pipeline
status += pipeline->registerGElement<MyNode1>(&c, {a}, "nodeC");
status += pipeline->registerGElement<MyNode2>(&d, {b, c}, "nodeD"); // Register the node named nodeD that depends on {b,c} to the pipeline
if (!status.isOK()) {
return; // When using it, check the return value of all CGraph interfaces
}
/* Execute the flow diagram framework */
status = pipeline->process();
GPipelineFactory::destroy(pipeline);
}
As shown in the preceding figure, when the graph structure is executed, node A is executed first. After node A is executed, nodes B and C are executed in parallel. After all nodes B and C are executed, run node D.