File indexing completed on 2025-11-03 09:17:48
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 #ifndef BOOST_COMPUTE_CLOSURE_HPP
0012 #define BOOST_COMPUTE_CLOSURE_HPP
0013 
0014 #include <string>
0015 #include <sstream>
0016 
0017 #include <boost/config.hpp>
0018 #include <boost/fusion/adapted/boost_tuple.hpp>
0019 #include <boost/fusion/algorithm/iteration/for_each.hpp>
0020 #include <boost/mpl/for_each.hpp>
0021 #include <boost/mpl/transform.hpp>
0022 #include <boost/typeof/typeof.hpp>
0023 #include <boost/static_assert.hpp>
0024 #include <boost/algorithm/string.hpp>
0025 #include <boost/tuple/tuple.hpp>
0026 #include <boost/type_traits/function_traits.hpp>
0027 
0028 #include <boost/compute/cl.hpp>
0029 #include <boost/compute/function.hpp>
0030 #include <boost/compute/type_traits/type_name.hpp>
0031 #include <boost/compute/type_traits/detail/capture_traits.hpp>
0032 
0033 namespace boost {
0034 namespace compute {
0035 namespace detail {
0036 
0037 template<class ResultType, class ArgTuple, class CaptureTuple>
0038 class invoked_closure
0039 {
0040 public:
0041     typedef ResultType result_type;
0042 
0043     BOOST_STATIC_CONSTANT(
0044         size_t, arity = boost::tuples::length<ArgTuple>::value
0045     );
0046 
0047     invoked_closure(const std::string &name,
0048                     const std::string &source,
0049                     const std::map<std::string, std::string> &definitions,
0050                     const ArgTuple &args,
0051                     const CaptureTuple &capture)
0052         : m_name(name),
0053           m_source(source),
0054           m_definitions(definitions),
0055           m_args(args),
0056           m_capture(capture)
0057     {
0058     }
0059 
0060     std::string name() const
0061     {
0062         return m_name;
0063     }
0064 
0065     std::string source() const
0066     {
0067         return m_source;
0068     }
0069 
0070     const std::map<std::string, std::string>& definitions() const
0071     {
0072         return m_definitions;
0073     }
0074 
0075     const ArgTuple& args() const
0076     {
0077         return m_args;
0078     }
0079 
0080     const CaptureTuple& capture() const
0081     {
0082         return m_capture;
0083     }
0084 
0085 private:
0086     std::string m_name;
0087     std::string m_source;
0088     std::map<std::string, std::string> m_definitions;
0089     ArgTuple m_args;
0090     CaptureTuple m_capture;
0091 };
0092 
0093 } 
0094 
0095 
0096 template<class Signature, class CaptureTuple>
0097 class closure
0098 {
0099 public:
0100     typedef typename
0101         boost::function_traits<Signature>::result_type result_type;
0102 
0103     BOOST_STATIC_CONSTANT(
0104         size_t, arity = boost::function_traits<Signature>::arity
0105     );
0106 
0107     closure(const std::string &name,
0108             const CaptureTuple &capture,
0109             const std::string &source)
0110         : m_name(name),
0111           m_source(source),
0112           m_capture(capture)
0113     {
0114     }
0115 
0116     ~closure()
0117     {
0118     }
0119 
0120     std::string name() const
0121     {
0122         return m_name;
0123     }
0124 
0125     
0126     std::string source() const
0127     {
0128         return m_source;
0129     }
0130 
0131     
0132     void define(std::string name, std::string value = std::string())
0133     {
0134         m_definitions[name] = value;
0135     }
0136 
0137     
0138     detail::invoked_closure<result_type, boost::tuple<>, CaptureTuple>
0139     operator()() const
0140     {
0141         BOOST_STATIC_ASSERT_MSG(
0142             arity == 0,
0143             "Non-nullary closure function invoked with zero arguments"
0144         );
0145 
0146         return detail::invoked_closure<result_type, boost::tuple<>, CaptureTuple>(
0147             m_name, m_source, m_definitions, boost::make_tuple(), m_capture
0148         );
0149     }
0150 
0151     
0152     template<class Arg1>
0153     detail::invoked_closure<result_type, boost::tuple<Arg1>, CaptureTuple>
0154     operator()(const Arg1 &arg1) const
0155     {
0156         BOOST_STATIC_ASSERT_MSG(
0157             arity == 1,
0158             "Non-unary closure function invoked with one argument"
0159         );
0160 
0161         return detail::invoked_closure<result_type, boost::tuple<Arg1>, CaptureTuple>(
0162             m_name, m_source, m_definitions, boost::make_tuple(arg1), m_capture
0163         );
0164     }
0165 
0166     
0167     template<class Arg1, class Arg2>
0168     detail::invoked_closure<result_type, boost::tuple<Arg1, Arg2>, CaptureTuple>
0169     operator()(const Arg1 &arg1, const Arg2 &arg2) const
0170     {
0171         BOOST_STATIC_ASSERT_MSG(
0172             arity == 2,
0173             "Non-binary closure function invoked with two arguments"
0174         );
0175 
0176         return detail::invoked_closure<result_type, boost::tuple<Arg1, Arg2>, CaptureTuple>(
0177             m_name, m_source, m_definitions, boost::make_tuple(arg1, arg2), m_capture
0178         );
0179     }
0180 
0181     
0182     template<class Arg1, class Arg2, class Arg3>
0183     detail::invoked_closure<result_type, boost::tuple<Arg1, Arg2, Arg3>, CaptureTuple>
0184     operator()(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) const
0185     {
0186         BOOST_STATIC_ASSERT_MSG(
0187             arity == 3,
0188             "Non-ternary closure function invoked with three arguments"
0189         );
0190 
0191         return detail::invoked_closure<result_type, boost::tuple<Arg1, Arg2, Arg3>, CaptureTuple>(
0192             m_name, m_source, m_definitions, boost::make_tuple(arg1, arg2, arg3), m_capture
0193         );
0194     }
0195 
0196 private:
0197     std::string m_name;
0198     std::string m_source;
0199     std::map<std::string, std::string> m_definitions;
0200     CaptureTuple m_capture;
0201 };
0202 
0203 namespace detail {
0204 
0205 struct closure_signature_argument_inserter
0206 {
0207     closure_signature_argument_inserter(std::stringstream &s_,
0208                                         const char *capture_string,
0209                                         size_t last)
0210         : s(s_)
0211     {
0212         n = 0;
0213         m_last = last;
0214 
0215         size_t capture_string_length = std::strlen(capture_string);
0216         BOOST_ASSERT(capture_string[0] == '(' &&
0217                      capture_string[capture_string_length-1] == ')');
0218         std::string capture_string_(capture_string + 1, capture_string_length - 2);
0219         boost::split(m_capture_names, capture_string_ , boost::is_any_of(","));
0220     }
0221 
0222     template<class T>
0223     void operator()(const T&) const
0224     {
0225         BOOST_ASSERT(n < m_capture_names.size());
0226 
0227         
0228         std::string variable_name = m_capture_names[n];
0229 
0230         
0231         boost::trim(variable_name);
0232 
0233         s << capture_traits<T>::type_name() << " " << variable_name;
0234         if(n+1 < m_last){
0235             s << ", ";
0236         }
0237         n++;
0238     }
0239 
0240     mutable size_t n;
0241     size_t m_last;
0242     std::vector<std::string> m_capture_names;
0243     std::stringstream &s;
0244 };
0245 
0246 template<class Signature, class CaptureTuple>
0247 inline std::string
0248 make_closure_declaration(const char *name,
0249                          const char *arguments,
0250                          const CaptureTuple &capture_tuple,
0251                          const char *capture_string)
0252 {
0253     typedef typename
0254         boost::function_traits<Signature>::result_type result_type;
0255     typedef typename
0256         boost::function_types::parameter_types<Signature>::type parameter_types;
0257     typedef typename
0258         mpl::size<parameter_types>::type arity_type;
0259 
0260     std::stringstream s;
0261     s << "inline " << type_name<result_type>() << " " << name;
0262     s << "(";
0263 
0264     
0265     signature_argument_inserter i(s, arguments, arity_type::value);
0266     mpl::for_each<
0267         typename mpl::transform<parameter_types, boost::add_pointer<mpl::_1>
0268     >::type>(i);
0269     s << ", ";
0270 
0271     
0272     closure_signature_argument_inserter j(
0273         s, capture_string, boost::tuples::length<CaptureTuple>::value
0274     );
0275     fusion::for_each(capture_tuple, j);
0276 
0277     s << ")";
0278     return s.str();
0279 }
0280 
0281 
0282 
0283 template<class Signature, class CaptureTuple>
0284 inline closure<Signature, CaptureTuple>
0285 make_closure_impl(const char *name,
0286                   const char *arguments,
0287                   const CaptureTuple &capture,
0288                   const char *capture_string,
0289                   const std::string &source)
0290 {
0291     std::stringstream s;
0292     s << make_closure_declaration<Signature>(name, arguments, capture, capture_string);
0293     s << source;
0294 
0295     return closure<Signature, CaptureTuple>(name, capture, s.str());
0296 }
0297 
0298 } 
0299 } 
0300 } 
0301 
0302 
0303 
0304 
0305 
0306 
0307 
0308 
0309 
0310 
0311 
0312 
0313 
0314 
0315 
0316 
0317 
0318 
0319 
0320 
0321 
0322 
0323 
0324 
0325 
0326 
0327 
0328 
0329 
0330 
0331 
0332 
0333 #ifdef BOOST_COMPUTE_DOXYGEN_INVOKED
0334 #define BOOST_COMPUTE_CLOSURE(return_type, name, arguments, capture, source)
0335 #else
0336 #define BOOST_COMPUTE_CLOSURE(return_type, name, arguments, capture, ...) \
0337     ::boost::compute::closure< \
0338         return_type arguments, BOOST_TYPEOF(boost::tie capture) \
0339     > name = \
0340         ::boost::compute::detail::make_closure_impl< \
0341             return_type arguments \
0342         >( \
0343             #name, #arguments, boost::tie capture, #capture, #__VA_ARGS__ \
0344         )
0345 #endif
0346 
0347 #endif