From 9cdc7adc80062bac0517db7ae07145a865fc81ca Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 12 Apr 2024 10:13:24 +0200 Subject: [PATCH 1/3] ReadMessage/WriteMessage --- src/parallel/bbs.cpp | 135 +++++++++++++++++++++-- src/parallel/bbs.h | 2 + src/parallel/bbsclimpi.cpp | 5 +- src/parallel/bbsdirectmpi.cpp | 5 +- src/parallel/bbsimpl.h | 49 ++++++++- src/parallel/ocbbs.cpp | 195 ++++++++++++++-------------------- 6 files changed, 265 insertions(+), 126 deletions(-) diff --git a/src/parallel/bbs.cpp b/src/parallel/bbs.cpp index 2a51b20c55..32beb36d18 100644 --- a/src/parallel/bbs.cpp +++ b/src/parallel/bbs.cpp @@ -269,7 +269,6 @@ void BBS::pkpickle(const char* s, size_t n) { void BBSImpl::execute(int id) { // assumes a "_todo" message in receive buffer ++etaskcnt; double st, et; - int userid; char* rs; char* s; size_t n; @@ -282,18 +281,17 @@ void BBSImpl::execute(int id) { // assumes a "_todo" message in receive buffer if (debug_) { printf("execute begin %g: working_id_=%d\n", st, working_id_); } - userid = upkint(); - int wid = upkint(); + Message mess = readMessage(this); hoc_ac_ = double(id); - rs = execute_helper(&n, id); // builds and execute hoc statement + rs = execute_helper(mess, &n, id); // builds and execute hoc statement et = time() - st; total_exec_time += et; if (debug) { printf("execute end elapsed %g: working_id_=%d hoc_ac_=%g\n", et, working_id_, hoc_ac_); } pkbegin(); - pkint(userid); - pkint(wid); + pkint(mess.userid); + pkint(mess.wid); pkint(rs ? 1 : 0); if (!rs) { pkdouble(hoc_ac_); @@ -490,3 +488,128 @@ void BBSImpl::start() { } started_ = 1; } + +static std::vector fromUpkpickle(BBSImpl* impl) { + std::size_t n; + char* s = impl->upkpickle(&n); + std::vector pickle(s, s + n); + delete[] s; + return pickle; +} + +static std::string fromUpkstr(BBSImpl* impl) { + char* s = impl->upkstr(); + std::string str(s); + delete[] s; + return str; +} + +static MyStr fromUpkstr2(BBSImpl* impl) { + char* s = impl->upkstr(); + MyStr str(s); + return str; +} + +static std::vector fromUpkvec(BBSImpl* impl) { + std::size_t n = impl->upkint(); + std::vector vec(n); + impl->upkvec(n, vec.data()); + return vec; +} + +Message readMessage(BBSImpl* impl) { + Message mess{}; + mess.userid = impl->upkint(); + mess.wid = impl->upkint(); + mess.style = impl->upkint(); + + int arg_manifest = 0; + switch (mess.style) { + case 0: + mess.statement = fromUpkstr(impl); + break; + case 1: + mess.fname = fromUpkstr(impl); + arg_manifest = impl->upkint(); + break; + case 2: + mess.template_name = fromUpkstr(impl); + mess.object_index = impl->upkint(); + mess.fname = fromUpkstr(impl); + arg_manifest = impl->upkint(); + break; + case 3: + mess.pickle = fromUpkpickle(impl); + arg_manifest = impl->upkint(); + break; + } + + if (arg_manifest != 0) { + for (int i = 0, j = arg_manifest; (i = j % 5) != 0; j /= 5) { + switch (i) { + case 1: + mess.args.push_back(impl->upkdouble()); + break; + case 2: + mess.args.push_back(fromUpkstr2(impl)); + break; + case 3: + mess.args.push_back(fromUpkvec(impl)); + break; + case 4: + mess.args.push_back(fromUpkpickle(impl)); + break; + } + } + } + + return mess; +} + +void writeMessage(BBS* impl, Message& mess) { + impl->pkint(mess.userid); + impl->pkint(mess.wid); + impl->pkint(mess.style); + + if (mess.style == 0) { + impl->pkstr(mess.statement.c_str()); + return; + } else if (mess.style == 1) { + impl->pkstr(mess.fname.c_str()); + } else if (mess.style == 2) { + impl->pkstr(mess.template_name.c_str()); + impl->pkint(mess.object_index); + impl->pkstr(mess.fname.c_str()); + } else if (mess.style == 3) { + impl->pkpickle(mess.pickle.data(), mess.pickle.size()); + } + + int argtype = 0; + int ii = 1; + for (auto& arg: mess.args) { + if (auto* var = std::get_if(&arg)) { + argtype += 1 * ii; + } else if (auto* var = std::get_if(&arg)) { + argtype += 2 * ii; + } else if (auto* var = std::get_if>(&arg)) { + argtype += 3 * ii; + } else if (auto* var = std::get_if>(&arg)) { + argtype += 4 * ii; + } + ii *= 5; + } + impl->pkint(argtype); + + for (auto& arg: mess.args) { + if (auto* var = std::get_if(&arg)) { + impl->pkdouble(*var); + } else if (auto* var = std::get_if(&arg)) { + impl->pkstr(var->data()); + } else if (auto* var = std::get_if>(&arg)) { + impl->pkint(var->size()); + impl->pkvec(var->size(), var->data()); + } else if (auto* var = std::get_if>(&arg)) { + impl->pkpickle(var->data(), var->size()); + } + } +} diff --git a/src/parallel/bbs.h b/src/parallel/bbs.h index 01f4ed28d0..e7ba3077d1 100644 --- a/src/parallel/bbs.h +++ b/src/parallel/bbs.h @@ -72,3 +72,5 @@ class BBS { protected: BBSImpl* impl_; }; + +void writeMessage(BBS* impl, Message& mess); diff --git a/src/parallel/bbsclimpi.cpp b/src/parallel/bbsclimpi.cpp index 101949cd83..b926c2fefc 100644 --- a/src/parallel/bbsclimpi.cpp +++ b/src/parallel/bbsclimpi.cpp @@ -226,13 +226,12 @@ int BBSClient::take_todo() { size_t n; while ((type = get(0, TAKE_TODO)) == CONTEXT) { upkbegin(); - upkint(); // throw away userid - upkint(); // throw away info in reserved second slot for worker_id + Message mess = readMessage(this); #if debug printf("%d execute context\n", nrnmpi_myid_bbs); fflush(stdout); #endif - rs = execute_helper(&n, -1); + rs = execute_helper(mess, &n, -1); if (rs) { delete[] rs; } diff --git a/src/parallel/bbsdirectmpi.cpp b/src/parallel/bbsdirectmpi.cpp index ca68f86dfc..fc4b75032e 100644 --- a/src/parallel/bbsdirectmpi.cpp +++ b/src/parallel/bbsdirectmpi.cpp @@ -56,9 +56,8 @@ void BBSDirect::context() { nrnmpi_ref(recvbuf_); nrnmpi_copy(recvbuf_, sendbuf_); nrnmpi_upkbegin(recvbuf_); - nrnmpi_upkint(recvbuf_); - nrnmpi_upkint(recvbuf_); // slot reserved for tag - execute_helper(&n, -1, false); + Message mess = readMessage(this); + execute_helper(mess, &n, -1, false); nrnmpi_unref(recvbuf_); recvbuf_ = rsav; } diff --git a/src/parallel/bbsimpl.h b/src/parallel/bbsimpl.h index 6a89af82ed..dc408b4c2b 100644 --- a/src/parallel/bbsimpl.h +++ b/src/parallel/bbsimpl.h @@ -1,5 +1,11 @@ #pragma once +#include +#include +#include + +struct Message; + class BBSImpl { public: BBSImpl(); @@ -63,7 +69,7 @@ class BBSImpl { static bool master_works_; protected: - char* execute_helper(size_t*, int id, bool exec = true); // involves hoc specific details in + char* execute_helper(Message&, size_t*, int id, bool exec = true); // involves hoc specific details in // ocbbs.cpp void subworld_worker_execute(); // shadows execute_helper. ie. each of // the nrnmpi_myid_bbs workers (and master) need to execute @@ -72,3 +78,44 @@ class BBSImpl { // intracommunicate via the bulletin board but only via // mpi on the subworld communicator. }; + +class MyStr { + public: + MyStr(char* s) + : s_(s) + {}; + + ~MyStr() { + delete[] s_; + } + + std::size_t size() { + return strlen(s_); + } + + char*& data() { + return s_; + } + + private: + char* s_ = nullptr; +}; + +struct Message { + int userid; + int wid; // working_id + int style; + + std::string statement; + + std::string fname; + std::string template_name; + int object_index; + + std::vector pickle; + + using ArgType = std::variant, std::vector, MyStr>; + std::vector args; +}; + +Message readMessage(BBSImpl* impl); diff --git a/src/parallel/ocbbs.cpp b/src/parallel/ocbbs.cpp index e71cb56900..190d272aff 100644 --- a/src/parallel/ocbbs.cpp +++ b/src/parallel/ocbbs.cpp @@ -102,83 +102,76 @@ void bbs_done() { } static int submit_help(OcBBS* bbs) { - int id, i, firstarg, style; - char* pname = 0; // if using Python callable posting_ = true; bbs->pkbegin(); - i = 1; + int i = 1; + Message mess{}; if (hoc_is_double_arg(i)) { - bbs->pkint((id = (int) chkarg(i++, 0, MD))); + mess.userid = (int) chkarg(i++, 0, MD); } else { - bbs->pkint((id = --bbs->next_local_)); + mess.userid = --bbs->next_local_; } - bbs->pkint(0); // space for working_id + mess.wid = 0; if (ifarg(i + 1)) { -#if 1 - int argtypes = 0; - int ii = 1; if (hoc_is_str_arg(i)) { - style = 1; - bbs->pkint(style); // "fname", arg1, ... style - bbs->pkstr(gargstr(i++)); + mess.style = 1; + mess.fname = gargstr(i++); } else { Object* ob = *hoc_objgetarg(i++); - size_t size; + char* pname = nullptr; if (neuron::python::methods.po2pickle) { + std::size_t size; pname = neuron::python::methods.po2pickle(ob, &size); - } - if (pname) { - style = 3; - bbs->pkint(style); // pyfun, arg1, ... style - bbs->pkpickle(pname, size); - delete[] pname; - } else { - style = 2; - bbs->pkint(style); // [object],"fname", arg1, ... style - bbs->pkstr(ob->ctemplate->sym->name); - bbs->pkint(ob->index); - // printf("ob=%s\n", hoc_object_name(ob)); - bbs->pkstr(gargstr(i++)); + if (pname != nullptr) { + mess.style = 3; + mess.pickle.resize(size); + std::copy(pname, pname + size, mess.pickle.data()); + delete[] pname; + } else { + mess.style = 2; + mess.template_name = ob->ctemplate->sym->name; + mess.object_index = ob->index; + mess.fname = gargstr(i++); + } } } - firstarg = i; - for (; ifarg(i); ++i) { // first is least significant + for (; ifarg(i); ++i) { if (hoc_is_double_arg(i)) { - argtypes += 1 * ii; + mess.args.push_back(*getarg(i)); } else if (hoc_is_str_arg(i)) { - argtypes += 2 * ii; - } else if (is_vector_arg(i)) { // hoc Vector - argtypes += 3 * ii; + mess.args.push_back(MyStr(gargstr(i))); + } else if (is_vector_arg(i)) { + Vect* vec = vector_arg(i); + mess.args.push_back(vec->vec()); } else { // must be a PythonObject - argtypes += 4 * ii; + size_t size; + char* s = neuron::python::methods.po2pickle(*hoc_objgetarg(i), &size); + std::vector pickle(size); + std::copy(s, s + size, pickle.data()); + mess.pickle = pickle; + delete[] s; } - ii *= 5; } - // printf("submit style %d %s argtypes=%o\n", style, gargstr(firstarg-1), argtypes); - bbs->pkint(argtypes); - pack_help(firstarg, bbs); -#endif } else { if (hoc_is_str_arg(i)) { - bbs->pkint(0); // hoc statement style - bbs->pkstr(gargstr(i)); + mess.style = 0; + mess.statement = gargstr(i); } else if (neuron::python::methods.po2pickle) { + mess.style = 3; size_t size; - pname = neuron::python::methods.po2pickle(*hoc_objgetarg(i), &size); - bbs->pkint(3); // pyfun with no arg style - bbs->pkpickle(pname, size); - bbs->pkint(0); // argtypes + char* pname = neuron::python::methods.po2pickle(*hoc_objgetarg(i), &size); + std::copy(pname, pname + size, mess.pickle.data()); delete[] pname; } } + writeMessage(bbs, mess); posting_ = false; - return id; + return mess.userid; } static double submit(void* v) { - int id; OcBBS* bbs = (OcBBS*) v; - id = submit_help(bbs); + int id = submit_help(bbs); bbs->submit(id); return double(id); } @@ -186,7 +179,6 @@ static double submit(void* v) { static double context(void* v) { OcBBS* bbs = (OcBBS*) v; submit_help(bbs); - // printf("%d context %s %s\n", bbs->myid(), hoc_object_name(*hoc_objgetarg(1)), gargstr(2)); bbs->context(); return 1.; } @@ -1181,53 +1173,46 @@ void ParallelContext_reg() { // A python pickle (https://docs.python.org/3/library/pickle.html) followed by arguments. // Return a string that is of size `size`. // Dry run if `exec` is false. -char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { - char* python_pickle; // Used only for style == 3 +char* BBSImpl::execute_helper(Message& mess, size_t* size, int id, bool exec) { int subworld = (nrnmpi_numprocs > 1 && nrnmpi_numprocs_bbs < nrnmpi_numprocs_world); - int style = upkint(); if (subworld) { assert(nrnmpi_myid == 0); int info[2]; info[0] = id; - info[1] = style; + info[1] = mess.style; nrnmpi_int_broadcast(info, 2, 0); } char* rs = nullptr; *size = 0; - switch (style) { + switch (mess.style) { case 0: { - char* statement = upkstr(); if (subworld) { - int size = strlen(statement) + 1; + int size = mess.statement.size() + 1; nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(statement, size, 0); + nrnmpi_char_broadcast(mess.statement.data(), size, 0); } - hoc_obj_run(statement, nullptr); - delete[] statement; + hoc_obj_run(mess.statement.data(), nullptr); } break; default: { - size_t npickle; Symbol* fname = nullptr; Object* ob = nullptr; std::list sarg; // Store the strings pointer to delete[] them later // Use a list because, we push pointers of the object into // the hoc stack int narg = 0; // total number of args - if (style == 2) { // object first - char* template_name = upkstr(); - int object_index = upkint(); // object index - Symbol* sym = hoc_lookup(template_name); + if (mess.style == 2) { // object first + Symbol* sym = hoc_lookup(mess.template_name.c_str()); if (sym) { sym = hoc_which_template(sym); } if (!sym) { - hoc_execerror(template_name, "is not a template"); + hoc_execerror(mess.template_name.c_str(), "is not a template"); } hoc_Item *q, *ql; ql = sym->u.ctemplate->olist; ITERATE(q, ql) { ob = OBJ(q); - if (ob->index == object_index) { + if (ob->index == mess.object_index) { break; } ob = nullptr; @@ -1235,41 +1220,35 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { if (!ob) { fprintf(stderr, "%s[%d] is not an Object in this process\n", - template_name, - object_index); + mess.template_name.c_str(), + mess.object_index); hoc_execerror("ParallelContext execution error", nullptr); } - delete[] template_name; - char* fname_str = upkstr(); - fname = hoc_table_lookup(fname_str, sym->u.ctemplate->symtable); + fname = hoc_table_lookup(mess.fname.c_str(), sym->u.ctemplate->symtable); if (!fname) { - fprintf(stderr, "%s not a function in %s\n", fname_str, hoc_object_name(ob)); + fprintf(stderr, "%s not a function in %s\n", mess.fname.c_str(), hoc_object_name(ob)); hoc_execerror("ParallelContext execution error", nullptr); } - delete[] fname_str; if (subworld) { hoc_execerror("with subworlds, this submit style not implemented", nullptr); } - } else if (style == 3) { // Python callable - python_pickle = upkpickle(&npickle); + } else if (mess.style == 3) { // Python callable if (subworld) { - int size = npickle; + int size = mess.pickle.size(); nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(python_pickle, size, 0); + nrnmpi_char_broadcast(mess.pickle.data(), size, 0); } } else { - char* fname_str = upkstr(); if (subworld) { - int size = strlen(fname_str) + 1; + int size = mess.fname.size() + 1; nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(fname_str, size, 0); + nrnmpi_char_broadcast(mess.fname.data(), size, 0); } - fname = hoc_lookup(fname_str); + fname = hoc_lookup(mess.fname.c_str()); if (!fname) { - fprintf(stderr, "%s not a function in %s\n", fname_str, hoc_object_name(ob)); + fprintf(stderr, "%s not a function in %s\n", mess.fname.c_str(), hoc_object_name(ob)); hoc_execerror("ParallelContext execution error", nullptr); } - delete[] fname_str; } int argtypes = upkint(); // first is least signif @@ -1277,48 +1256,42 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { // printf("%d exec argtypes = %d\n", nrnmpi_myid_world, argtypes); nrnmpi_int_broadcast(&argtypes, 1, 0); } - for (int i = 0, j = argtypes; (i = j % 5) != 0; j /= 5) { - ++narg; - if (i == 1) { - double x = upkdouble(); + for (auto& arg: mess.args) { + if (auto* var = std::get_if(&arg)) { if (subworld) { - nrnmpi_dbl_broadcast(&x, 1, 0); + nrnmpi_dbl_broadcast(var, 1, 0); } - hoc_pushx(x); - } else if (i == 2) { - sarg.push_back(upkstr()); + hoc_pushx(*var); + } else if (auto* var = std::get_if(&arg)) { if (subworld) { - int size = strlen(sarg.back()) + 1; + int size = var->size() + 1; nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(sarg.back(), size, 0); + nrnmpi_char_broadcast(var->data(), size, 0); } - hoc_pushstr(&(sarg.back())); - } else if (i == 3) { - int n = upkint(); + hoc_pushstr(&var->data()); + } else if (auto* var = std::get_if>(&arg)) { + int size = var->size(); if (subworld) { - nrnmpi_int_broadcast(&n, 1, 0); + nrnmpi_int_broadcast(&size, 1, 0); } - Vect* vec = new Vect(n); - upkvec(n, vec->data()); + Vect* vec = new Vect(); + vec->vec() = *var; if (subworld) { - nrnmpi_dbl_broadcast(vec->data(), n, 0); + nrnmpi_dbl_broadcast(vec->data(), size, 0); } hoc_pushobj(vec->temp_objvar()); - } else { // PythonObject - size_t n; - char* pickle = upkpickle(&n); - int size = n; + } else if (auto* var = std::get_if>(&arg)) { // PythonObject + int size = var->size(); if (subworld) { nrnmpi_int_broadcast(&size, 1, 0); - nrnmpi_char_broadcast(pickle, size, 0); + nrnmpi_char_broadcast(var->data(), size, 0); } assert(neuron::python::methods.pickle2po); - Object* po = neuron::python::methods.pickle2po(pickle, n); - delete[] pickle; + Object* po = neuron::python::methods.pickle2po(var->data(), size); hoc_pushobj(hoc_temp_objptr(po)); } } - if (style == 3) { + if (mess.style == 3) { assert(neuron::python::methods.call_picklef); if (pickle_ret_) { delete[] pickle_ret_; @@ -1326,19 +1299,15 @@ char* BBSImpl::execute_helper(size_t* size, int id, bool exec) { pickle_ret_size_ = 0; } if (exec) { - rs = neuron::python::methods.call_picklef(python_pickle, npickle, narg, size); + rs = neuron::python::methods.call_picklef(mess.pickle.data(), mess.pickle.size(), mess.args.size(), size); } hoc_ac_ = 0.; - delete[] python_pickle; } else { hoc_ac_ = 0.; if (exec) { - hoc_ac_ = hoc_call_objfunc(fname, narg, ob); + hoc_ac_ = hoc_call_objfunc(fname, mess.args.size(), ob); } } - for (auto& arg: sarg) { - delete[] arg; - } } break; } return rs; From 5c97d5341bdaa25c69bd0a68b9bd50b014df7a00 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 08:18:07 +0000 Subject: [PATCH 2/3] Fix formatting --- src/parallel/bbs.cpp | 58 +++++++++++++++++++++--------------------- src/parallel/bbsimpl.h | 39 ++++++++++++++-------------- src/parallel/ocbbs.cpp | 17 ++++++++++--- 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/src/parallel/bbs.cpp b/src/parallel/bbs.cpp index 32beb36d18..3581cbf6e2 100644 --- a/src/parallel/bbs.cpp +++ b/src/parallel/bbs.cpp @@ -525,40 +525,40 @@ Message readMessage(BBSImpl* impl) { int arg_manifest = 0; switch (mess.style) { - case 0: - mess.statement = fromUpkstr(impl); - break; - case 1: - mess.fname = fromUpkstr(impl); - arg_manifest = impl->upkint(); - break; - case 2: - mess.template_name = fromUpkstr(impl); - mess.object_index = impl->upkint(); - mess.fname = fromUpkstr(impl); - arg_manifest = impl->upkint(); - break; - case 3: - mess.pickle = fromUpkpickle(impl); - arg_manifest = impl->upkint(); - break; + case 0: + mess.statement = fromUpkstr(impl); + break; + case 1: + mess.fname = fromUpkstr(impl); + arg_manifest = impl->upkint(); + break; + case 2: + mess.template_name = fromUpkstr(impl); + mess.object_index = impl->upkint(); + mess.fname = fromUpkstr(impl); + arg_manifest = impl->upkint(); + break; + case 3: + mess.pickle = fromUpkpickle(impl); + arg_manifest = impl->upkint(); + break; } if (arg_manifest != 0) { for (int i = 0, j = arg_manifest; (i = j % 5) != 0; j /= 5) { switch (i) { - case 1: - mess.args.push_back(impl->upkdouble()); - break; - case 2: - mess.args.push_back(fromUpkstr2(impl)); - break; - case 3: - mess.args.push_back(fromUpkvec(impl)); - break; - case 4: - mess.args.push_back(fromUpkpickle(impl)); - break; + case 1: + mess.args.push_back(impl->upkdouble()); + break; + case 2: + mess.args.push_back(fromUpkstr2(impl)); + break; + case 3: + mess.args.push_back(fromUpkvec(impl)); + break; + case 4: + mess.args.push_back(fromUpkpickle(impl)); + break; } } } diff --git a/src/parallel/bbsimpl.h b/src/parallel/bbsimpl.h index dc408b4c2b..6ebff0fb7f 100644 --- a/src/parallel/bbsimpl.h +++ b/src/parallel/bbsimpl.h @@ -69,9 +69,9 @@ class BBSImpl { static bool master_works_; protected: - char* execute_helper(Message&, size_t*, int id, bool exec = true); // involves hoc specific details in - // ocbbs.cpp - void subworld_worker_execute(); // shadows execute_helper. ie. each of + char* execute_helper(Message&, size_t*, int id, bool exec = true); // involves hoc specific + // details in ocbbs.cpp + void subworld_worker_execute(); // shadows execute_helper. ie. each of // the nrnmpi_myid_bbs workers (and master) need to execute // the same thing on each of the subworld processes // associated with nrnmpi_myid==0. A subworld does not @@ -80,30 +80,29 @@ class BBSImpl { }; class MyStr { - public: - MyStr(char* s) - : s_(s) - {}; + public: + MyStr(char* s) + : s_(s){}; - ~MyStr() { - delete[] s_; - } + ~MyStr() { + delete[] s_; + } - std::size_t size() { - return strlen(s_); - } + std::size_t size() { + return strlen(s_); + } - char*& data() { - return s_; - } + char*& data() { + return s_; + } - private: - char* s_ = nullptr; + private: + char* s_ = nullptr; }; struct Message { int userid; - int wid; // working_id + int wid; // working_id int style; std::string statement; @@ -118,4 +117,4 @@ struct Message { std::vector args; }; -Message readMessage(BBSImpl* impl); +Message readMessage(BBSImpl* impl); diff --git a/src/parallel/ocbbs.cpp b/src/parallel/ocbbs.cpp index 190d272aff..c7fd1f443a 100644 --- a/src/parallel/ocbbs.cpp +++ b/src/parallel/ocbbs.cpp @@ -1200,7 +1200,7 @@ char* BBSImpl::execute_helper(Message& mess, size_t* size, int id, bool exec) { // Use a list because, we push pointers of the object into // the hoc stack int narg = 0; // total number of args - if (mess.style == 2) { // object first + if (mess.style == 2) { // object first Symbol* sym = hoc_lookup(mess.template_name.c_str()); if (sym) { sym = hoc_which_template(sym); @@ -1226,7 +1226,10 @@ char* BBSImpl::execute_helper(Message& mess, size_t* size, int id, bool exec) { } fname = hoc_table_lookup(mess.fname.c_str(), sym->u.ctemplate->symtable); if (!fname) { - fprintf(stderr, "%s not a function in %s\n", mess.fname.c_str(), hoc_object_name(ob)); + fprintf(stderr, + "%s not a function in %s\n", + mess.fname.c_str(), + hoc_object_name(ob)); hoc_execerror("ParallelContext execution error", nullptr); } if (subworld) { @@ -1246,7 +1249,10 @@ char* BBSImpl::execute_helper(Message& mess, size_t* size, int id, bool exec) { } fname = hoc_lookup(mess.fname.c_str()); if (!fname) { - fprintf(stderr, "%s not a function in %s\n", mess.fname.c_str(), hoc_object_name(ob)); + fprintf(stderr, + "%s not a function in %s\n", + mess.fname.c_str(), + hoc_object_name(ob)); hoc_execerror("ParallelContext execution error", nullptr); } } @@ -1299,7 +1305,10 @@ char* BBSImpl::execute_helper(Message& mess, size_t* size, int id, bool exec) { pickle_ret_size_ = 0; } if (exec) { - rs = neuron::python::methods.call_picklef(mess.pickle.data(), mess.pickle.size(), mess.args.size(), size); + rs = neuron::python::methods.call_picklef(mess.pickle.data(), + mess.pickle.size(), + mess.args.size(), + size); } hoc_ac_ = 0.; } else { From bc10cd983935a3002814f0416c042b9d855a05bd Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 12 Apr 2024 14:05:42 +0200 Subject: [PATCH 3/3] From BBS to OC --- src/parallel/bbs.cpp | 73 ++++++++++++++++++++++++++++++------------ src/parallel/ocbbs.cpp | 31 ++++++------------ 2 files changed, 61 insertions(+), 43 deletions(-) diff --git a/src/parallel/bbs.cpp b/src/parallel/bbs.cpp index 32beb36d18..bcc63a5099 100644 --- a/src/parallel/bbs.cpp +++ b/src/parallel/bbs.cpp @@ -517,6 +517,30 @@ static std::vector fromUpkvec(BBSImpl* impl) { return vec; } +std::vector readArgsFromOc(int hoc_arg_index) { + std::vector args; + for (; ifarg(i); ++i) { + if (hoc_is_double_arg(i)) { + args.push_back(*getarg(i)); + } else if (hoc_is_str_arg(i)) { + char* s = gargstr(i); + args.push_back(std::string(s)); + delete[] s; + } else if (is_vector_arg(i)) { + Vect* vec = vector_arg(i); + args.push_back(vec->vec()); + } else { // must be a PythonObject + size_t size; + char* s = neuron::python::methods.po2pickle(*hoc_objgetarg(i), &size); + std::vector pickle(size); + std::copy(s, s + size, pickle.data()); + delete[] s; + args.push_back(pickle); + } + } + return args; +} + Message readMessage(BBSImpl* impl) { Message mess{}; mess.userid = impl->upkint(); @@ -566,27 +590,10 @@ Message readMessage(BBSImpl* impl) { return mess; } -void writeMessage(BBS* impl, Message& mess) { - impl->pkint(mess.userid); - impl->pkint(mess.wid); - impl->pkint(mess.style); - - if (mess.style == 0) { - impl->pkstr(mess.statement.c_str()); - return; - } else if (mess.style == 1) { - impl->pkstr(mess.fname.c_str()); - } else if (mess.style == 2) { - impl->pkstr(mess.template_name.c_str()); - impl->pkint(mess.object_index); - impl->pkstr(mess.fname.c_str()); - } else if (mess.style == 3) { - impl->pkpickle(mess.pickle.data(), mess.pickle.size()); - } - +int computeArgType(const std::vector& args) { int argtype = 0; int ii = 1; - for (auto& arg: mess.args) { + for (auto& arg: args) { if (auto* var = std::get_if(&arg)) { argtype += 1 * ii; } else if (auto* var = std::get_if(&arg)) { @@ -598,9 +605,11 @@ void writeMessage(BBS* impl, Message& mess) { } ii *= 5; } - impl->pkint(argtype); + return argtype; +} - for (auto& arg: mess.args) { +void writeArgs(BBS* impl, std::vector& args) { + for (auto& arg: args) { if (auto* var = std::get_if(&arg)) { impl->pkdouble(*var); } else if (auto* var = std::get_if(&arg)) { @@ -613,3 +622,25 @@ void writeMessage(BBS* impl, Message& mess) { } } } + +void writeMessage(BBS* impl, Message& mess) { + impl->pkint(mess.userid); + impl->pkint(mess.wid); + impl->pkint(mess.style); + + if (mess.style == 0) { + impl->pkstr(mess.statement.c_str()); + return; + } else if (mess.style == 1) { + impl->pkstr(mess.fname.c_str()); + } else if (mess.style == 2) { + impl->pkstr(mess.template_name.c_str()); + impl->pkint(mess.object_index); + impl->pkstr(mess.fname.c_str()); + } else if (mess.style == 3) { + impl->pkpickle(mess.pickle.data(), mess.pickle.size()); + } + + impl->pkint(computeArgType(mess.args)); + writeArgs(impl, mess.args); +} diff --git a/src/parallel/ocbbs.cpp b/src/parallel/ocbbs.cpp index 190d272aff..439517d52e 100644 --- a/src/parallel/ocbbs.cpp +++ b/src/parallel/ocbbs.cpp @@ -102,8 +102,6 @@ void bbs_done() { } static int submit_help(OcBBS* bbs) { - posting_ = true; - bbs->pkbegin(); int i = 1; Message mess{}; if (hoc_is_double_arg(i)) { @@ -164,8 +162,13 @@ static int submit_help(OcBBS* bbs) { delete[] pname; } } - writeMessage(bbs, mess); - posting_ = false; + + { + posting_ = true; + bbs->pkbegin(); + writeMessage(bbs, mess); + posting_ = false; + } return mess.userid; } @@ -266,24 +269,8 @@ static void pack_help(int i, OcBBS* bbs) { bbs->pkbegin(); posting_ = true; } - for (; ifarg(i); ++i) { - if (hoc_is_double_arg(i)) { - bbs->pkdouble(*getarg(i)); - } else if (hoc_is_str_arg(i)) { - bbs->pkstr(gargstr(i)); - } else if (is_vector_arg(i)) { - int n; - double* px; - n = vector_arg_px(i, &px); - bbs->pkint(n); - bbs->pkvec(n, px); - } else { // must be a PythonObject - size_t size; - char* s = neuron::python::methods.po2pickle(*hoc_objgetarg(i), &size); - bbs->pkpickle(s, size); - delete[] s; - } - } + auto args = readArgsFromOc(i); + writeArgs(bbs, args); } static double pack(void* v) {