Skip to content
Marc edited this page Nov 13, 2017 · 1 revision

The Worker class

The Worker class is a class that allows to compile and execute code in c++ inside the platform.

This class is used to allow code generation at the moment and insert it at run time.

How it works

A new worker is defined as:

Worker<T, T1>(std::string header, std::string footer, std::string functionName,
         std::string commandLine, std::string path, bool deleteFiles = true)

were each parameter is:

  • T : The type of the return value
  • T1 : The types of the parameter values of the call.
  • header : The header to attach to the code (it must contain an extern "C"), for example
     "#include <vector>
      #include <exception>
      #include <stdexcept>
      #include <string>
      #include <algorithm>
      #include <iostream>
      #include <cstdlib>
      #include <ctime>
      #include \"Bundle/BundleInfo.h\"
      #include \"adtnPlus/Json.h\"
      #include \"adtnPlus/Worker.h\"
      extern \"C\" {
       const uint64_t g_timeFrom2000 = 946684800;
       using json = nlohmann::json;
       bool f(Json& ns, Json& bs, json bp) {"
  • footer : The footer to attach to the code (it must close the extern C and the function), for example
    "return true;}}"
  • functionName: The name of the function that will be loaded from the generated library, in this example f
  • commandLine : The command line used to generate the shared library (it will contain two %s, the first for the code file and the second for the library output name), for example
    "g++ -w -fPIC -shared -std=c++14 %s -Wl,--no-whole-archive -o %s -lpthread 2>&1"
  • path : The path to save the generated library and the auxiliary .cpp files.
  • deleteFiles : If set to true if will deleted all the generated files.

After define a worker you must call the

 void generateFunction(std::string code);

This call will generate the cpp and so file with all the given parameters, and attaching between the header and the footer the given code. It throws a WorkerException if for some reason the library has not been created.

When the code is already generated it can be executed with

void execute(Args &.. params);

This function takes the same arguments defined in T1, for example

 worker.execute(m_nodeState, bundleState, bundleProcessState);

This function executes the function asynchronous, so to retrieve the result you must call the

T getResult();

This returns the result of the execute call, returning the value of the type defined at T. If the function can not return a result a WorkerException is thrown.

Examples

Example 1

  std::string header = "extern \"C\" {int r(int& value) {"; // the header containing the signature of the function
  std::string footer = "}}"; // the footer with the closing brackets
  std::string commandLine = "g++ -w -fPIC -shared %s -o %s 2>&1"; // the compiling line 
  std::string code = "return value * 10;"; // the code to generate
  int val = 10;
  Worker<int, int> w(header, footer, "r", commandLine, "./"); // the worker definition
  w.generateFunction(code);
  w.execute(val);
  w.getResult(); // return 100

This example generates a simple function that takes an int as input parameters and returns an int.

The functions is as simple as returning the input value multiplied by 10.

Example 2

std::string header = "#include <string>\n"
      "#include <vector>\n"
      "#include <sstream>\n"
      "extern \"C\" {std::string r(std::vector<std::string> values) {";
  std::string footer = "}}";
  std::string commandLine = "g++ -w -fPIC -shared %s -o %s 2>&1";
  std::string code = "std::stringstream ss;"
      "for (int i = 0; i < values.size(); ++i) {"
      "  ss << values[i].at(0);}"
      "return ss.str();";

  Worker<std::string, std::vector<std::string>> w(header, footer, "r",
                                                  commandLine, "./");
  w.generateFunction(code);
  std::vector<std::string> params;
  params.push_back("This");
  params.push_back("Is");
  params.push_back("A");
  params.push_back("Test");
  w.execute(params);
  w.getResult(); // returns "TIAT"

This time a string and a vector<string> are used as input and return values.

Example 3

std::string header = "#include <string>\n"
      "#include <vector>\n"
      "extern \"C\" {int r(int& value, std::string val2, "
      "std::vector<std::string> value3) {";
  std::string footer = "}}";
  std::string commandLine = "g++ -w -fPIC -shared -std=c++11 %s -o %s 2>&1";
  std::string code = "int res = value;"
      "for (std::string s : value3) {"
      " res += std::stoi(s);"
      "}"
      "res += std::stoi(val2);"
      "return res;";

  Worker<int, int, std::string, std::vector<std::string>> w(header, footer, "r",
                                                            commandLine, "./");
  int value = 10;
  std::string val2 = "20";
  std::vector<std::string> params;
  params.push_back("10");
  params.push_back("20");
  params.push_back("30");
  params.push_back("40");
  w.generateFunction(code);
  w.execute(value, val2, params);
  w.getResult(); // return 130;

This example shows the use of multiple parameters of different types.

Clone this wiki locally