3636#include < graphlab/vertex_program/icontext.hpp>
3737#include < graphlab/graph/distributed_graph.hpp>
3838#include < graphlab/util/generics/conditional_addition_wrapper.hpp>
39+ #include < graphlab/util/generics/test_function_or_functor_type.hpp>
40+
3941#include < graphlab/util/generics/any.hpp>
4042#include < graphlab/util/timer.hpp>
4143#include < graphlab/util/mutable_queue.hpp>
@@ -174,7 +176,6 @@ namespace graphlab {
174176 map_reduce_type (VertexMapperType map_vtx_function,
175177 FinalizerType finalize_function)
176178 : map_vtx_function(map_vtx_function),
177- map_edge_function (NULL ),
178179 finalize_function (finalize_function), vertex_map(true ) { }
179180
180181 /* *
@@ -184,8 +185,7 @@ namespace graphlab {
184185 map_reduce_type (EdgeMapperType map_edge_function,
185186 FinalizerType finalize_function,
186187 bool )
187- : map_vtx_function(NULL ),
188- map_edge_function(map_edge_function),
188+ : map_edge_function(map_edge_function),
189189 finalize_function(finalize_function), vertex_map(false ) { }
190190
191191
@@ -310,6 +310,74 @@ namespace graphlab {
310310 mutable_queue<std::string, float > schedule;
311311 mutex schedule_lock;
312312 size_t ncpus;
313+
314+ template <typename ReductionType, typename F>
315+ static void test_vertex_mapper_type (std::string key = " " ) {
316+ bool test_result = test_function_or_const_functor_2<F,
317+ ReductionType (icontext_type&,
318+ const vertex_type&),
319+ ReductionType,
320+ icontext_type&,
321+ const vertex_type&>::value;
322+ if (!test_result) {
323+ std::stringstream strm;
324+ strm << " \n " ;
325+ if (key.empty ()) {
326+ strm << " Vertex Map Function does not pass strict runtime type checks. \n " ;
327+ }
328+ else {
329+ strm << " Map Function in Vertex Aggregator " << key
330+ << " does not pass strict runtime type checks. \n " ;
331+ }
332+ if (boost::is_function<typename boost::remove_pointer<F>::type>::value) {
333+ strm
334+ << " Function prototype should be \n "
335+ << " \t ReductionType f(icontext_type&, const vertex_type&)\n " ;
336+ }
337+ else {
338+ strm << " Functor's operator() prototype should be \n "
339+ << " \t ReductionType operator()(icontext_type&, const vertex_type&) const\n " ;
340+ }
341+ strm << " If you are not intentionally violating the abstraction,"
342+ << " we recommend fixing your function for safety reasons" ;
343+ strm.flush ();
344+ logstream (LOG_WARNING ) << strm.str () << std::endl;
345+ }
346+ }
347+
348+ template <typename ReductionType, typename F>
349+ static void test_edge_mapper_type (std::string key = " " ) {
350+ bool test_result = test_function_or_const_functor_2<F,
351+ ReductionType (icontext_type&,
352+ const edge_type&),
353+ ReductionType,
354+ icontext_type&,
355+ const edge_type&>::value;
356+
357+ if (!test_result) {
358+ std::stringstream strm;
359+ strm << " \n " ;
360+ if (key.empty ()) {
361+ strm << " Edge Map Function does not pass strict runtime type checks. \n " ;
362+ }
363+ else {
364+ strm << " Map Function in Edge Aggregator " << key
365+ << " does not pass strict runtime type checks. \n " ;
366+ }
367+ if (boost::is_function<typename boost::remove_pointer<F>::type>::value) {
368+ strm << " Function prototype should be \n "
369+ << " \t ReductionType f(icontext_type&, const edge_type&)\n " ;
370+ }
371+ else {
372+ strm << " Functor's operator() prototype should be "
373+ << " \t ReductionType operator()(icontext_type&, const edge_type&) const\n " ;
374+ }
375+ strm << " If you are not intentionally violating the abstraction,"
376+ << " we recommend fixing your function for safety reasons" ;
377+ logstream (LOG_WARNING ) << strm.str () << std::endl;
378+ }
379+ }
380+
313381 public:
314382
315383
@@ -330,6 +398,12 @@ namespace graphlab {
330398 FinalizerType finalize_function) {
331399 if (key.length () == 0 ) return false ;
332400 if (aggregators.count (key) == 0 ) {
401+
402+ if (rmi.procid () == 0 ) {
403+ // do a runtime type check
404+ test_vertex_mapper_type<ReductionType, VertexMapperType>(key);
405+ }
406+
333407 aggregators[key] = new map_reduce_type<ReductionType,
334408 VertexMapperType,
335409 typename default_map_types<ReductionType>::edge_map_type,
@@ -386,6 +460,10 @@ namespace graphlab {
386460 FinalizerType finalize_function) {
387461 if (key.length () == 0 ) return false ;
388462 if (aggregators.count (key) == 0 ) {
463+ if (rmi.procid () == 0 ) {
464+ // do a runtime type check
465+ test_edge_mapper_type<ReductionType, EdgeMapperType>(key);
466+ }
389467 aggregators[key] = new map_reduce_type<ReductionType,
390468 typename default_map_types<ReductionType>::vertex_map_type,
391469 EdgeMapperType,
@@ -862,6 +940,12 @@ namespace graphlab {
862940 template <typename ResultType, typename MapFunctionType>
863941 ResultType map_reduce_vertices (MapFunctionType mapfunction) {
864942 ASSERT_MSG (graph.is_finalized (), " Graph must be finalized" );
943+
944+ if (rmi.procid () == 0 ) {
945+ // do a runtime type check
946+ test_vertex_mapper_type<ResultType, MapFunctionType>();
947+ }
948+
865949 rmi.barrier ();
866950 bool global_result_set = false ;
867951 ResultType global_result = ResultType ();
@@ -910,6 +994,12 @@ namespace graphlab {
910994 template <typename ResultType, typename MapFunctionType>
911995 ResultType map_reduce_edges (MapFunctionType mapfunction) {
912996 ASSERT_MSG (graph.is_finalized (), " Graph must be finalized" );
997+
998+ if (rmi.procid () == 0 ) {
999+ // do a runtime type check
1000+ test_edge_mapper_type<ResultType, MapFunctionType>();
1001+ }
1002+
9131003 rmi.barrier ();
9141004 bool global_result_set = false ;
9151005 ResultType global_result = ResultType ();
0 commit comments