00001
00002
00003
00004
00005 #ifndef GIL_070107_HPP
00006 # define GIL_070107_HPP
00007
00008 # include <boost/python/make_function.hpp>
00009 # include <boost/python/def_visitor.hpp>
00010 # include <boost/python/signature.hpp>
00011 # include <boost/mpl/at.hpp>
00012
00013
00014
00015
00016 struct allow_threading_guard
00017 {
00018 allow_threading_guard()
00019 : save(PyEval_SaveThread())
00020 {}
00021
00022 ~allow_threading_guard()
00023 {
00024 PyEval_RestoreThread(save);
00025 }
00026
00027 PyThreadState* save;
00028 };
00029
00030 struct lock_gil
00031 {
00032 lock_gil()
00033 : state(PyGILState_Ensure())
00034 {}
00035
00036 ~lock_gil()
00037 {
00038 PyGILState_Release(state);
00039 }
00040
00041 PyGILState_STATE state;
00042 };
00043
00044 template <class F, class R>
00045 struct allow_threading
00046 {
00047 allow_threading(F fn)
00048 : fn(fn)
00049 {}
00050
00051 template <class A0>
00052 R operator()(A0& a0)
00053 {
00054 allow_threading_guard guard;
00055 return (a0.*fn)();
00056 }
00057
00058 template <class A0, class A1>
00059 R operator()(A0& a0, A1& a1)
00060 {
00061 allow_threading_guard guard;
00062 return (a0.*fn)(a1);
00063 }
00064
00065 template <class A0, class A1, class A2>
00066 R operator()(A0& a0, A1& a1, A2& a2)
00067 {
00068 allow_threading_guard guard;
00069 return (a0.*fn)(a1,a2);
00070 }
00071
00072 template <class A0, class A1, class A2, class A3>
00073 R operator()(A0& a0, A1& a1, A2& a2, A3& a3)
00074 {
00075 allow_threading_guard guard;
00076 return (a0.*fn)(a1,a2,a3);
00077 }
00078
00079 template <class A0, class A1, class A2, class A3, class A4>
00080 R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4)
00081 {
00082 allow_threading_guard guard;
00083 return (a0.*fn)(a1,a2,a3,a4);
00084 }
00085
00086 template <class A0, class A1, class A2, class A3, class A4, class A5>
00087 R operator()(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4, A5& a5)
00088 {
00089 allow_threading_guard guard;
00090 return (a0.*fn)(a1,a2,a3,a4,a5);
00091 }
00092
00093 F fn;
00094 };
00095
00096 template <class F>
00097 struct visitor : boost::python::def_visitor<visitor<F> >
00098 {
00099 visitor(F fn)
00100 : fn(fn)
00101 {}
00102
00103 template <class Class, class Options, class Signature>
00104 void visit_aux(
00105 Class& cl, char const* name
00106 , Options const& options, Signature const& signature) const
00107 {
00108 typedef typename boost::mpl::at_c<Signature,0>::type return_type;
00109
00110 cl.def(
00111 name
00112 , boost::python::make_function(
00113 allow_threading<F, return_type>(fn)
00114 , options.policies()
00115 , options.keywords()
00116 , signature
00117 )
00118 );
00119 }
00120
00121 template <class Class, class Options>
00122 void visit(Class& cl, char const* name, Options const& options) const
00123 {
00124 this->visit_aux(
00125 cl, name, options
00126 , boost::python::detail::get_signature(fn, (typename Class::wrapped_type*)0)
00127 );
00128 }
00129
00130 F fn;
00131 };
00132
00133
00134
00135 template <class F>
00136 visitor<F> allow_threads(F fn)
00137 {
00138 return visitor<F>(fn);
00139 }
00140
00141
00142
00143 #endif // GIL_070107_HPP
00144