diff --git a/README.rst b/README.rst index ed27754..ca5a409 100644 --- a/README.rst +++ b/README.rst @@ -76,6 +76,7 @@ On ubuntu you can install these with:: this:: CFLAGS="-std=c++11 \ + -lpthread \ -I/usr/local/Cellar/boost/1.68.0/include/ \ -I/usr/local/include/ \ -L/usr/local/Cellar/boost/1.68.0/lib \ diff --git a/setup.py b/setup.py index 7bb3650..8e34709 100755 --- a/setup.py +++ b/setup.py @@ -233,7 +233,8 @@ def get_extensions(): library_dirs=library_dirs, include_dirs=include_dirs, # Since casacore 3.0.0 we have to be C++11 - extra_compile_args=['-std=c++11'])) + extra_compile_args=['-std=c++11', + '-lpthread'])) return extensions diff --git a/src/guards.h b/src/guards.h new file mode 100644 index 0000000..2c39b86 --- /dev/null +++ b/src/guards.h @@ -0,0 +1,115 @@ +#include + +#include +#include +#include +#include +#include +#include + +namespace details { + +/// @brief Functor that will invoke a function while holding a guard. +/// Upon returning from the function, the guard is released. +template +class guarded_function +{ +public: + + typedef typename boost::function_types::result_type::type + result_type; + + template + guarded_function(Fn fn) + : fn_(fn) + {} + + template + result_type operator()(Args... args) + { + Guard g; + return fn_(args...); + } + +private: + boost::function fn_; +}; + +/// @brief Provides signature type. +template +struct mpl_signature +{ + typedef typename boost::function_types::components::type type; +}; + +// Support boost::function. +template +struct mpl_signature >: + public mpl_signature +{}; + +/// @brief Create a callable object with guards. +template +boost::python::object with_aux(Fn fn, const Policy& policy) +{ + // Obtain the components of the Fn. This will decompose non-member + // and member functions into an mpl sequence. + // R (*)(A1) => R, A1 + // R (C::*)(A1) => R, C*, A1 + typedef typename mpl_signature::type mpl_signature_type; + + // Synthesize the components into a function type. This process + // causes member functions to require the instance argument. + // This is necessary because member functions will be explicitly + // provided the 'self' argument. + // R, A1 => R (*)(A1) + // R, C*, A1 => R (*)(C*, A1) + typedef typename boost::function_types::function_type< + mpl_signature_type>::type signature_type; + + // Create a callable boost::python::object that delegates to the + // guarded_function. + return boost::python::make_function( + guarded_function(fn), + policy, mpl_signature_type()); +} + +} // namespace details + +/// @brief Create a callable object with guards. +template +boost::python::object with(const Fn& fn, const Policy& policy) +{ + return details::with_aux(fn, policy); +} + +/// @brief Create a callable object with guards. +template +boost::python::object with(const Fn& fn) +{ + return with(fn, boost::python::default_call_policies()); +} + +/// @brief Guard that will unlock the GIL upon construction, and +/// reacquire it upon destruction. +struct no_gil +{ +public: + no_gil() { state_ = PyEval_SaveThread(); } + ~no_gil() { PyEval_RestoreThread(state_); } +private: + PyThreadState* state_; +}; + +/// @brief Guard that prints to std::cout. +struct echo_guard +{ + echo_guard() { std::cout << "echo_guard()" << std::endl; } + ~echo_guard() { std::cout << "~echo_guard()" << std::endl; } +}; diff --git a/src/pytable.cc b/src/pytable.cc index 2fec487..d6c1041 100755 --- a/src/pytable.cc +++ b/src/pytable.cc @@ -33,6 +33,7 @@ #include #include +#include "guards.h" using namespace boost::python; @@ -139,91 +140,20 @@ namespace casacore { namespace python { .def ("_iscelldefined", &TableProxy::cellContentsDefined, (boost::python::arg("columnname"), boost::python::arg("rownr"))) - .def ("_getcell", &TableProxy::getCell, - (boost::python::arg("columnname"), - boost::python::arg("rownr"))) - .def ("_getcellvh", &TableProxy::getCellVH, - (boost::python::arg("columnname"), - boost::python::arg("rownr"), - boost::python::arg("value"))) - .def ("_getcellslice", &TableProxy::getCellSliceIP, - (boost::python::arg("columnname"), - boost::python::arg("rownr"), - boost::python::arg("blc"), - boost::python::arg("trc"), - boost::python::arg("inc"))) - .def ("_getcellslicevh", &TableProxy::getCellSliceVHIP, - (boost::python::arg("columnname"), - boost::python::arg("rownr"), - boost::python::arg("blc"), - boost::python::arg("trc"), - boost::python::arg("inc"), - boost::python::arg("value"))) - .def ("_getcol", &TableProxy::getColumn, - (boost::python::arg("columnname"), - boost::python::arg("startrow"), - boost::python::arg("nrow"), - boost::python::arg("rowincr"))) - .def ("_getcolvh", &TableProxy::getColumnVH, - (boost::python::arg("columnname"), - boost::python::arg("startrow"), - boost::python::arg("nrow"), - boost::python::arg("rowincr"), - boost::python::arg("value"))) - .def ("_getvarcol", &TableProxy::getVarColumn, - (boost::python::arg("columnname"), - boost::python::arg("startrow"), - boost::python::arg("nrow"), - boost::python::arg("rowincr"))) - .def ("_getcolslice", &TableProxy::getColumnSliceIP, - (boost::python::arg("columnname"), - boost::python::arg("blc"), - boost::python::arg("trc"), - boost::python::arg("inc"), - boost::python::arg("startrow"), - boost::python::arg("nrow"), - boost::python::arg("rowincr"))) - .def ("_getcolslicevh", &TableProxy::getColumnSliceVHIP, - (boost::python::arg("columnname"), - boost::python::arg("blc"), - boost::python::arg("trc"), - boost::python::arg("inc"), - boost::python::arg("startrow"), - boost::python::arg("nrow"), - boost::python::arg("rowincr"), - boost::python::arg("value"))) - .def ("_putcell", &TableProxy::putCell, - (boost::python::arg("columnname"), - boost::python::arg("rownr"), - boost::python::arg("value"))) - .def ("_putcellslice", &TableProxy::putCellSliceIP, - (boost::python::arg("columnname"), - boost::python::arg("rownr"), - boost::python::arg("value"), - boost::python::arg("blc"), - boost::python::arg("trc"), - boost::python::arg("inc"))) - .def ("_putcol", &TableProxy::putColumn, - (boost::python::arg("columnname"), - boost::python::arg("startrow"), - boost::python::arg("nrow"), - boost::python::arg("rowincr"), - boost::python::arg("value"))) - .def ("_putvarcol", &TableProxy::putVarColumn, - (boost::python::arg("columnname"), - boost::python::arg("startrow"), - boost::python::arg("nrow"), - boost::python::arg("rowincr"), - boost::python::arg("value"))) - .def ("_putcolslice", &TableProxy::putColumnSliceIP, - (boost::python::arg("columnname"), - boost::python::arg("value"), - boost::python::arg("blc"), - boost::python::arg("trc"), - boost::python::arg("inc"), - boost::python::arg("startrow"), - boost::python::arg("nrow"), - boost::python::arg("rowincr"))) + .def ("_getcell", with(&TableProxy::getCell)) + .def ("_getcellvh", with(&TableProxy::getCellVH)) + .def ("_getcellslice", with(&TableProxy::getCellSliceIP)) + .def ("_getcellslicevh", with(&TableProxy::getCellSliceVHIP)) + .def ("_getcol", with(&TableProxy::getColumn)) + .def ("_getcolvh", with(&TableProxy::getColumnVH)) + .def ("_getvarcol", with(&TableProxy::getVarColumn)) + .def ("_getcolslice", with(&TableProxy::getColumnSliceIP)) + .def ("_getcolslicevh", with(&TableProxy::getColumnSliceVHIP)) + .def ("_putcell", with(&TableProxy::putCell)) + .def ("_putcellslice", with(&TableProxy::putCellSliceIP)) + .def ("_putcol", with(&TableProxy::putColumn)) + .def ("_putvarcol", with(&TableProxy::putVarColumn)) + .def ("_putcolslice", with(&TableProxy::putColumnSliceIP)) .def ("_getcolshapestring", &TableProxy::getColumnShapeString, (boost::python::arg("columnname"), boost::python::arg("startrow"), diff --git a/src/tables.cc b/src/tables.cc index b214a9e..80af618 100755 --- a/src/tables.cc +++ b/src/tables.cc @@ -32,15 +32,18 @@ #include #include #include +#include #include #include #include #include +#include BOOST_PYTHON_MODULE(_tables) { + casacore::python::registerNotThreadSafeException(); casacore::python::register_convert_excp(); casacore::python::register_convert_basicdata(); casacore::python::register_convert_casa_valueholder();