Example #1
0
int vertex_callback::invoke(io_request *reqs[], int num)
{
	worker_thread *curr_thread = (worker_thread *) thread::get_curr_thread();
	for (int i = 0; i < num; i++) {
		char *req_buf = reqs[i]->get_buf();
		size_t req_size = reqs[i]->get_size();
		assert(this->io == reqs[i]->get_io());
		ext_mem_vertex ext_v(req_buf, req_size, graph->is_directed());
		// If the algorithm doesn't need to get the full information
		// of their neighbors
		if (graph->get_required_neighbor_type() == edge_type::NONE
				// Or the vertex doesn't have neighbors.
				|| (reqs[i]->get_user_data() == NULL
					&& ext_v.get_num_edges(graph->get_required_neighbor_type()) == 0)) {
			// We can run user's code immediately on the vertex.
			compute_vertex &v = graph->get_vertex(ext_v.get_id());
			v.materialize(ext_v);
			v.run(*graph, NULL, 0);
			v.dematerialize();
			delete [] req_buf;
		}
		// We just fetched a vertex, we need to fetch its neighbors to
		// perform computation.
		else if (reqs[i]->get_user_data() == NULL) {
			curr_thread->add_pending_vertex(ext_v);
		}
		else {
			// Now a neighbor has been fetched, now we can do some computation
			// between the original pending vertex and its neighbor.
			pending_vertex *pending
				= (pending_vertex *) reqs[i]->get_user_data();
			compute_vertex &v = graph->get_vertex(
					pending->get_id());
			// We materialize the vertex and perform computation.
			// The callback function is guaranteed to be called in the thread
			// where a request is issued. Since all requests of fetching
			// neighbors are issued by one thread, we don't need to use a lock
			// to protect the pending vertex from concurrent access.
			v.materialize(*pending);
			v.run(*graph, &ext_v, 1);
			v.dematerialize();
			// The buffer contains the info of the neighbor, no we don't need
			// it any more.
			delete [] req_buf;
			pending->complete_neighbor();
			// Once we perform computation on all neighbors. We can destroy
			// the pending vertex.
			if (pending->is_complete())
				pending_vertex::destroy(pending);
		}
	}
	return 0;
}
  static bool rt_valid(DstBlock& dst, SrcBlock const& src)
  {
    VBlock const& vblock = src.get_vblk();
    MBlock const& mblock = src.get_mblk();

    Ext_data<DstBlock, dst_lp>  ext_dst(dst, SYNC_OUT);
    Ext_data<VBlock, vblock_lp> ext_v(vblock, SYNC_IN);
    Ext_data<MBlock, mblock_lp> ext_m(mblock, SYNC_IN);

    if (SD == row && Type_equal<order_type, row2_type>::value ||
	SD == col && Type_equal<order_type, col2_type>::value)
    {
      dimension_type const axis = SD == row ? 1 : 0;
      length_type dst_stride = static_cast<length_type>(abs(ext_dst.stride(axis == 0)));
      length_type m_stride = static_cast<length_type>(abs(ext_m.stride(axis == 0)));
      return 
        // make sure blocks are dense (major stride == minor size)
        (ext_dst.size(axis) == dst_stride) &&
        (ext_m.size(axis) == m_stride) &&
        // ensure unit stride along the dimension opposite the chosen one
	(ext_dst.stride(axis) == 1) &&
	(ext_m.stride(axis) == 1) &&
	(ext_v.stride(0) == 1);
    }
    else
    {
      dimension_type const axis = SD == row ? 0 : 1;
      length_type dst_stride = static_cast<length_type>(abs(ext_dst.stride(axis == 0)));
      length_type m_stride = static_cast<length_type>(abs(ext_m.stride(axis == 0)));
      return 
        // make sure blocks are dense (major stride == minor size)
        (ext_dst.size(axis) == dst_stride) &&
        (ext_m.size(axis) == m_stride) &&
        // ensure unit stride along the same dimension as the chosen one
	(ext_dst.stride(axis) == 1) &&
	(ext_m.stride(axis) == 1) &&
	(ext_v.stride(0) == 1);
    }
  }