portable_issue.hpp

Go to the documentation of this file.
00001 /*
00002 This file is part of GraphLab.
00003 
00004 GraphLab is free software: you can redistribute it and/or modify
00005 it under the terms of the GNU Lesser General Public License as 
00006 published by the Free Software Foundation, either version 3 of 
00007 the License, or (at your option) any later version.
00008 
00009 GraphLab is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU Lesser General Public License for more details.
00013 
00014 You should have received a copy of the GNU Lesser General Public 
00015 License along with GraphLab.  If not, see <http://www.gnu.org/licenses/>.
00016 */
00017 
00018 #ifndef PORTABLE_ISSUE_HPP
00019 #define PORTABLE_ISSUE_HPP
00020 #include <graphlab/rpc/function_call_issue.hpp>
00021 #include <graphlab/rpc/request_issue.hpp>
00022 #include <graphlab/rpc/portable.hpp>
00023 #include <graphlab/rpc/dc_send.hpp>
00024 #include <graphlab/util/generics/any.hpp>
00025 #include <graphlab/rpc/is_rpc_call.hpp>
00026 #include <graphlab/rpc/function_arg_types_def.hpp>
00027 #include <boost/preprocessor.hpp>
00028 namespace graphlab{
00029 namespace dc_impl {
00030 
00031 /**
00032 \ingroup rpc_internal
00033  \file
00034  
00035  This is an internal function and should not be used directly
00036  
00037 This is a partial specialization of the remote_call_issue classes
00038 described in function_call_issue.hpp and request_issue.hpp to handle the portable calls
00039 A portable call permits function calls across different binaries, but required
00040 registration.
00041 
00042 Portable Call Formats \n
00043 ===================== \n
00044 The format of a "portable call" packet is in the form of an archive and is as follows
00045 
00046 \li size_t(NULL)     -- NULL. Corresponds to the dispatch_type* in the native call
00047 \li  std::string      -- name of the function to call
00048 \li  char(0)          -- flag that this is a call
00049 \li  fn::arg1_type    -- target function's 1st argument
00050 \li  fn::arg2_type    -- target function's 2nd argument
00051 \li ...
00052 \li  fn::argN_type    -- target function's Nth argument
00053 
00054 Unlike the native call, argument casting is performed by the caller. The caller is
00055 required to know the type of the function (At least through a function prototype)
00056 
00057 ---------\n
00058 The format of a "portable request" packet is in the form of an archive and is as follows
00059 \li  size_t(NULL)     -- NULL. Corresponds to the dispatch_type* in the native call
00060 \li  std::string      -- name of the function to call
00061 \li  char(1)          -- flag that this is a request
00062 \li  fn::arg1_type    -- target function's 1st argument
00063 \li  fn::arg2_type    -- target function's 2nd argument
00064 \li   ...
00065 \li  fn::argN_type    -- target function's Nth argument
00066 
00067 Unlike the native call, argument casting is performed by the caller. The caller is
00068 required to know the type of the function (At least through a function prototype)
00069 At the end of the request, the dispatch will perform a fast call to the
00070  reply_increment_counter on the source machine passing the ID as an argument.
00071  The return data is passed using the actual result type of the function.
00072 
00073 \see function_call_issue.hpp
00074 */
00075 
00076 #define GENARGS(Z,N,_)  BOOST_PP_CAT(const T, N) BOOST_PP_CAT(&i, N)
00077 #define GENARC(Z,N,_) arc << ( typename BOOST_PP_CAT(get_cleaned_user_arg, N)<F>::arg_type ) BOOST_PP_CAT(i, N);
00078 
00079 #define PORTABLE_CALL_ISSUE_GENERATOR(Z,N,FNAME_AND_CALL) \
00080 template<typename F BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, typename T) > \
00081   class BOOST_PP_CAT(FNAME_AND_CALL,N)<portable_call<F> BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, T)> { \
00082    public: \
00083     static void exec(dc_send* sender, unsigned char flags, procid_t target, portable_call<F> remote_function BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM(N,GENARGS ,_)  ) {   \
00084     boost::iostreams::stream<resizing_array_sink_ref> &strm = get_thread_local_stream();    \
00085       oarchive arc(strm);                           \
00086       arc << 0;       \
00087       arc << remote_function.fname;      \
00088       arc << char(0);    \
00089       BOOST_PP_REPEAT(N, GENARC, _)                \
00090         strm.flush();                   \
00091       sender->send_data(target,  flags, strm->c_str(), strm->size());    \
00092     }  \
00093   };
00094 
00095 
00096 BOOST_PP_REPEAT(6, PORTABLE_CALL_ISSUE_GENERATOR, remote_call_issue)
00097 //BOOST_PP_REPEAT(6, PORTABLE_CALL_ISSUE_GENERATOR, basic_call_issue)
00098 
00099 
00100 #define PORTABLE_REQUEST_ISSUE_GENERATOR(Z,N,FNAME_AND_CALL) \
00101 template<typename F BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, typename T) > \
00102   class BOOST_PP_CAT(FNAME_AND_CALL,N)<portable_call<F> BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM_PARAMS(N, T)> { \
00103    public: \
00104     static typename function_ret_type<__GLRPC_FRESULT>::type  exec(dc_send* sender, unsigned char flags, procid_t target, portable_call<F> remote_function BOOST_PP_COMMA_IF(N) BOOST_PP_ENUM(N,GENARGS ,_)  ) {   \
00105     boost::iostreams::stream<resizing_array_sink_ref> &strm = get_thread_local_stream();    \
00106     oarchive arc(strm);                         \
00107     reply_ret_type reply(REQUEST_WAIT_METHOD);      \
00108     size_t fn = 0; \
00109     arc << fn;       \
00110     arc << remote_function.fname; \
00111     arc << char(1);       \
00112     arc << reinterpret_cast<size_t>(&reply);       \
00113     BOOST_PP_REPEAT(N, GENARC, _)                \
00114     strm.flush();           \
00115     sender->send_data(target, flags, strm->c_str(), strm->size());    \
00116     reply.wait(); \
00117     boost::iostreams::stream<boost::iostreams::array_source> retstrm(reply.val.c, reply.val.len);    \
00118     iarchive iarc(retstrm);  \
00119     typename function_ret_type<__GLRPC_FRESULT>::type  result; \
00120     iarc >> result;  \
00121     reply.val.free(); \
00122     return result;  \
00123     }  \
00124   };
00125 
00126 BOOST_PP_REPEAT(6, PORTABLE_REQUEST_ISSUE_GENERATOR, remote_request_issue)
00127 
00128 #undef GENARC
00129 #undef GENARGS
00130 #undef PORTABLE_CALL_ISSUE_GENERATOR
00131 #undef PORTABLE_REQUEST_ISSUE_GENERATOR
00132 
00133 #include <graphlab/rpc/function_arg_types_undef.hpp>
00134 
00135 } // namespace dc_impl
00136 } // namespace graphlab
00137 
00138 #endif
00139