Skip to content

Commit

Permalink
Replace HocTopContext* macros with class (#3279)
Browse files Browse the repository at this point in the history
  • Loading branch information
JCGoran authored Dec 11, 2024
1 parent de07242 commit 45fb66a
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 30 deletions.
32 changes: 20 additions & 12 deletions src/nrnpython/hoccontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,6 @@ extern Objectdata* hoc_top_level_data;
extern Symlist* hoc_top_level_symlist;
extern Symlist* hoc_symlist;

#define HocTopContextSet \
HocContext hcref; \
HocContext* hc_ = 0; \
if (hoc_thisobject) { \
hc_ = hc_save_and_set_to_top_(&hcref); \
}

#define HocContextRestore \
if (hc_) { \
hc_restore_(hc_); \
}

struct HocContext {
Object* obj;
Objectdata* obd;
Expand All @@ -37,3 +25,23 @@ static void hc_restore_(HocContext* hc) {
hoc_objectdata = hc->obd;
hoc_symlist = hc->sl;
}

// RAII guard for the top HOC context
class HocTopContextManager {
private:
HocContext hcref;
HocContext* hc_ = nullptr;

public:
HocTopContextManager() {
// ``hoc_thisobject`` is global
if (hoc_thisobject) {
hc_ = hc_save_and_set_to_top_(&hcref);
}
}
~HocTopContextManager() {
if (hc_) {
hc_restore_(hc_);
}
}
};
20 changes: 6 additions & 14 deletions src/nrnpython/nrnpy_hoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ static void* fcall(void* vself, void* vargs) {

return result;
} else {
HocTopContextSet
auto interp = HocTopContextManager();
Inst fc[4];
// ugh. so a potential call of hoc_get_last_pointer_symbol will return nullptr.
fc[0].in = STOP;
Expand All @@ -766,7 +766,6 @@ static void* fcall(void* vself, void* vargs) {
Inst* pcsav = save_pc(fc + 1);
hoc_call();
hoc_pc = pcsav;
HocContextRestore;
}

return nrnpy_hoc_pop("laststatement fcall");
Expand Down Expand Up @@ -1263,7 +1262,7 @@ static PyObject* hocobj_getattr(PyObject* subself, PyObject* pyname) {
}
}
// top level interpreter fork
HocTopContextSet
auto interp = HocTopContextManager();
switch (sym->type) {
case VAR: // double*
if (!is_array(*sym)) {
Expand Down Expand Up @@ -1373,7 +1372,6 @@ static PyObject* hocobj_getattr(PyObject* subself, PyObject* pyname) {
}
}
}
HocContextRestore
return result.release().ptr();
}

Expand Down Expand Up @@ -1499,7 +1497,7 @@ static int hocobj_setattro(PyObject* subself, PyObject* pyname, PyObject* value)
return -1;
}
}
HocTopContextSet
auto interp = HocTopContextManager();
switch (sym->type) {
case VAR: // double*
if (is_array(*sym)) {
Expand Down Expand Up @@ -1533,7 +1531,6 @@ static int hocobj_setattro(PyObject* subself, PyObject* pyname, PyObject* value)
} else {
hoc_pushs(sym);
if (hoc_evalpointer_err()) { // not possible to raise error.
HocContextRestore;
return -1;
}
err = PyArg_Parse(value, "d", hoc_pxpop()) == 0;
Expand Down Expand Up @@ -1590,7 +1587,6 @@ static int hocobj_setattro(PyObject* subself, PyObject* pyname, PyObject* value)
err = -1;
break;
}
HocContextRestore
return err;
}

Expand Down Expand Up @@ -2009,14 +2005,13 @@ static PyObject* hocobj_getitem(PyObject* self, Py_ssize_t ix) {
}
}
} else { // must be a top level intermediate
HocTopContextSet
auto interp = HocTopContextManager();
switch (po->sym_->type) {
case VAR:
hocobj_pushtop(po, po->sym_, ix);
if (hoc_evalpointer_err()) {
--po->nindex_;
HocContextRestore;
return NULL;
return nullptr;
}
--po->nindex_;
if (po->type_ == PyHoc::HocArrayIncomplete) {
Expand All @@ -2040,7 +2035,6 @@ static PyObject* hocobj_getitem(PyObject* self, Py_ssize_t ix) {
--po->nindex_;
break;
}
HocContextRestore;
}
}
return result.release().ptr();
Expand Down Expand Up @@ -2158,12 +2152,11 @@ static int hocobj_setitem(PyObject* self, Py_ssize_t i, PyObject* arg) {
err = set_final_from_stk(arg);
}
} else { // must be a top level intermediate
HocTopContextSet
auto interp = HocTopContextManager();
switch (po->sym_->type) {
case VAR:
hocobj_pushtop(po, po->sym_, i);
if (hoc_evalpointer_err()) {
HocContextRestore;
--po->nindex_;
return -1;
}
Expand Down Expand Up @@ -2194,7 +2187,6 @@ static int hocobj_setitem(PyObject* self, Py_ssize_t i, PyObject* arg) {
PyErr_SetString(PyExc_TypeError, "not assignable");
break;
}
HocContextRestore;
}
return err;
}
Expand Down
3 changes: 1 addition & 2 deletions src/nrnpython/nrnpy_p2h.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static nb::object nrnpy_pyCallObject(nb::callable callable, nb::object args) {
// When hoc calls a PythonObject method, then in case python
// calls something back in hoc, the hoc interpreter must be
// at the top level
HocTopContextSet
auto interp = HocTopContextManager();
nb::tuple tup(args);
nb::object p = nb::steal(PyObject_CallObject(callable.ptr(), tup.ptr()));
#if 0
Expand All @@ -110,7 +110,6 @@ printf("\nargs\n");
PyObject_Print(args, stdout, 0);
printf("\nreturn %p\n", p);
#endif
HocContextRestore
// It would be nice to handle the error here, ending with a hoc_execerror
// for any Exception (note, that does not include SystemExit). However
// since many, but not all, of the callers need to clean up and
Expand Down
3 changes: 1 addition & 2 deletions src/nrnpython/nrnpython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,12 +383,11 @@ static int nrnpython_start(int b) {
static void nrnpython_real() {
int retval = 0;
#if USE_PYTHON
HocTopContextSet
{
auto interp = HocTopContextManager();
nanobind::gil_scoped_acquire lock{};
retval = (PyRun_SimpleString(hoc_gargstr(1)) == 0);
}
HocContextRestore
#endif
hoc_retpushx(retval);
}
Expand Down

0 comments on commit 45fb66a

Please sign in to comment.