Operator implementation

You use skeleton template files that are generated by the spl-make-operator script as the basis for operator implementations.

Figure 1 shows the skeleton C++ header and implementation files.
Figure 1. Templates for operator implementation

Header file

<%SPL::CodeGen::headerPrologue($model);%>

class MY_OPERATOR : public MY_BASE_OPERATOR {
public:
  // constructor
  MY_OPERATOR();
  // destructor
  virtual ~MY_OPERATOR(); 
  // notify port readiness
  void allPortsReady();
  // notify termination
  void prepareToShutdown(); 
  // processing for source and threaded operators
  void process(uint32_t idx);
  // tuple processing for mutating ports 
  void process(Tuple & tuple, uint32_t port);
  // tuple processing for non-mutating ports
  void process(Tuple const & tuple, uint32_t port);
  // punctuation processing
  void process(Punctuation const & punct, uint32_t port);
};

<%SPL::CodeGen::headerEpilogue($model);%>

Implementation file

<%SPL::CodeGen::implementationPrologue($model);%>

MY_OPERATOR::MY_OPERATOR()
  : MY_BASE_OPERATOR() {}
MY_OPERATOR::~MY_OPERATOR() {}
void MY_OPERATOR::process(uint32_t idx) {}
void MY_OPERATOR::process(Tuple & tuple, uint32_t port) {}
void MY_OPERATOR::process(Tuple const & tuple, uint32_t port) {}
void MY_OPERATOR::process(Punctuation const & punct, uint32_t port) {}
void MY_OPERATOR::allPortsReady() {}
void MY_OPERATOR::prepareToShutdown() {}

<%SPL::CodeGen::implementationEpilogue($model);%>
The code listing in the figure shows the member functions of the operator that are commonly implemented. The name of the operator class always shows up as MY_OPERATOR in the code.
Table 1. SPL C++ type mappings

This table lists the Streams Processing Language (SPL) types and how those types map to C++ programming language types.

SPL type C++ type C++ base implementation C++ reflective type
boolean SPL::boolean bool N/A
blob SPL::blob N/A N/A
timestamp SPL::timestamp N/A N/A
(r|u)string SPL::(r|u)string std::string|icu::UnicodeString N/A
rstring SPL::rstring std::string

(on x86_64)

N/A
ustring SPL::ustring N/A N/A
u?int(8|16|32|64) SPL::u?int(8|16|32|64) u?int(8|16|32|64)_t N/A
float(32|64) SPL::float(32|64) (float|double) N/A
decimal(32|64|
128)
SPL::decimal(32|64|
128)
std::decimal::decimal(32|64|
128)
N/A
complex(32|64) SPL::complex(32|64) std::complex<float(32|64)> N/A
list<T> SPL::list<T> std::vector<T> SPL::List
set<T> SPL::set<T> std::tr1::unordered_set<T> SPL::Set
map<T,K> SPL::map<T,K> std::tr1::unordered_map<T,K> SPL::Map
rstring[N] SPL::bstring<N> N/A SPL::BString
list<T>[N] SPL::blist<T,N> N/A SPL::BList
set<T>[N] SPL::bset<T,N> N/A SPL::BSet
map<T,K>[N] SPL::bmap<T,K,N> N/A SPL::BMap
tuple generated N/A SPL::Tuple
enum generated N/A SPL::Enum
XML generated N/A SPL::xml

The header and implementation templates start and end with <%...%> segments. These segments contain prologue and epilogue code generation calls, namely headerPrologue and headerEpilogue, and their implementation counterparts implementationPrologue and imlementationEpilogue. These calls are used to generate code for header file includes, operator port typedefs, inclusion guards, etc. Non-generic operator implementors might opt to use C++ compliant alternatives:

#pragma SPL_NON_GENERIC_OPERATOR_HEADER_PROLOGUE
#pragma SPL_NON_GENERIC_OPERATOR_HEADER_EPILOGUE
#pragma SPL_NON_GENERIC_OPERATOR_IMPLEMENTATION_PROLOGUE
#pragma SPL_NON_GENERIC_OPERATOR_IMPLEMENTATION_EPILOGUE

The non-generic operator prologue and epilogue pragma ensure that any errors reported during the compilation of the generated code references the code generator templates, rather than the generated code. For non-generic operators, it is most likely the wanted behavior, as the code generator template contains only C++ code. These pragma also result in generation of helper member functions to easily access operator parameters for non-generic operators, as described. In summary, a non-generic operator implementation is free of any Perl code and can work with any C++ editor.

Before you get into the details of implementing operators, cover the basics of the SPL type system mappings for C++. For instance, the process member functions associated with input tuple processing have a tuple parameter of type Tuple as shown in Figure 1. The type Tuple is part of the SPL-specific C++ types.