{"id":16812085,"url":"https://github.com/undeadkernel/anise_framework","last_synced_at":"2025-03-17T11:14:33.463Z","repository":{"id":22528174,"uuid":"25868745","full_name":"UndeadKernel/anise_framework","owner":"UndeadKernel","description":"Programming framework for the development and deployment of algorithms and tasks","archived":false,"fork":false,"pushed_at":"2015-11-16T12:30:37.000Z","size":12962,"stargazers_count":0,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-23T20:36:36.040Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UndeadKernel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-28T12:42:39.000Z","updated_at":"2015-04-22T11:57:22.000Z","dependencies_parsed_at":"2022-08-21T06:30:10.470Z","dependency_job_id":null,"html_url":"https://github.com/UndeadKernel/anise_framework","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UndeadKernel%2Fanise_framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UndeadKernel%2Fanise_framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UndeadKernel%2Fanise_framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UndeadKernel%2Fanise_framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UndeadKernel","download_url":"https://codeload.github.com/UndeadKernel/anise_framework/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244022724,"owners_count":20385134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T10:20:38.405Z","updated_at":"2025-03-17T11:14:33.423Z","avatar_url":"https://github.com/UndeadKernel.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ANISE Framework: Node Based Algorithm Programming Framework (for its acronym in Sindarin) #\n\nANISE is a C++ framework using the QT libraries for developing reusable, memory efficient and multi-threaded\ncapable algorithms in C++ without the need to worry excessively about memory management and multi-threading\nfor the GNU/Linux operating system. This framework is suitable for building small and efficient desktop\nalgorithms or large scale algorithms targeting a clustering environment, for instance.\n\n## ANISE Overview ##\n\n### Data Management ###\n\nThe framework provides an environment for developing algorithms as a series of interconnected nodes. Nodes are\nable to receive data from other nodes, process all the received data, and forward the processing results to\nother nodes. Each node is only responsible for managing its own memory; the data sent to other nodes is\nefficiently managed by the framework. The data is distributed using the CoW (Copy-on-Write) paradigm: The\nforwarded data is able to be read without incurring in any memory operations. The data, however, is copied\nwhenever it needs to be modified.\n\n### Automatic Multi-Threading ###\n\nEvery node runs in parallel, whenever it is possible, using as many kernel threads as the local system\nprovides. Nodes start processing data as soon as it is made available and can forward new data to other nodes.\n\n### Algorithm Reusability ###\n\nAlgorithms are able to be logically split into nodes that process incoming data and forward data to other\nnodes. A collection of nodes and how they are connected is known as a mesh. Nodes can be reused in multiple\nmeshes and contexts. Each node receives and forwards a particular (and predefined) type of data. As long as\nthe nodes receive the type of data they expect, they can be used in different meshes. This enables the\ncreation of reusable components that can be shared among different algorithms.\n\nNodes are built as standalone libraries that the ANISE framework incorporates. As such, the framework is a\nstandalone unit that incorporates external libraries (Nodes) to extend its functionality. Each Node is able to\nhave its own code-base and different compilation process.\n\n## ANISE Components ##\n\n![ANISE Components](http://undeadkernel.github.io/anise_images/components.png)\n\n### The Gate ###\n\n```c++\nclass CGate\n{\n    QString m_name;                               // A unique identifier of a gate.\n    QString m_msg_type;                           // The type of data that can be linked to the gate.\n    CNode *m_linked_Node;                         // The Node linked to this gate.\n    QList\u003cQSharedPpointer\u003cCGate\u003e\u003e m_linked_gates; // Gates this gate is linked to.\n};\n```\n\nNodes in the ANISE framework communicate by receiving and forwarding data among each other. Gates are the\nmeans by which Nodes connect to each other. A gate is identified by a *name*, *belongs to only one Node* and\nspecifies the *type of data* the gate can handle. Gates can only connect to other gates of the same type.\nAdditionally, a gate might be either an input or an output gate. Input gates can be connected to multiple\noutput gates and output gates might have multiple (different) input gates connected to them.\n\n### The Node ###\n\nNodes are the core of the ANISE framework. Each Node is a logical unit capable of receiving, processing and\nforwarding data to other Nodes. Each Node has a configuration component that specifies, among other things,\nthe input and output gates available to the Node. Input gates receive a predefined type of data and either\nforward it to the processing component of the Node or add it to a queue for later processing. Output gates are\nconnected to other Input gates (with a matching data type) and transmit the data forwarded by the processing\ncomponent of the Node.\n\n```c++\nclass CNodeConfig\n{\n    QString m_name;                                     // Unique identifier for the Node\n    Qstring m_description;                              // Description of the Node\n    QList\u003cSParameterTemplate\u003e m_parameter_template_map; // List of parameters\n    QList\u003cSGateTemplate\u003e m_input_tempaltes;             // List of gates\n    QList\u003cSGateTemplate\u003e m_output_templates;            // List of gates\n};\n```\n\nEach Node has a configuration (```class CNodeConfig```) that specifies different properties inherent to a\nNode. The developer of a Node is able to modify the configuration of the node by specifying the default name\nof the Node; a user-readable description of the Node; the input and output gates available to the Node; and\nthe parameters the Node expects. When using a Node, the user is not able to add or change the details of the\ngates, parameters or description. The user is, however, capable of changing the name of the node, assigning\nvalues to parameters and connecting output gates with other input gates.\n\n## Node Programming and Development ##\n\n### Building the Framework ###\n\nThe framework currently uses the QT 5.4.0 libraries. Before Nodes can be developed, the framework must be\ndownloaded and compiled. Download the framework with:\n```\n$ git clone https://github.com/UndeadKernel/anise_framework.git\n```\nThis will create a folder called 'anise_framework' in the current directory. The framework can be compiled\ninto either a debug or release mode. In debug mode, messages from the framework and all nodes are printed on\nthe screen detailed with the line and function where they were printed. Debugging symbols are also enabled.\nThe performance of the framework in **debug mode** is suboptimal and, as such, should only be used to debug\nNodes in development. On the contrary, the **release mode** suppresses most of the output messages and\nincreases and optimizes the framework for performance.\n\nCompile the framework with **debug mode** enabled with the following commands:\n```\n$ qmake CONFIG+=debug\n$ make\n```\nThe compiled framework will be created under the folder 'bin/debug/anise-framework'.\n\nCompile the framework in **release mode** with the following commands:\n```\n$ qmake CONFIG=+release\n$ make\n```\nThe compiled framework will be created under the folder 'bin/release/anise-framework'.\n\nThe previous commands will also compile the framework and all Nodes and Data structures also located in\n```src_nodes``` and ```src_data```, respectively.\n\nIn the same folder where the framework is built, two folders are also created (or must be created if they do\nnot exist). The folder *nodes* has all the nodes (in the form of .so libraries) that the framework will read\nand incorporate when started. Likewise, the folder *data* contains all the data structures the framework\nknows about and is able to use within Nodes.\n\n\n### Building the Framework with QT Creator ###\n\nThe framework can be easily compiled using QT Creator as well. Open the file **anids-framework.pro** and\nselect a build mode (either debug or release) and compile as usual. The same folder\n\nNodes can be developed using any IDE or programming toolchain. However, QT Creator enables an easy integration\nwith the framework for ease of development. If QT creator is used, building the framework i\n\n### Creating a New Node ###\n\nA Node can be developed by adding a new QT project folder in ```src_nodes``` and adding the corresponding\n'.pro' of the project to 'src_nodes.pro'. If this path for building Nodes is taken, when the framework is\nbuilt, as described in the previous section, the Node in development will also be compiled and automatically\nplaced where it needs to be. Otherwise, if chosen to develop the Node outside of QT creator, the Node must be\ncompiled as a library and placed in the **nodes* folder where the framework binary (*anise-framework*) is\nlocated.\n\nTo start developing a Node, copy the contents of 'src_nodes/skeleton' into a new folder and change the name of\nthe contents named *skeleton* to match the name of the node you have chosen. Keep the file extensions. A Node\nimplementation should look like:\n\n```c++\nclass CNewNode: public CNode\n{\n  Q_OBJECT\n\n  private:\n    // Data Structures\n\n  public:\n    // Constructor\n    explicit CNewNode(const CNodeConfig \u0026config, QObject *parent = 0);\n    // Set the configuration template for this Node.\n    static void configure(CNodeConfig \u0026config);\n\n  protected:\n    // Function called when the simulation is started.\n    virtual bool start();\n    // Receive data sent by other nodes connected to this node.\n    virtual void data(QString gate_name, const CConstDataPointer \u0026data);\n};\n```\n\nIt's the responsibility of the Node developer to implement 4 functions:\n1. The Node **constructor**\n2. The **configure** function\n3. The **start** function\n4. The **data** function\n\nThe requirements and purpose of these functions are described in the following subsections.\n\n#### The Node **constructor** ####\n\nThe constructor must call the ```CNode()``` parent class constructor as well. For example:\n```c++\nCNewNode::CNewNode(const CNodeConfig \u0026config, QObject *parent/* = 0*/)\n    : CNode(config, parent)\n{\n\n}\n```\n\n#### The **configure** Function ####\n\nThe configure function is where the node is setup to receive certain parameters, to create input and output\ngates, to set a default Node name and to set a user-readable Node description.\n\nThis is an example configure function that sets all these 4 options:\n```c++\nvoid CNewNode::configure(CNodeConfig \u0026config)\n{\n    config.setName(\"New\");\n    // Set a Description of this node.\n    config.setDescription(\"\");\n\n    // Add parameters\n    config.addFilename(\"file\", \"Input File\", \"File to be read from disk.\");\n\n    // Add the gates.\n    config.addInput(\"in\", \"table\");\n    config.addOutput(\"out\", \"table\");\n}\n```\n\n#### The **start** Function ####\n\nThis function is called only once when the framework is started for each instance of the Node being used in a\nmesh. Initialization of dynamic memory that should be used during the entire lifetime of the Node should be\nperformed here. The function returns *true* if all is well, oitherwise, the function returns *false* to\nindicate that something went wrong. If *false* is returned, the entire simulation is halted.\n\nIt's important to note that all Nodes are instantiated at the same time when a mesh in created.\n\nExample:\n```c++\nbool CNewNode::start()\n{\n    qDebug() \u003c\u003c \"Start called.\";\n    m_member_variable = new int[10000];\n    if(m_member_variable != nullptr)\n        return true;\n    else\n        return true;\n}\n```\n\n#### The **data** Function ####\nWhenever a Node forwards data to another Node the gate that picks up the forwarded data calls this function.\nThe function is called with the name of the gate that is calling this function as the first parameter, and\nwith the data the gate received as the second parameter.\n\nThis is where the node can do all the processing work in needs to be. After finishing processing data in this\nfunction, the resultant data can be forwarded to other nodes connected to the output gates of this Node. The\nfunction ```commit()``` is used to forward the data. The first parameter of this function specifies the name\nof the gate to output data from, the second parameter specifies the data we are sending out.\n\nExample:\n```c++\nvoid CNewNode::data(QString gate_name, const CConstDataPointer \u0026data)\n{\n    if(gate_name == \"input\") {\n        auto pmsg = data.staticCast\u003cconst CMessageData\u003e();\n        QString msg = pmsg-\u003egetMessage();\n        if(msg == \"start\") {\n            commit(\"out\", m_data);\n            // We can now clear the data so that it is freed\n            // ... when it is no longer being used.\n            m_data.clear();\n        }\n        else if(msg == \"error\") {\n            qCritical() \u003c\u003c \"Error found while processing data.\";\n            commitError(\"out\", \"Received an error.\");\n        }\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fundeadkernel%2Fanise_framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fundeadkernel%2Fanise_framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fundeadkernel%2Fanise_framework/lists"}