LCOV - code coverage report
Current view: top level - src/Runtime/Task - Task.cpp (source / functions) Hit Total Coverage
Test: streampu_clean.info Lines: 414 771 53.7 %
Date: 2024-07-31 15:48:41 Functions: 50 132 37.9 %

          Line data    Source code
       1             : #include <algorithm>
       2             : #include <iomanip>
       3             : #include <ios>
       4             : #include <iostream>
       5             : #include <rang.hpp>
       6             : #include <sstream>
       7             : #include <typeinfo>
       8             : 
       9             : #include "Module/Module.hpp"
      10             : #include "Runtime/Socket/Socket.hpp"
      11             : #include "Runtime/Task/Task.hpp"
      12             : #include "Tools/Exception/exception.hpp"
      13             : 
      14             : using namespace spu;
      15             : using namespace spu::runtime;
      16             : 
      17        3071 : Task::Task(module::Module& module,
      18             :            const std::string& name,
      19             :            const bool autoalloc,
      20             :            const bool stats,
      21             :            const bool fast,
      22        3071 :            const bool debug)
      23        3071 :   : module(&module)
      24        3071 :   , name(name)
      25        3071 :   , autoalloc(autoalloc)
      26        3071 :   , stats(stats)
      27        3071 :   , fast(fast)
      28        3071 :   , debug(debug)
      29        3071 :   , debug_hex(false)
      30        3071 :   , replicable(module.is_clonable())
      31        3071 :   , debug_limit(-1)
      32        3071 :   , debug_precision(2)
      33        3071 :   , debug_frame_max(-1)
      34        3071 :   , codelet(
      35           0 :       [](module::Module& m, Task& t, const size_t frame_id) -> int
      36             :       {
      37           0 :           throw tools::unimplemented_error(__FILE__, __LINE__, __func__);
      38             :           return 0;
      39             :       })
      40        3071 :   , n_input_sockets(0)
      41        3071 :   , n_output_sockets(0)
      42        3071 :   , n_fwd_sockets(0)
      43        3071 :   , status(module.get_n_waves())
      44        3071 :   , n_calls(0)
      45        3071 :   , duration_total(std::chrono::nanoseconds(0))
      46        3071 :   , duration_min(std::chrono::nanoseconds(0))
      47        3071 :   , duration_max(std::chrono::nanoseconds(0))
      48        9213 :   , last_input_socket(nullptr)
      49             : {
      50        3071 : }
      51             : 
      52             : Socket&
      53           0 : Task::operator[](const std::string& sck_name)
      54             : {
      55           0 :     std::string s_name = sck_name;
      56           0 :     s_name.erase(remove(s_name.begin(), s_name.end(), ' '), s_name.end());
      57             : 
      58           0 :     auto it = find_if(this->sockets.begin(),
      59             :                       this->sockets.end(),
      60           0 :                       [s_name](std::shared_ptr<runtime::Socket> s) { return s->get_name() == s_name; });
      61             : 
      62           0 :     if (it == this->sockets.end())
      63             :     {
      64           0 :         std::stringstream message;
      65           0 :         message << "runtime::Socket '" << s_name << "' not found for task '" << this->get_name() << "'.";
      66           0 :         throw tools::invalid_argument(__FILE__, __LINE__, __func__, message.str());
      67           0 :     }
      68             : 
      69           0 :     return *it->get();
      70           0 : }
      71             : 
      72             : void
      73       68794 : Task::set_autoalloc(const bool autoalloc)
      74             : {
      75       68794 :     if (autoalloc != this->autoalloc)
      76             :     {
      77           0 :         this->autoalloc = autoalloc;
      78             : 
      79           0 :         if (!autoalloc)
      80             :         {
      81           0 :             this->out_buffers.clear();
      82           0 :             for (auto& s : sockets)
      83           0 :                 if (s->get_type() == socket_t::SOUT && s->get_name() != "status") s->dataptr = nullptr;
      84             :         }
      85             :         else
      86             :         {
      87           0 :             for (auto& s : sockets)
      88           0 :                 if (s->get_type() == socket_t::SOUT && s->get_name() != "status")
      89             :                 {
      90           0 :                     out_buffers.push_back(buffer(s->databytes));
      91           0 :                     s->dataptr = out_buffers.back().data();
      92             :                 }
      93             :         }
      94             :     }
      95       68794 : }
      96             : 
      97             : void
      98       72292 : Task::set_stats(const bool stats)
      99             : {
     100       72292 :     this->stats = stats;
     101       72292 : }
     102             : 
     103             : void
     104       76488 : Task::set_fast(const bool fast)
     105             : {
     106       76488 :     this->fast = fast;
     107      277154 :     for (size_t i = 0; i < sockets.size(); i++)
     108      200666 :         sockets[i]->set_fast(this->fast);
     109       76488 : }
     110             : 
     111             : void
     112       72200 : Task::set_debug(const bool debug)
     113             : {
     114       72200 :     this->debug = debug;
     115       72200 : }
     116             : 
     117             : void
     118           0 : Task::set_debug_hex(const bool debug_hex)
     119             : {
     120           0 :     this->debug_hex = debug_hex;
     121           0 : }
     122             : 
     123             : void
     124       72200 : Task::set_debug_limit(const uint32_t limit)
     125             : {
     126       72200 :     this->debug_limit = (int32_t)limit;
     127       72200 : }
     128             : 
     129             : void
     130           0 : Task::set_debug_precision(const uint8_t prec)
     131             : {
     132           0 :     this->debug_precision = prec;
     133           0 : }
     134             : 
     135             : void
     136           0 : Task::set_debug_frame_max(const uint32_t limit)
     137             : {
     138           0 :     this->debug_frame_max = limit;
     139           0 : }
     140             : 
     141             : // trick to compile on the GNU compiler version 4 (where 'std::hexfloat' is unavailable)
     142             : #if !defined(__clang__) && !defined(__llvm__) && defined(__GNUC__) && defined(__cplusplus) && __GNUC__ < 5
     143             : namespace std
     144             : {
     145             : class Hexfloat
     146             : {
     147             :   public:
     148             :     void message(std::ostream& os) const { os << " /!\\ 'std::hexfloat' is not supported by this compiler. /!\\ "; }
     149             : };
     150             : Hexfloat hexfloat;
     151             : }
     152             : std::ostream&
     153             : operator<<(std::ostream& os, const std::Hexfloat& obj)
     154             : {
     155             :     obj.message(os);
     156             :     return os;
     157             : }
     158             : #endif
     159             : 
     160             : template<typename T>
     161             : static inline void
     162         397 : display_data(const T* data,
     163             :              const size_t fra_size,
     164             :              const size_t n_fra,
     165             :              const size_t n_fra_per_w,
     166             :              const size_t limit,
     167             :              const size_t max_frame,
     168             :              const uint8_t p,
     169             :              const uint8_t n_spaces,
     170             :              const bool hex)
     171             : {
     172         397 :     constexpr bool is_float_type = std::is_same<float, T>::value || std::is_same<double, T>::value;
     173             : 
     174         397 :     std::ios::fmtflags f(std::cout.flags());
     175         397 :     if (hex)
     176             :     {
     177             :         if (is_float_type)
     178           0 :             std::cout << std::hexfloat << std::hex;
     179             :         else
     180           0 :             std::cout << std::hex;
     181             :     }
     182             :     else
     183         397 :         std::cout << std::fixed << std::setprecision(p) << std::dec;
     184             : 
     185         397 :     if (n_fra == 1 && max_frame != 0)
     186             :     {
     187        5531 :         for (size_t i = 0; i < limit; i++)
     188             :         {
     189        5133 :             if (hex)
     190           0 :                 std::cout << (!is_float_type ? "0x" : "") << +data[i] << (i < limit - 1 ? ", " : "");
     191             :             else
     192        5133 :                 std::cout << std::setw(p + 3) << +data[i] << (i < limit - 1 ? ", " : "");
     193             :         }
     194         398 :         std::cout << (limit < fra_size ? ", ..." : "");
     195         397 :     }
     196             :     else
     197             :     {
     198           0 :         std::string spaces = "#";
     199           0 :         for (uint8_t s = 0; s < n_spaces - 1; s++)
     200           0 :             spaces += " ";
     201             : 
     202           0 :         auto n_digits_dec = [](size_t f) -> size_t
     203             :         {
     204           0 :             size_t count = 0;
     205           0 :             while (f && ++count)
     206           0 :                 f /= 10;
     207           0 :             return count;
     208             :         };
     209             : 
     210           0 :         const auto n_digits = n_digits_dec(max_frame);
     211           0 :         auto ftos = [&n_digits_dec, &n_digits](size_t f) -> std::string
     212             :         {
     213           0 :             auto n_zero = n_digits - n_digits_dec(f);
     214           0 :             std::string f_str = "";
     215           0 :             for (size_t z = 0; z < n_zero; z++)
     216           0 :                 f_str += "0";
     217           0 :             f_str += std::to_string(f);
     218           0 :             return f_str;
     219           0 :         };
     220             : 
     221           0 :         const auto n_digits_w = n_digits_dec((max_frame / n_fra_per_w) == 0 ? 1 : (max_frame / n_fra_per_w));
     222           0 :         auto wtos = [&n_digits_dec, &n_digits_w](size_t w) -> std::string
     223             :         {
     224           0 :             auto n_zero = n_digits_w - n_digits_dec(w);
     225           0 :             std::string f_str = "";
     226           0 :             for (size_t z = 0; z < n_zero; z++)
     227           0 :                 f_str += "0";
     228           0 :             f_str += std::to_string(w);
     229           0 :             return f_str;
     230           0 :         };
     231             : 
     232           0 :         for (size_t f = 0; f < max_frame; f++)
     233             :         {
     234           0 :             const auto w = f / n_fra_per_w;
     235           0 :             std::cout << (f >= 1 ? spaces : "") << rang::style::bold << rang::fg::gray << "f" << ftos(f + 1) << "_w"
     236           0 :                       << wtos(w + 1) << rang::style::reset << "(";
     237             : 
     238           0 :             for (size_t i = 0; i < limit; i++)
     239             :             {
     240           0 :                 if (hex)
     241           0 :                     std::cout << (!is_float_type ? "0x" : "") << +data[f * fra_size + i] << (i < limit - 1 ? ", " : "");
     242             :                 else
     243           0 :                     std::cout << std::setw(p + 3) << +data[f * fra_size + i] << (i < limit - 1 ? ", " : "");
     244             :             }
     245           0 :             std::cout << (limit < fra_size ? ", ..." : "") << ")" << (f < n_fra - 1 ? ", \n" : "");
     246             :         }
     247             : 
     248           0 :         if (max_frame < n_fra)
     249             :         {
     250           0 :             const auto w1 = max_frame / n_fra_per_w;
     251           0 :             const auto w2 = n_fra / n_fra_per_w;
     252           0 :             std::cout << (max_frame >= 1 ? spaces : "") << rang::style::bold << rang::fg::gray << "f"
     253           0 :                       << std::setw(n_digits) << max_frame + 1 << "_w" << std::setw(n_digits_w) << w1 + 1 << "->"
     254           0 :                       << "f" << std::setw(n_digits) << n_fra << "_w" << std::setw(n_digits_w) << w2 + 1 << ":"
     255           0 :                       << rang::style::reset << "(...)";
     256             :         }
     257           0 :     }
     258             : 
     259         397 :     std::cout.flags(f);
     260         397 : }
     261             : 
     262             : void
     263     3158993 : Task::_exec(const int frame_id, const bool managed_memory)
     264             : {
     265     3158993 :     const auto n_frames = this->get_module().get_n_frames();
     266     3132617 :     const auto n_frames_per_wave = this->get_module().get_n_frames_per_wave();
     267     3100787 :     const auto n_waves = this->get_module().get_n_waves();
     268     3070396 :     const auto n_frames_per_wave_rest = this->get_module().get_n_frames_per_wave_rest();
     269             : 
     270             :     // do not use 'this->status' because the dataptr can have been changed by the 'tools::Sequence' when using the no
     271             :     // copy mode
     272     3049560 :     int* status = this->sockets.back()->get_dataptr<int>();
     273     7591029 :     for (size_t w = 0; w < n_waves; w++)
     274     4719515 :         status[w] = (int)status_t::UNKNOWN;
     275             : 
     276     2871514 :     if ((managed_memory == false && frame_id >= 0) || (frame_id == -1 && n_frames_per_wave == n_frames) ||
     277      170496 :         (frame_id == 0 && n_frames_per_wave == 1) || (frame_id == 0 && n_waves > 1) ||
     278           0 :         (frame_id == 0 && n_frames_per_wave_rest == 0))
     279             :     {
     280     2704783 :         const auto real_frame_id = frame_id == -1 ? 0 : frame_id;
     281     2704783 :         const size_t w = (real_frame_id % n_frames) / n_frames_per_wave;
     282     2704783 :         status[w] = this->codelet(*this->module, *this, real_frame_id);
     283     2929772 :     }
     284             :     else
     285             :     {
     286             :         // save the initial dataptr of the sockets
     287      471979 :         for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
     288      300666 :             sockets_dataptr_init[sid] = (int8_t*)this->sockets[sid]->_get_dataptr();
     289             : 
     290      170079 :         if (frame_id > 0 && managed_memory == true && n_frames_per_wave > 1)
     291             :         {
     292           0 :             const size_t w = (frame_id % n_frames) / n_frames_per_wave;
     293           0 :             const size_t w_pos = frame_id % n_frames_per_wave;
     294             : 
     295           0 :             for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
     296             :             {
     297           0 :                 if (sockets[sid]->get_type() == socket_t::SIN || sockets[sid]->get_type() == socket_t::SFWD)
     298           0 :                     std::copy(
     299           0 :                       sockets_dataptr_init[sid] + ((frame_id % n_frames) + 0) * sockets_databytes_per_frame[sid],
     300           0 :                       sockets_dataptr_init[sid] + ((frame_id % n_frames) + 1) * sockets_databytes_per_frame[sid],
     301           0 :                       sockets_data[sid].begin() + w_pos * sockets_databytes_per_frame[sid]);
     302           0 :                 this->sockets[sid]->dataptr = (void*)sockets_data[sid].data();
     303             :             }
     304             : 
     305           0 :             status[w] = this->codelet(*this->module, *this, w * n_frames_per_wave);
     306             : 
     307           0 :             for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
     308           0 :                 if (sockets[sid]->get_type() == socket_t::SOUT || sockets[sid]->get_type() == socket_t::SFWD)
     309           0 :                     std::copy(sockets_data[sid].begin() + (w_pos + 0) * sockets_databytes_per_frame[sid],
     310           0 :                               sockets_data[sid].begin() + (w_pos + 1) * sockets_databytes_per_frame[sid],
     311           0 :                               sockets_dataptr_init[sid] + (frame_id % n_frames) * sockets_databytes_per_frame[sid]);
     312           0 :         }
     313             :         else // if (frame_id <= 0 || n_frames_per_wave == 1)
     314             :         {
     315      170079 :             const size_t w_start = (frame_id < 0) ? 0 : frame_id % n_waves;
     316      170079 :             const size_t w_stop = (frame_id < 0) ? n_waves : w_start + 1;
     317             : 
     318      170079 :             size_t w = 0;
     319      170079 :             auto exec_status = status_t::SUCCESS;
     320     1746207 :             for (w = w_start; w < w_stop - 1 && exec_status != status_t::FAILURE_STOP; w++)
     321             :             {
     322     4353747 :                 for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
     323     2745442 :                     this->sockets[sid]->dataptr =
     324     5515173 :                       (void*)(sockets_dataptr_init[sid] + w * n_frames_per_wave * sockets_databytes_per_frame[sid]);
     325             : 
     326     1281211 :                 status[w] = this->codelet(*this->module, *this, w * n_frames_per_wave);
     327     1576128 :                 exec_status = (status_t)status[w];
     328             :             }
     329             : 
     330      169859 :             if (exec_status != status_t::FAILURE_STOP)
     331             :             {
     332      169208 :                 if (n_frames_per_wave_rest == 0)
     333             :                 {
     334      472295 :                     for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
     335      301927 :                         this->sockets[sid]->dataptr =
     336      604684 :                           (void*)(sockets_dataptr_init[sid] + w * n_frames_per_wave * sockets_databytes_per_frame[sid]);
     337             : 
     338      162279 :                     status[w] = this->codelet(*this->module, *this, w * n_frames_per_wave);
     339             :                 }
     340             :                 else
     341             :                 {
     342           0 :                     for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
     343             :                     {
     344           0 :                         if (sockets[sid]->get_type() == socket_t::SIN || sockets[sid]->get_type() == socket_t::SFWD)
     345           0 :                             std::copy(sockets_dataptr_init[sid] +
     346           0 :                                         w * n_frames_per_wave * sockets_databytes_per_frame[sid],
     347           0 :                                       sockets_dataptr_init[sid] + n_frames * sockets_databytes_per_frame[sid],
     348           0 :                                       sockets_data[sid].begin());
     349           0 :                         this->sockets[sid]->dataptr = (void*)sockets_data[sid].data();
     350             :                     }
     351             : 
     352           0 :                     status[w] = this->codelet(*this->module, *this, w * n_frames_per_wave);
     353             : 
     354           0 :                     for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
     355         747 :                         if (sockets[sid]->get_type() == socket_t::SOUT || sockets[sid]->get_type() == socket_t::SFWD)
     356           0 :                             std::copy(
     357           0 :                               sockets_data[sid].begin(),
     358           0 :                               sockets_data[sid].begin() + n_frames_per_wave_rest * sockets_databytes_per_frame[sid],
     359           0 :                               sockets_dataptr_init[sid] + w * n_frames_per_wave * sockets_databytes_per_frame[sid]);
     360             :                 }
     361             :             }
     362             :         }
     363             : 
     364             :         // restore the initial dataptr of the sockets
     365      470265 :         for (size_t sid = 0; sid < this->sockets.size() - 1; sid++)
     366      301195 :             this->sockets[sid]->dataptr = (void*)sockets_dataptr_init[sid];
     367             :     }
     368     3092580 : }
     369             : 
     370             : const std::vector<int>&
     371     3090765 : Task::exec(const int frame_id, const bool managed_memory)
     372             : {
     373             : #ifndef SPU_FAST
     374     3090765 :     if (this->is_fast() && !this->is_debug() && !this->is_stats())
     375             :     {
     376             : #endif
     377     3092598 :         this->_exec(frame_id, managed_memory);
     378     3071228 :         this->n_calls++;
     379     3071228 :         return this->get_status();
     380             : #ifndef SPU_FAST
     381             :     }
     382             : 
     383        5279 :     if (frame_id != -1 && (size_t)frame_id >= this->get_module().get_n_frames())
     384             :     {
     385           0 :         std::stringstream message;
     386           0 :         message << "'frame_id' has to be equal to '-1' or to be smaller than 'n_frames' ('frame_id' = " << frame_id
     387           0 :                 << ", 'n_frames' = " << this->get_module().get_n_frames() << ").";
     388           0 :         throw tools::length_error(__FILE__, __LINE__, __func__, message.str());
     389           0 :     }
     390             : 
     391        7893 :     if (this->is_fast() || this->can_exec())
     392             :     {
     393        7887 :         size_t max_n_chars = 0;
     394        7887 :         if (this->is_debug())
     395             :         {
     396         329 :             auto n_fra = this->module->get_n_frames();
     397         329 :             auto n_fra_per_w = this->module->get_n_frames_per_wave();
     398             : 
     399             :             std::string module_name =
     400         329 :               module->get_custom_name().empty() ? module->get_name() : module->get_custom_name();
     401             : 
     402         329 :             std::cout << "# ";
     403         329 :             std::cout << rang::style::bold << rang::fg::green << module_name << rang::style::reset
     404         329 :                       << "::" << rang::style::bold << rang::fg::magenta << get_name() << rang::style::reset << "(";
     405         728 :             for (auto i = 0; i < (int)sockets.size() - 1; i++)
     406             :             {
     407         399 :                 auto& s = *sockets[i];
     408         399 :                 auto s_type = s.get_type();
     409         399 :                 auto n_elmts = s.get_databytes() / (size_t)s.get_datatype_size();
     410         399 :                 std::cout << rang::style::bold << rang::fg::blue << (s_type == socket_t::SIN ? "const " : "")
     411         399 :                           << s.get_datatype_string() << rang::style::reset << " " << s.get_name() << "["
     412         798 :                           << (n_fra > 1 ? std::to_string(n_fra) + "x" : "") << (n_elmts / n_fra) << "]"
     413         399 :                           << (i < (int)sockets.size() - 2 ? ", " : "");
     414             : 
     415         399 :                 max_n_chars = std::max(s.get_name().size(), max_n_chars);
     416             :             }
     417         329 :             std::cout << ")" << std::endl;
     418             : 
     419        1057 :             for (auto& s : sockets)
     420             :             {
     421         728 :                 auto s_type = s->get_type();
     422         728 :                 if (s_type == socket_t::SIN || s_type == socket_t::SFWD)
     423             :                 {
     424         215 :                     std::string spaces;
     425         343 :                     for (size_t ss = 0; ss < max_n_chars - s->get_name().size(); ss++)
     426         128 :                         spaces += " ";
     427             : 
     428         215 :                     auto n_elmts = s->get_databytes() / (size_t)s->get_datatype_size();
     429         215 :                     auto fra_size = n_elmts / n_fra;
     430         215 :                     auto limit = debug_limit != -1 ? std::min(fra_size, (size_t)debug_limit) : fra_size;
     431         215 :                     auto max_frame = debug_frame_max != -1 ? std::min(n_fra, (size_t)debug_frame_max) : n_fra;
     432         215 :                     auto p = debug_precision;
     433         215 :                     auto h = debug_hex;
     434         215 :                     std::cout << "# {IN}  " << s->get_name() << spaces << " = [";
     435         215 :                     if (s->get_datatype() == typeid(int8_t))
     436           0 :                         display_data(s->get_dataptr<const int8_t>(),
     437             :                                      fra_size,
     438             :                                      n_fra,
     439             :                                      n_fra_per_w,
     440             :                                      limit,
     441             :                                      max_frame,
     442             :                                      p,
     443           0 :                                      (uint8_t)max_n_chars + 12,
     444             :                                      h);
     445         215 :                     else if (s->get_datatype() == typeid(uint8_t))
     446         170 :                         display_data(s->get_dataptr<const uint8_t>(),
     447             :                                      fra_size,
     448             :                                      n_fra,
     449             :                                      n_fra_per_w,
     450             :                                      limit,
     451             :                                      max_frame,
     452             :                                      p,
     453         170 :                                      (uint8_t)max_n_chars + 12,
     454             :                                      h);
     455          45 :                     else if (s->get_datatype() == typeid(int16_t))
     456           0 :                         display_data(s->get_dataptr<const int16_t>(),
     457             :                                      fra_size,
     458             :                                      n_fra,
     459             :                                      n_fra_per_w,
     460             :                                      limit,
     461             :                                      max_frame,
     462             :                                      p,
     463           0 :                                      (uint8_t)max_n_chars + 12,
     464             :                                      h);
     465          45 :                     else if (s->get_datatype() == typeid(uint16_t))
     466           0 :                         display_data(s->get_dataptr<const uint16_t>(),
     467             :                                      fra_size,
     468             :                                      n_fra,
     469             :                                      n_fra_per_w,
     470             :                                      limit,
     471             :                                      max_frame,
     472             :                                      p,
     473           0 :                                      (uint8_t)max_n_chars + 12,
     474             :                                      h);
     475          45 :                     else if (s->get_datatype() == typeid(int32_t))
     476           0 :                         display_data(s->get_dataptr<const int32_t>(),
     477             :                                      fra_size,
     478             :                                      n_fra,
     479             :                                      n_fra_per_w,
     480             :                                      limit,
     481             :                                      max_frame,
     482             :                                      p,
     483           0 :                                      (uint8_t)max_n_chars + 12,
     484             :                                      h);
     485          45 :                     else if (s->get_datatype() == typeid(uint32_t))
     486          27 :                         display_data(s->get_dataptr<const uint32_t>(),
     487             :                                      fra_size,
     488             :                                      n_fra,
     489             :                                      n_fra_per_w,
     490             :                                      limit,
     491             :                                      max_frame,
     492             :                                      p,
     493          27 :                                      (uint8_t)max_n_chars + 12,
     494             :                                      h);
     495          18 :                     else if (s->get_datatype() == typeid(int64_t))
     496           0 :                         display_data(s->get_dataptr<const int64_t>(),
     497             :                                      fra_size,
     498             :                                      n_fra,
     499             :                                      n_fra_per_w,
     500             :                                      limit,
     501             :                                      max_frame,
     502             :                                      p,
     503           0 :                                      (uint8_t)max_n_chars + 12,
     504             :                                      h);
     505          18 :                     else if (s->get_datatype() == typeid(uint64_t))
     506          18 :                         display_data(s->get_dataptr<const uint64_t>(),
     507             :                                      fra_size,
     508             :                                      n_fra,
     509             :                                      n_fra_per_w,
     510             :                                      limit,
     511             :                                      max_frame,
     512             :                                      p,
     513          18 :                                      (uint8_t)max_n_chars + 12,
     514             :                                      h);
     515           0 :                     else if (s->get_datatype() == typeid(float))
     516           0 :                         display_data(s->get_dataptr<const float>(),
     517             :                                      fra_size,
     518             :                                      n_fra,
     519             :                                      n_fra_per_w,
     520             :                                      limit,
     521             :                                      max_frame,
     522             :                                      p,
     523           0 :                                      (uint8_t)max_n_chars + 12,
     524             :                                      h);
     525           0 :                     else if (s->get_datatype() == typeid(double))
     526           0 :                         display_data(s->get_dataptr<const double>(),
     527             :                                      fra_size,
     528             :                                      n_fra,
     529             :                                      n_fra_per_w,
     530             :                                      limit,
     531             :                                      max_frame,
     532             :                                      p,
     533           0 :                                      (uint8_t)max_n_chars + 12,
     534             :                                      h);
     535         215 :                     std::cout << "]" << std::endl;
     536         215 :                 }
     537             :             }
     538         329 :         }
     539             : 
     540        7880 :         if (this->is_stats())
     541             :         {
     542        7523 :             auto t_start = std::chrono::steady_clock::now();
     543        7524 :             this->_exec(frame_id, managed_memory);
     544        7416 :             auto duration = std::chrono::steady_clock::now() - t_start;
     545             : 
     546        7422 :             this->duration_total += duration;
     547        7415 :             if (n_calls)
     548             :             {
     549        7024 :                 this->duration_min = std::min(this->duration_min, duration);
     550        7020 :                 this->duration_max = std::max(this->duration_max, duration);
     551             :             }
     552             :             else
     553             :             {
     554         391 :                 this->duration_min = duration;
     555         391 :                 this->duration_max = duration;
     556             :             }
     557             :         }
     558             :         else
     559             :         {
     560         357 :             this->_exec(frame_id, managed_memory);
     561             :         }
     562        7758 :         this->n_calls++;
     563             : 
     564        7758 :         if (this->is_debug())
     565             :         {
     566         326 :             auto n_fra = this->module->get_n_frames();
     567         326 :             auto n_fra_per_w = this->module->get_n_frames_per_wave();
     568        1045 :             for (auto& s : sockets)
     569             :             {
     570         720 :                 auto s_type = s->get_type();
     571         719 :                 if ((s_type == socket_t::SOUT) && s->get_name() != "status")
     572             :                 {
     573         182 :                     std::string spaces;
     574         200 :                     for (size_t ss = 0; ss < max_n_chars - s->get_name().size(); ss++)
     575          18 :                         spaces += " ";
     576             : 
     577         182 :                     auto n_elmts = s->get_databytes() / (size_t)s->get_datatype_size();
     578         182 :                     auto fra_size = n_elmts / n_fra;
     579         182 :                     auto limit = debug_limit != -1 ? std::min(fra_size, (size_t)debug_limit) : fra_size;
     580         182 :                     auto max_frame = debug_frame_max != -1 ? std::min(n_fra, (size_t)debug_frame_max) : n_fra;
     581         182 :                     auto p = debug_precision;
     582         182 :                     auto h = debug_hex;
     583         182 :                     std::cout << "# {OUT} " << s->get_name() << spaces << " = [";
     584         182 :                     if (s->get_datatype() == typeid(int8_t))
     585           0 :                         display_data(s->get_dataptr<const int8_t>(),
     586             :                                      fra_size,
     587             :                                      n_fra,
     588             :                                      n_fra_per_w,
     589             :                                      limit,
     590             :                                      max_frame,
     591             :                                      p,
     592           0 :                                      (uint8_t)max_n_chars + 12,
     593             :                                      h);
     594         182 :                     else if (s->get_datatype() == typeid(uint8_t))
     595         146 :                         display_data(s->get_dataptr<const uint8_t>(),
     596             :                                      fra_size,
     597             :                                      n_fra,
     598             :                                      n_fra_per_w,
     599             :                                      limit,
     600             :                                      max_frame,
     601             :                                      p,
     602         146 :                                      (uint8_t)max_n_chars + 12,
     603             :                                      h);
     604          36 :                     else if (s->get_datatype() == typeid(int16_t))
     605           0 :                         display_data(s->get_dataptr<const int16_t>(),
     606             :                                      fra_size,
     607             :                                      n_fra,
     608             :                                      n_fra_per_w,
     609             :                                      limit,
     610             :                                      max_frame,
     611             :                                      p,
     612           0 :                                      (uint8_t)max_n_chars + 12,
     613             :                                      h);
     614          36 :                     else if (s->get_datatype() == typeid(uint16_t))
     615           0 :                         display_data(s->get_dataptr<const uint16_t>(),
     616             :                                      fra_size,
     617             :                                      n_fra,
     618             :                                      n_fra_per_w,
     619             :                                      limit,
     620             :                                      max_frame,
     621             :                                      p,
     622           0 :                                      (uint8_t)max_n_chars + 12,
     623             :                                      h);
     624          36 :                     else if (s->get_datatype() == typeid(int32_t))
     625           0 :                         display_data(s->get_dataptr<const int32_t>(),
     626             :                                      fra_size,
     627             :                                      n_fra,
     628             :                                      n_fra_per_w,
     629             :                                      limit,
     630             :                                      max_frame,
     631             :                                      p,
     632           0 :                                      (uint8_t)max_n_chars + 12,
     633             :                                      h);
     634          36 :                     else if (s->get_datatype() == typeid(uint32_t))
     635          18 :                         display_data(s->get_dataptr<const uint32_t>(),
     636             :                                      fra_size,
     637             :                                      n_fra,
     638             :                                      n_fra_per_w,
     639             :                                      limit,
     640             :                                      max_frame,
     641             :                                      p,
     642          18 :                                      (uint8_t)max_n_chars + 12,
     643             :                                      h);
     644          18 :                     else if (s->get_datatype() == typeid(int64_t))
     645           0 :                         display_data(s->get_dataptr<const int64_t>(),
     646             :                                      fra_size,
     647             :                                      n_fra,
     648             :                                      n_fra_per_w,
     649             :                                      limit,
     650             :                                      max_frame,
     651             :                                      p,
     652           0 :                                      (uint8_t)max_n_chars + 12,
     653             :                                      h);
     654          18 :                     else if (s->get_datatype() == typeid(uint64_t))
     655          18 :                         display_data(s->get_dataptr<const uint64_t>(),
     656             :                                      fra_size,
     657             :                                      n_fra,
     658             :                                      n_fra_per_w,
     659             :                                      limit,
     660             :                                      max_frame,
     661             :                                      p,
     662          18 :                                      (uint8_t)max_n_chars + 12,
     663             :                                      h);
     664           0 :                     else if (s->get_datatype() == typeid(float))
     665           0 :                         display_data(s->get_dataptr<const float>(),
     666             :                                      fra_size,
     667             :                                      n_fra,
     668             :                                      n_fra_per_w,
     669             :                                      limit,
     670             :                                      max_frame,
     671             :                                      p,
     672           0 :                                      (uint8_t)max_n_chars + 12,
     673             :                                      h);
     674           0 :                     else if (s->get_datatype() == typeid(double))
     675           0 :                         display_data(s->get_dataptr<const double>(),
     676             :                                      fra_size,
     677             :                                      n_fra,
     678             :                                      n_fra_per_w,
     679             :                                      limit,
     680             :                                      max_frame,
     681             :                                      p,
     682           0 :                                      (uint8_t)max_n_chars + 12,
     683             :                                      h);
     684         182 :                     std::cout << "]" << std::endl;
     685         182 :                 }
     686             :             }
     687         325 :             std::cout << "# Returned status: [";
     688             :             // do not use 'this->status' because the dataptr can have been changed by the 'tools::Sequence' when using
     689             :             // the no copy mode
     690         326 :             int* status = this->sockets.back()->get_dataptr<int>();
     691         652 :             for (size_t w = 0; w < this->get_module().get_n_waves(); w++)
     692             :             {
     693         326 :                 if (status_t_to_string.count(status[w]))
     694         326 :                     std::cout << ((w != 0) ? ", " : "") << std::dec << status[w] << " '"
     695         326 :                               << status_t_to_string[status[w]] << "'";
     696             :                 else
     697           0 :                     std::cout << ((w != 0) ? ", " : "") << std::dec << status[w];
     698             :             }
     699         326 :             std::cout << "]" << std::endl;
     700         326 :             std::cout << "#" << std::noshowbase << std::endl;
     701             :         }
     702             : 
     703             :         // if (exec_status < 0)
     704             :         // {
     705             :         //  std::stringstream message;
     706             :         //  message << "'exec_status' can't be negative ('exec_status' = " << exec_status << ").";
     707             :         //  throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     708             :         // }
     709             : 
     710        7754 :         return this->get_status();
     711             :     }
     712             :     else
     713             :     {
     714           0 :         std::stringstream socs;
     715           0 :         socs << "'socket(s).name' = [";
     716           0 :         auto s = 0;
     717           0 :         for (size_t i = 0; i < sockets.size(); i++)
     718           0 :             if (sockets[i]->dataptr == nullptr) socs << (s != 0 ? ", " : "") << sockets[i]->name;
     719           0 :         socs << "]";
     720             : 
     721           0 :         std::stringstream message;
     722             :         message << "The task cannot be executed because some of the inputs/output sockets are not fed ('task.name' = "
     723           0 :                 << this->get_name() << ", 'module.name' = " << module->get_name() << ", " << socs.str() << ").";
     724           0 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     725           0 :     }
     726             : #endif /* !SPU_FAST */
     727             : }
     728             : 
     729             : template<typename T>
     730             : Socket&
     731        7630 : Task::create_2d_socket(const std::string& name,
     732             :                        const size_t n_rows,
     733             :                        const size_t n_cols,
     734             :                        const socket_t type,
     735             :                        const bool hack_status)
     736             : {
     737        7630 :     if (name.empty())
     738             :     {
     739           0 :         std::stringstream message;
     740             :         message << "Impossible to create this socket because the name is empty ('task.name' = " << this->get_name()
     741           0 :                 << ", 'module.name' = " << module->get_name() << ").";
     742           0 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     743           0 :     }
     744             : 
     745        7630 :     if (name == "status" && !hack_status)
     746             :     {
     747           0 :         std::stringstream message;
     748           0 :         message << "A socket can't be named 'status'.";
     749           0 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     750           0 :     }
     751             : 
     752       14313 :     for (auto& s : sockets)
     753        6683 :         if (s->get_name() == name)
     754             :         {
     755           0 :             std::stringstream message;
     756             :             message << "Impossible to create this socket because an other socket has the same name ('socket.name' = "
     757           0 :                     << name << ", 'task.name' = " << this->get_name() << ", 'module.name' = " << module->get_name()
     758           0 :                     << ").";
     759           0 :             throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     760           0 :         }
     761             : 
     762       14313 :     for (auto s : this->sockets)
     763        6683 :         if (s->get_name() == "status")
     764             :         {
     765           0 :             std::stringstream message;
     766           0 :             message << "Creating new sockets after the 'status' socket is forbidden.";
     767           0 :             throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     768           0 :         }
     769             : 
     770        7630 :     std::pair<size_t, size_t> databytes_per_dim = { n_rows, n_cols * sizeof(T) };
     771        7630 :     auto s = std::make_shared<Socket>(*this, name, typeid(T), databytes_per_dim, type, this->is_fast());
     772             : 
     773        7630 :     sockets.push_back(std::move(s));
     774             : 
     775        7630 :     this->sockets_dataptr_init.push_back(nullptr);
     776        7630 :     this->sockets_databytes_per_frame.push_back(sockets.back()->get_databytes() / this->get_module().get_n_frames());
     777        7630 :     this->sockets_data.push_back(
     778       15260 :       std::vector<int8_t>((this->get_module().get_n_frames_per_wave() > 1)
     779           0 :                             ? this->sockets_databytes_per_frame.back() * this->get_module().get_n_frames_per_wave()
     780             :                             : 0));
     781             : 
     782       15260 :     return *sockets.back();
     783        7630 : }
     784             : 
     785             : template<typename T>
     786             : size_t
     787        1862 : Task::create_2d_socket_in(const std::string& name, const size_t n_rows, const size_t n_cols)
     788             : {
     789        1862 :     auto& s = create_2d_socket<T>(name, n_rows, n_cols, socket_t::SIN);
     790        1862 :     last_input_socket = &s;
     791             : 
     792        1862 :     this->n_input_sockets++;
     793             : 
     794        1862 :     return sockets.size() - 1;
     795             : }
     796             : 
     797             : size_t
     798         611 : Task::create_2d_socket_in(const std::string& name,
     799             :                           const size_t n_rows,
     800             :                           const size_t n_cols,
     801             :                           const std::type_index& datatype)
     802             : {
     803         611 :     if (datatype == typeid(int8_t))
     804          66 :         return this->template create_2d_socket_in<int8_t>(name, n_rows, n_cols);
     805         545 :     else if (datatype == typeid(uint8_t))
     806         418 :         return this->template create_2d_socket_in<uint8_t>(name, n_rows, n_cols);
     807         127 :     else if (datatype == typeid(int16_t))
     808           0 :         return this->template create_2d_socket_in<int16_t>(name, n_rows, n_cols);
     809         127 :     else if (datatype == typeid(uint16_t))
     810           0 :         return this->template create_2d_socket_in<uint16_t>(name, n_rows, n_cols);
     811         127 :     else if (datatype == typeid(int32_t))
     812          27 :         return this->template create_2d_socket_in<int32_t>(name, n_rows, n_cols);
     813         100 :     else if (datatype == typeid(uint32_t))
     814          84 :         return this->template create_2d_socket_in<uint32_t>(name, n_rows, n_cols);
     815          16 :     else if (datatype == typeid(int64_t))
     816           0 :         return this->template create_2d_socket_in<int64_t>(name, n_rows, n_cols);
     817          16 :     else if (datatype == typeid(uint64_t))
     818          16 :         return this->template create_2d_socket_in<uint64_t>(name, n_rows, n_cols);
     819           0 :     else if (datatype == typeid(float))
     820           0 :         return this->template create_2d_socket_in<float>(name, n_rows, n_cols);
     821           0 :     else if (datatype == typeid(double))
     822           0 :         return this->template create_2d_socket_in<double>(name, n_rows, n_cols);
     823             :     else
     824             :     {
     825           0 :         std::stringstream message;
     826           0 :         message << "This should never happen.";
     827           0 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     828           0 :     }
     829             : }
     830             : 
     831             : size_t
     832           0 : Task::create_2d_socket_in(const std::string& name, const size_t n_rows, const size_t n_cols, const datatype_t datatype)
     833             : {
     834           0 :     switch (datatype)
     835             :     {
     836           0 :         case datatype_t::F64:
     837           0 :             return this->template create_2d_socket_in<double>(name, n_rows, n_cols);
     838             :             break;
     839           0 :         case datatype_t::F32:
     840           0 :             return this->template create_2d_socket_in<float>(name, n_rows, n_cols);
     841             :             break;
     842           0 :         case datatype_t::S64:
     843           0 :             return this->template create_2d_socket_in<int64_t>(name, n_rows, n_cols);
     844             :             break;
     845           0 :         case datatype_t::S32:
     846           0 :             return this->template create_2d_socket_in<int32_t>(name, n_rows, n_cols);
     847             :             break;
     848           0 :         case datatype_t::S16:
     849           0 :             return this->template create_2d_socket_in<int16_t>(name, n_rows, n_cols);
     850             :             break;
     851           0 :         case datatype_t::S8:
     852           0 :             return this->template create_2d_socket_in<int8_t>(name, n_rows, n_cols);
     853             :             break;
     854           0 :         case datatype_t::U64:
     855           0 :             return this->template create_2d_socket_in<uint64_t>(name, n_rows, n_cols);
     856             :             break;
     857           0 :         case datatype_t::U32:
     858           0 :             return this->template create_2d_socket_in<uint32_t>(name, n_rows, n_cols);
     859             :             break;
     860           0 :         case datatype_t::U16:
     861           0 :             return this->template create_2d_socket_in<uint16_t>(name, n_rows, n_cols);
     862             :             break;
     863           0 :         case datatype_t::U8:
     864           0 :             return this->template create_2d_socket_in<uint8_t>(name, n_rows, n_cols);
     865             :             break;
     866           0 :         default:
     867             :         {
     868           0 :             std::stringstream message;
     869           0 :             message << "This should never happen.";
     870           0 :             throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     871             :             break;
     872           0 :         }
     873             :     }
     874             : }
     875             : 
     876             : template<typename T>
     877             : size_t
     878        4821 : Task::create_2d_socket_out(const std::string& name, const size_t n_rows, const size_t n_cols, const bool hack_status)
     879             : {
     880        4821 :     auto& s = create_2d_socket<T>(name, n_rows, n_cols, socket_t::SOUT, hack_status);
     881        4821 :     this->n_output_sockets++;
     882             : 
     883             :     // memory allocation
     884        4821 :     if (is_autoalloc())
     885             :     {
     886        4821 :         out_buffers.push_back(buffer(s.get_databytes()));
     887        4821 :         s.dataptr = out_buffers.back().data(); // memory allocation
     888             :     }
     889             : 
     890        4821 :     return sockets.size() - 1;
     891             : }
     892             : 
     893             : size_t
     894         606 : Task::create_2d_socket_out(const std::string& name,
     895             :                            const size_t n_rows,
     896             :                            const size_t n_cols,
     897             :                            const std::type_index& datatype,
     898             :                            const bool hack_status)
     899             : {
     900         606 :     if (datatype == typeid(int8_t))
     901          61 :         return this->template create_2d_socket_out<int8_t>(name, n_rows, n_cols, hack_status);
     902         545 :     else if (datatype == typeid(uint8_t))
     903         418 :         return this->template create_2d_socket_out<uint8_t>(name, n_rows, n_cols, hack_status);
     904         127 :     else if (datatype == typeid(int16_t))
     905           0 :         return this->template create_2d_socket_out<int16_t>(name, n_rows, n_cols, hack_status);
     906         127 :     else if (datatype == typeid(uint16_t))
     907           0 :         return this->template create_2d_socket_out<uint16_t>(name, n_rows, n_cols, hack_status);
     908         127 :     else if (datatype == typeid(int32_t))
     909          27 :         return this->template create_2d_socket_out<int32_t>(name, n_rows, n_cols, hack_status);
     910         100 :     else if (datatype == typeid(uint32_t))
     911          84 :         return this->template create_2d_socket_out<uint32_t>(name, n_rows, n_cols, hack_status);
     912          16 :     else if (datatype == typeid(int64_t))
     913           0 :         return this->template create_2d_socket_out<int64_t>(name, n_rows, n_cols, hack_status);
     914          16 :     else if (datatype == typeid(uint64_t))
     915          16 :         return this->template create_2d_socket_out<uint64_t>(name, n_rows, n_cols, hack_status);
     916           0 :     else if (datatype == typeid(float))
     917           0 :         return this->template create_2d_socket_out<float>(name, n_rows, n_cols, hack_status);
     918           0 :     else if (datatype == typeid(double))
     919           0 :         return this->template create_2d_socket_out<double>(name, n_rows, n_cols, hack_status);
     920             :     else
     921             :     {
     922           0 :         std::stringstream message;
     923           0 :         message << "This should never happen.";
     924           0 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     925           0 :     }
     926             : }
     927             : 
     928             : size_t
     929           0 : Task::create_2d_socket_out(const std::string& name,
     930             :                            const size_t n_rows,
     931             :                            const size_t n_cols,
     932             :                            const datatype_t datatype,
     933             :                            const bool hack_status)
     934             : {
     935           0 :     switch (datatype)
     936             :     {
     937           0 :         case datatype_t::F64:
     938           0 :             return this->template create_2d_socket_out<double>(name, n_rows, n_cols, hack_status);
     939             :             break;
     940           0 :         case datatype_t::F32:
     941           0 :             return this->template create_2d_socket_out<float>(name, n_rows, n_cols, hack_status);
     942             :             break;
     943           0 :         case datatype_t::S64:
     944           0 :             return this->template create_2d_socket_out<int64_t>(name, n_rows, n_cols, hack_status);
     945             :             break;
     946           0 :         case datatype_t::S32:
     947           0 :             return this->template create_2d_socket_out<int32_t>(name, n_rows, n_cols, hack_status);
     948             :             break;
     949           0 :         case datatype_t::S16:
     950           0 :             return this->template create_2d_socket_out<int16_t>(name, n_rows, n_cols, hack_status);
     951             :             break;
     952           0 :         case datatype_t::S8:
     953           0 :             return this->template create_2d_socket_out<int8_t>(name, n_rows, n_cols, hack_status);
     954             :             break;
     955           0 :         case datatype_t::U64:
     956           0 :             return this->template create_2d_socket_out<uint64_t>(name, n_rows, n_cols, hack_status);
     957             :             break;
     958           0 :         case datatype_t::U32:
     959           0 :             return this->template create_2d_socket_out<uint32_t>(name, n_rows, n_cols, hack_status);
     960             :             break;
     961           0 :         case datatype_t::U16:
     962           0 :             return this->template create_2d_socket_out<uint16_t>(name, n_rows, n_cols, hack_status);
     963             :             break;
     964           0 :         case datatype_t::U8:
     965           0 :             return this->template create_2d_socket_out<uint8_t>(name, n_rows, n_cols, hack_status);
     966             :             break;
     967           0 :         default:
     968             :         {
     969           0 :             std::stringstream message;
     970           0 :             message << "This should never happen.";
     971           0 :             throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
     972             :             break;
     973           0 :         }
     974             :     }
     975             : }
     976             : 
     977             : template<typename T>
     978             : size_t
     979         947 : Task::create_2d_socket_fwd(const std::string& name, const size_t n_rows, const size_t n_cols)
     980             : {
     981         947 :     auto& s = create_2d_socket<T>(name, n_rows, n_cols, socket_t::SFWD);
     982         947 :     last_input_socket = &s;
     983             : 
     984         947 :     this->n_fwd_sockets++;
     985             : 
     986         947 :     return sockets.size() - 1;
     987             : }
     988             : 
     989             : size_t
     990           0 : Task::create_2d_socket_fwd(const std::string& name,
     991             :                            const size_t n_rows,
     992             :                            const size_t n_cols,
     993             :                            const std::type_index& datatype)
     994             : {
     995           0 :     if (datatype == typeid(int8_t))
     996           0 :         return this->template create_2d_socket_fwd<int8_t>(name, n_rows, n_cols);
     997           0 :     else if (datatype == typeid(uint8_t))
     998           0 :         return this->template create_2d_socket_fwd<uint8_t>(name, n_rows, n_cols);
     999           0 :     else if (datatype == typeid(int16_t))
    1000           0 :         return this->template create_2d_socket_fwd<int16_t>(name, n_rows, n_cols);
    1001           0 :     else if (datatype == typeid(uint16_t))
    1002           0 :         return this->template create_2d_socket_fwd<uint16_t>(name, n_rows, n_cols);
    1003           0 :     else if (datatype == typeid(int32_t))
    1004           0 :         return this->template create_2d_socket_fwd<int32_t>(name, n_rows, n_cols);
    1005           0 :     else if (datatype == typeid(uint32_t))
    1006           0 :         return this->template create_2d_socket_fwd<uint32_t>(name, n_rows, n_cols);
    1007           0 :     else if (datatype == typeid(int64_t))
    1008           0 :         return this->template create_2d_socket_fwd<int64_t>(name, n_rows, n_cols);
    1009           0 :     else if (datatype == typeid(uint64_t))
    1010           0 :         return this->template create_2d_socket_fwd<uint64_t>(name, n_rows, n_cols);
    1011           0 :     else if (datatype == typeid(float))
    1012           0 :         return this->template create_2d_socket_fwd<float>(name, n_rows, n_cols);
    1013           0 :     else if (datatype == typeid(double))
    1014           0 :         return this->template create_2d_socket_fwd<double>(name, n_rows, n_cols);
    1015             :     else
    1016             :     {
    1017           0 :         std::stringstream message;
    1018           0 :         message << "This should never happen.";
    1019           0 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
    1020           0 :     }
    1021             : }
    1022             : 
    1023             : size_t
    1024           0 : Task::create_2d_socket_fwd(const std::string& name, const size_t n_rows, const size_t n_cols, const datatype_t datatype)
    1025             : {
    1026           0 :     switch (datatype)
    1027             :     {
    1028           0 :         case datatype_t::F64:
    1029           0 :             return this->template create_2d_socket_fwd<double>(name, n_rows, n_cols);
    1030             :             break;
    1031           0 :         case datatype_t::F32:
    1032           0 :             return this->template create_2d_socket_fwd<float>(name, n_rows, n_cols);
    1033             :             break;
    1034           0 :         case datatype_t::S64:
    1035           0 :             return this->template create_2d_socket_fwd<int64_t>(name, n_rows, n_cols);
    1036             :             break;
    1037           0 :         case datatype_t::S32:
    1038           0 :             return this->template create_2d_socket_fwd<int32_t>(name, n_rows, n_cols);
    1039             :             break;
    1040           0 :         case datatype_t::S16:
    1041           0 :             return this->template create_2d_socket_fwd<int16_t>(name, n_rows, n_cols);
    1042             :             break;
    1043           0 :         case datatype_t::S8:
    1044           0 :             return this->template create_2d_socket_fwd<int8_t>(name, n_rows, n_cols);
    1045             :             break;
    1046           0 :         case datatype_t::U64:
    1047           0 :             return this->template create_2d_socket_fwd<uint64_t>(name, n_rows, n_cols);
    1048             :             break;
    1049           0 :         case datatype_t::U32:
    1050           0 :             return this->template create_2d_socket_fwd<uint32_t>(name, n_rows, n_cols);
    1051             :             break;
    1052           0 :         case datatype_t::U16:
    1053           0 :             return this->template create_2d_socket_fwd<uint16_t>(name, n_rows, n_cols);
    1054             :             break;
    1055           0 :         case datatype_t::U8:
    1056           0 :             return this->template create_2d_socket_fwd<uint8_t>(name, n_rows, n_cols);
    1057             :             break;
    1058           0 :         default:
    1059             :         {
    1060           0 :             std::stringstream message;
    1061           0 :             message << "This should never happen.";
    1062           0 :             throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
    1063             :             break;
    1064           0 :         }
    1065             :     }
    1066             : }
    1067             : 
    1068             : void
    1069        3071 : Task::create_codelet(std::function<int(module::Module& m, Task& t, const size_t frame_id)>& codelet)
    1070             : {
    1071        3071 :     this->codelet = codelet;
    1072             : 
    1073             :     // create automatically a socket that contains the status of the task
    1074        3071 :     const bool hack_status = true;
    1075        3071 :     auto s = this->template create_2d_socket_out<int>("status", 1, this->get_module().get_n_waves(), hack_status);
    1076        3071 :     this->sockets[s]->dataptr = (void*)this->status.data();
    1077        3071 : }
    1078             : 
    1079             : void
    1080       79568 : Task::update_n_frames(const size_t old_n_frames, const size_t new_n_frames)
    1081             : {
    1082       79568 :     size_t sout_id = 0;
    1083      285210 :     for (auto& s : this->sockets)
    1084             :     {
    1085      205642 :         if (s->get_name() == "status")
    1086             :         {
    1087       79568 :             if (this->get_module().get_n_waves() * sizeof(int) != s->get_databytes())
    1088             :             {
    1089       70452 :                 s->set_databytes(this->get_module().get_n_waves() * sizeof(int));
    1090       70452 :                 this->status.resize(this->get_module().get_n_waves());
    1091       70452 :                 s->set_dataptr((void*)this->status.data());
    1092             :             }
    1093             :         }
    1094             :         else
    1095             :         {
    1096      126074 :             const auto old_databytes = s->get_databytes();
    1097      126074 :             const auto new_databytes = (old_databytes / old_n_frames) * new_n_frames;
    1098      126074 :             s->set_databytes(new_databytes);
    1099             : 
    1100      126074 :             const size_t prev_n_rows_wo_nfra = s->get_n_rows() / old_n_frames;
    1101      126074 :             s->set_n_rows(prev_n_rows_wo_nfra * new_n_frames);
    1102             : 
    1103      126074 :             if (this->is_autoalloc() && s->get_type() == socket_t::SOUT)
    1104             :             {
    1105       49836 :                 this->out_buffers[sout_id].resize(new_databytes);
    1106       49836 :                 s->set_dataptr((void*)this->out_buffers[sout_id].data());
    1107       49836 :                 sout_id++;
    1108             :             }
    1109             :         }
    1110             :     }
    1111       79568 : }
    1112             : 
    1113             : void
    1114       18232 : Task::update_n_frames_per_wave(const size_t old_n_frames_per_wave, const size_t new_n_frames_per_wave)
    1115             : {
    1116       18232 :     size_t s_id = 0;
    1117       74452 :     for (auto& s : this->sockets)
    1118             :     {
    1119       56220 :         if (s->get_name() == "status")
    1120             :         {
    1121       18232 :             if (this->get_module().get_n_waves() * sizeof(int) != s->get_databytes())
    1122             :             {
    1123        9116 :                 s->set_databytes(this->get_module().get_n_waves() * sizeof(int));
    1124        9116 :                 this->status.resize(this->get_module().get_n_waves());
    1125        9116 :                 s->set_dataptr((void*)this->status.data());
    1126             :             }
    1127             :         }
    1128             :         else
    1129             :         {
    1130       56982 :             this->sockets_data[s_id].resize(
    1131       18994 :               (new_n_frames_per_wave > 1) ? this->sockets_databytes_per_frame[s_id] * new_n_frames_per_wave : 0);
    1132             :         }
    1133       56220 :         s_id++;
    1134             :     }
    1135       18232 : }
    1136             : 
    1137             : bool
    1138         360 : Task::can_exec() const
    1139             : {
    1140        1429 :     for (size_t i = 0; i < sockets.size(); i++)
    1141        1053 :         if (sockets[i]->dataptr == nullptr) return false;
    1142         358 :     return true;
    1143             : }
    1144             : 
    1145             : std::chrono::nanoseconds
    1146        7376 : Task::get_duration_total() const
    1147             : {
    1148        7376 :     return this->duration_total;
    1149             : }
    1150             : 
    1151             : std::chrono::nanoseconds
    1152        1126 : Task::get_duration_avg() const
    1153             : {
    1154        1126 :     return this->duration_total / this->n_calls;
    1155             : }
    1156             : 
    1157             : std::chrono::nanoseconds
    1158        1042 : Task::get_duration_min() const
    1159             : {
    1160        1042 :     return this->duration_min;
    1161             : }
    1162             : 
    1163             : std::chrono::nanoseconds
    1164        1042 : Task::get_duration_max() const
    1165             : {
    1166        1042 :     return this->duration_max;
    1167             : }
    1168             : 
    1169             : const std::vector<std::string>&
    1170         272 : Task::get_timers_name() const
    1171             : {
    1172         272 :     return this->timers_name;
    1173             : }
    1174             : 
    1175             : const std::vector<uint32_t>&
    1176           0 : Task::get_timers_n_calls() const
    1177             : {
    1178           0 :     return this->timers_n_calls;
    1179             : }
    1180             : 
    1181             : const std::vector<std::chrono::nanoseconds>&
    1182           0 : Task::get_timers_total() const
    1183             : {
    1184           0 :     return this->timers_total;
    1185             : }
    1186             : 
    1187             : const std::vector<std::chrono::nanoseconds>&
    1188           0 : Task::get_timers_min() const
    1189             : {
    1190           0 :     return this->timers_min;
    1191             : }
    1192             : 
    1193             : const std::vector<std::chrono::nanoseconds>&
    1194           0 : Task::get_timers_max() const
    1195             : {
    1196           0 :     return this->timers_max;
    1197             : }
    1198             : 
    1199             : size_t
    1200        2435 : Task::get_n_input_sockets() const
    1201             : {
    1202        2435 :     return this->n_input_sockets;
    1203             : }
    1204             : 
    1205             : size_t
    1206           0 : Task::get_n_output_sockets() const
    1207             : {
    1208           0 :     return this->n_output_sockets;
    1209             : }
    1210             : 
    1211             : size_t
    1212        3584 : Task::get_n_fwd_sockets() const
    1213             : {
    1214        3584 :     return this->n_fwd_sockets;
    1215             : }
    1216             : 
    1217             : void
    1218           0 : Task::register_timer(const std::string& name)
    1219             : {
    1220           0 :     this->timers_name.push_back(name);
    1221           0 :     this->timers_n_calls.push_back(0);
    1222           0 :     this->timers_total.push_back(std::chrono::nanoseconds(0));
    1223           0 :     this->timers_max.push_back(std::chrono::nanoseconds(0));
    1224           0 :     this->timers_min.push_back(std::chrono::nanoseconds(0));
    1225           0 : }
    1226             : 
    1227             : void
    1228       72292 : Task::reset()
    1229             : {
    1230       72292 :     this->n_calls = 0;
    1231       72292 :     this->duration_total = std::chrono::nanoseconds(0);
    1232       72292 :     this->duration_min = std::chrono::nanoseconds(0);
    1233       72292 :     this->duration_max = std::chrono::nanoseconds(0);
    1234             : 
    1235       72292 :     for (auto& x : this->timers_n_calls)
    1236           0 :         x = 0;
    1237       72292 :     for (auto& x : this->timers_total)
    1238           0 :         x = std::chrono::nanoseconds(0);
    1239       72292 :     for (auto& x : this->timers_min)
    1240           0 :         x = std::chrono::nanoseconds(0);
    1241       72292 :     for (auto& x : this->timers_max)
    1242           0 :         x = std::chrono::nanoseconds(0);
    1243       72292 : }
    1244             : 
    1245             : Task*
    1246       66987 : Task::clone() const
    1247             : {
    1248       66987 :     Task* t = new Task(*this);
    1249       66987 :     t->sockets.clear();
    1250       66987 :     t->last_input_socket = nullptr;
    1251       66987 :     t->fake_input_sockets.clear();
    1252             : 
    1253       66987 :     size_t out_buffers_counter = 0;
    1254      241956 :     for (auto s : this->sockets)
    1255             :     {
    1256      174969 :         void* dataptr = nullptr;
    1257      174969 :         if (s->get_type() == socket_t::SOUT && this->is_autoalloc())
    1258             :         {
    1259      109951 :             if (s->get_name() == "status")
    1260             :             {
    1261       66987 :                 dataptr = (void*)t->status.data();
    1262       66987 :                 out_buffers_counter++;
    1263             :             }
    1264             :             else
    1265       42964 :                 dataptr = (void*)t->out_buffers[out_buffers_counter++].data();
    1266             :         }
    1267       65018 :         else if (s->get_type() == socket_t::SIN || s->get_type() == socket_t::SFWD)
    1268       65018 :             dataptr = s->_get_dataptr();
    1269             : 
    1270      174969 :         const std::pair<size_t, size_t> databytes_per_dim = { s->get_n_rows(), s->get_databytes() / s->get_n_rows() };
    1271             :         auto s_new = std::shared_ptr<Socket>(
    1272      174969 :           new Socket(*t, s->get_name(), s->get_datatype(), databytes_per_dim, s->get_type(), s->is_fast(), dataptr));
    1273      174969 :         t->sockets.push_back(s_new);
    1274             : 
    1275      174969 :         if (s_new->get_type() == socket_t::SIN || s_new->get_type() == socket_t::SFWD)
    1276       65018 :             t->last_input_socket = s_new.get();
    1277      174969 :     }
    1278             : 
    1279       66987 :     return t;
    1280             : }
    1281             : 
    1282             : void
    1283        9240 : Task::_bind(Socket& s_out, const int priority)
    1284             : {
    1285             :     // check if the 's_out' socket is already used for an other fake input socket
    1286        9240 :     bool already_bound = false;
    1287        9240 :     for (auto& fsi : this->fake_input_sockets)
    1288           0 :         if (&fsi->get_bound_socket() == &s_out)
    1289             :         {
    1290           0 :             already_bound = true;
    1291           0 :             break;
    1292             :         }
    1293             : 
    1294             :     // check if the 's_out' socket is already used for an other read input/fwd socket
    1295        9240 :     if (!already_bound)
    1296       28130 :         for (auto& s : this->sockets)
    1297       18890 :             if (s->get_type() == socket_t::SIN || s->get_type() == socket_t::SFWD)
    1298             :             {
    1299             :                 try // because 's->get_bound_socket()' can throw if s->bound_socket == 'nullptr'
    1300             :                 {
    1301        1547 :                     if (&s->get_bound_socket() == &s_out)
    1302             :                     {
    1303           0 :                         already_bound = true;
    1304           0 :                         break;
    1305             :                     }
    1306             :                 }
    1307         692 :                 catch (...)
    1308             :                 {
    1309         692 :                 }
    1310             :             }
    1311             : 
    1312             :     // if the s_out socket is not already bound, then create a new fake input socket
    1313        9240 :     if (!already_bound)
    1314             :     {
    1315        9240 :         this->fake_input_sockets.push_back(
    1316       18480 :           std::shared_ptr<Socket>(new Socket(*this,
    1317       18480 :                                              "fake" + std::to_string(this->fake_input_sockets.size()),
    1318        9240 :                                              s_out.get_datatype(),
    1319        9240 :                                              s_out.get_databytes(),
    1320             :                                              socket_t::SIN,
    1321        9240 :                                              this->is_fast())));
    1322        9240 :         this->fake_input_sockets.back()->_bind(s_out, priority);
    1323        9240 :         this->last_input_socket = this->fake_input_sockets.back().get();
    1324        9240 :         this->n_input_sockets++;
    1325             :     }
    1326        9240 : }
    1327             : 
    1328             : void
    1329           0 : Task::bind(Socket& s_out, const int priority)
    1330             : {
    1331             : #ifdef SPU_SHOW_DEPRECATED
    1332             :     std::clog << rang::tag::warning << "Deprecated: 'Task::bind()' should be replaced by 'Task::operator='."
    1333             :               << std::endl;
    1334             : #ifdef SPU_STACKTRACE
    1335             : #ifdef SPU_COLORS
    1336             :     bool enable_color = true;
    1337             : #else
    1338             :     bool enable_color = false;
    1339             : #endif
    1340             :     cpptrace::generate_trace().print(std::clog, enable_color);
    1341             : #endif
    1342             : #endif
    1343           0 :     this->_bind(s_out, priority);
    1344           0 : }
    1345             : 
    1346             : void
    1347           0 : Task::_bind(Task& t_out, const int priority)
    1348             : {
    1349           0 :     this->_bind(*t_out.sockets.back(), priority);
    1350           0 : }
    1351             : 
    1352             : void
    1353           0 : Task::bind(Task& t_out, const int priority)
    1354             : {
    1355             : #ifdef SPU_SHOW_DEPRECATED
    1356             :     std::clog << rang::tag::warning << "Deprecated: 'Task::bind()' should be replaced by 'Task::operator='."
    1357             :               << std::endl;
    1358             : #ifdef SPU_STACKTRACE
    1359             : #ifdef SPU_COLORS
    1360             :     bool enable_color = true;
    1361             : #else
    1362             :     bool enable_color = false;
    1363             : #endif
    1364             :     cpptrace::generate_trace().print(std::clog, enable_color);
    1365             : #endif
    1366             : #endif
    1367           0 :     this->_bind(t_out, priority);
    1368           0 : }
    1369             : 
    1370             : void
    1371        7377 : Task::operator=(Socket& s_out)
    1372             : {
    1373             : #ifndef SPU_FAST
    1374        7377 :     if (s_out.get_type() == socket_t::SOUT || s_out.get_type() == socket_t::SFWD)
    1375             : #endif
    1376        7377 :         this->_bind(s_out);
    1377             : #ifndef SPU_FAST
    1378             :     else
    1379             :     {
    1380           0 :         std::stringstream message;
    1381             :         message << "'s_out' should be and output socket ("
    1382           0 :                 << "'s_out.datatype' = " << type_to_string[s_out.get_datatype()] << ", "
    1383           0 :                 << "'s_out.name' = " << s_out.get_name() << ", "
    1384           0 :                 << "'s_out.task.name' = " << s_out.task.get_name() << ", "
    1385           0 :                 << "'s_out.type' = " << (s_out.get_type() == socket_t::SIN ? "SIN" : "SOUT") << ", "
    1386           0 :                 << "'s_out.task.module.name' = " << s_out.task.get_module().get_custom_name() << ").";
    1387           0 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
    1388           0 :     }
    1389             : #endif
    1390        7377 : }
    1391             : 
    1392             : void
    1393         300 : Task::operator=(Task& t_out)
    1394             : {
    1395         300 :     (*this) = *t_out.sockets.back();
    1396         300 : }
    1397             : 
    1398             : size_t
    1399       50457 : Task::unbind(Socket& s_out)
    1400             : {
    1401       50457 :     if (this->fake_input_sockets.size())
    1402             :     {
    1403        6277 :         size_t i = 0;
    1404        6317 :         for (auto& fsi : this->fake_input_sockets)
    1405             :         {
    1406        6277 :             if (&fsi->get_bound_socket() == &s_out)
    1407             :             {
    1408        6237 :                 const auto pos = fsi->unbind(s_out);
    1409        6237 :                 if (this->last_input_socket == fsi.get()) this->last_input_socket = nullptr;
    1410        6237 :                 this->fake_input_sockets.erase(this->fake_input_sockets.begin() + i);
    1411        6237 :                 this->n_input_sockets--;
    1412        6237 :                 if (this->fake_input_sockets.size() && this->last_input_socket == nullptr)
    1413           0 :                     this->last_input_socket = this->fake_input_sockets.back().get();
    1414        6237 :                 return pos;
    1415             :             }
    1416          40 :             i++;
    1417             :         }
    1418             : 
    1419          40 :         std::stringstream message;
    1420             :         message << "'s_out' is not bound the this task ("
    1421          80 :                 << "'s_out.datatype' = " << type_to_string[s_out.datatype] << ", "
    1422          40 :                 << "'s_out.name' = " << s_out.get_name() << ", "
    1423           0 :                 << "'s_out.task.name' = " << s_out.task.get_name() << ", "
    1424          40 :                 << "'s_out.task.module.name' = " << s_out.task.get_module().get_custom_name() << ", "
    1425          40 :                 << "'task.name' = " << this->get_name() << ", "
    1426          80 :                 << "'task.module.name' = " << this->get_module().get_custom_name() << ").";
    1427          40 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
    1428          40 :     }
    1429             :     else
    1430             :     {
    1431       44180 :         std::stringstream message;
    1432             :         message << "This task does not have fake input socket to unbind ("
    1433       88360 :                 << "'s_out.datatype' = " << type_to_string[s_out.datatype] << ", "
    1434       44180 :                 << "'s_out.name' = " << s_out.get_name() << ", "
    1435           0 :                 << "'s_out.task.name' = " << s_out.task.get_name() << ", "
    1436       44180 :                 << "'s_out.task.module.name' = " << s_out.task.get_module().get_custom_name() << ", "
    1437       44180 :                 << "'task.name' = " << this->get_name() << ", "
    1438       88360 :                 << "'task.module.name' = " << this->get_module().get_custom_name() << ").";
    1439       44180 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
    1440       44180 :     }
    1441             : }
    1442             : 
    1443             : size_t
    1444         244 : Task::unbind(Task& t_out)
    1445             : {
    1446         244 :     return this->unbind(*t_out.sockets.back());
    1447             : }
    1448             : 
    1449             : size_t
    1450        2379 : Task::get_n_static_input_sockets() const
    1451             : {
    1452        2379 :     size_t n = 0;
    1453        8730 :     for (auto& s : this->sockets)
    1454        6351 :         if (s->get_type() == socket_t::SIN && s->_get_dataptr() != nullptr && s->bound_socket == nullptr) n++;
    1455        2379 :     return n;
    1456             : }
    1457             : 
    1458             : bool
    1459           0 : Task::is_stateless() const
    1460             : {
    1461           0 :     return this->get_module().is_stateless();
    1462             : }
    1463             : 
    1464             : bool
    1465           0 : Task::is_stateful() const
    1466             : {
    1467           0 :     return this->get_module().is_stateful();
    1468             : }
    1469             : 
    1470             : bool
    1471        1735 : Task::is_replicable() const
    1472             : {
    1473        1735 :     return this->replicable;
    1474             : }
    1475             : 
    1476             : void
    1477         270 : Task::set_replicability(const bool replicable)
    1478             : {
    1479         270 :     if (replicable && !this->module->is_clonable())
    1480             :     {
    1481           0 :         std::stringstream message;
    1482             :         message << "The replicability of this task cannot be set to true because its corresponding module is not "
    1483           0 :                 << "clonable (task.name = '" << this->get_name() << "', module.name = '"
    1484           0 :                 << this->get_module().get_name() << "').";
    1485           0 :         throw tools::runtime_error(__FILE__, __LINE__, __func__, message.str());
    1486           0 :     }
    1487         270 :     this->replicable = replicable;
    1488             :     // this->replicable = replicable ? this->module->is_clonable() : false;
    1489         270 : }
    1490             : 
    1491             : // ==================================================================================== explicit template instantiation
    1492             : template size_t
    1493             : Task::create_2d_socket_in<int8_t>(const std::string&, const size_t, const size_t);
    1494             : template size_t
    1495             : Task::create_2d_socket_in<uint8_t>(const std::string&, const size_t, const size_t);
    1496             : template size_t
    1497             : Task::create_2d_socket_in<int16_t>(const std::string&, const size_t, const size_t);
    1498             : template size_t
    1499             : Task::create_2d_socket_in<uint16_t>(const std::string&, const size_t, const size_t);
    1500             : template size_t
    1501             : Task::create_2d_socket_in<int32_t>(const std::string&, const size_t, const size_t);
    1502             : template size_t
    1503             : Task::create_2d_socket_in<uint32_t>(const std::string&, const size_t, const size_t);
    1504             : template size_t
    1505             : Task::create_2d_socket_in<int64_t>(const std::string&, const size_t, const size_t);
    1506             : template size_t
    1507             : Task::create_2d_socket_in<uint64_t>(const std::string&, const size_t, const size_t);
    1508             : template size_t
    1509             : Task::create_2d_socket_in<float>(const std::string&, const size_t, const size_t);
    1510             : template size_t
    1511             : Task::create_2d_socket_in<double>(const std::string&, const size_t, const size_t);
    1512             : 
    1513             : template size_t
    1514             : Task::create_2d_socket_out<int8_t>(const std::string&, const size_t, const size_t, const bool);
    1515             : template size_t
    1516             : Task::create_2d_socket_out<uint8_t>(const std::string&, const size_t, const size_t, const bool);
    1517             : template size_t
    1518             : Task::create_2d_socket_out<int16_t>(const std::string&, const size_t, const size_t, const bool);
    1519             : template size_t
    1520             : Task::create_2d_socket_out<uint16_t>(const std::string&, const size_t, const size_t, const bool);
    1521             : template size_t
    1522             : Task::create_2d_socket_out<int32_t>(const std::string&, const size_t, const size_t, const bool);
    1523             : template size_t
    1524             : Task::create_2d_socket_out<uint32_t>(const std::string&, const size_t, const size_t, const bool);
    1525             : template size_t
    1526             : Task::create_2d_socket_out<int64_t>(const std::string&, const size_t, const size_t, const bool);
    1527             : template size_t
    1528             : Task::create_2d_socket_out<uint64_t>(const std::string&, const size_t, const size_t, const bool);
    1529             : template size_t
    1530             : Task::create_2d_socket_out<float>(const std::string&, const size_t, const size_t, const bool);
    1531             : template size_t
    1532             : Task::create_2d_socket_out<double>(const std::string&, const size_t, const size_t, const bool);
    1533             : 
    1534             : template size_t
    1535             : Task::create_2d_socket_fwd<int8_t>(const std::string&, const size_t, const size_t);
    1536             : template size_t
    1537             : Task::create_2d_socket_fwd<uint8_t>(const std::string&, const size_t, const size_t);
    1538             : template size_t
    1539             : Task::create_2d_socket_fwd<int16_t>(const std::string&, const size_t, const size_t);
    1540             : template size_t
    1541             : Task::create_2d_socket_fwd<uint16_t>(const std::string&, const size_t, const size_t);
    1542             : template size_t
    1543             : Task::create_2d_socket_fwd<int32_t>(const std::string&, const size_t, const size_t);
    1544             : template size_t
    1545             : Task::create_2d_socket_fwd<uint32_t>(const std::string&, const size_t, const size_t);
    1546             : template size_t
    1547             : Task::create_2d_socket_fwd<int64_t>(const std::string&, const size_t, const size_t);
    1548             : template size_t
    1549             : Task::create_2d_socket_fwd<uint64_t>(const std::string&, const size_t, const size_t);
    1550             : template size_t
    1551             : Task::create_2d_socket_fwd<float>(const std::string&, const size_t, const size_t);
    1552             : template size_t
    1553             : Task::create_2d_socket_fwd<double>(const std::string&, const size_t, const size_t);
    1554             : // ==================================================================================== explicit template instantiation

Generated by: LCOV version 1.14