PFUNC  1.0
pfunc/parallel_for.hpp
Go to the documentation of this file.
00001 #ifndef PFUNC_PARALLEL_FOR_HPP
00002 #define PFUNC_PARALLEL_FOR_HPP
00003 
00004 #include <pfunc/pfunc.hpp>
00005 #include <iostream>
00006 
00007 namespace pfunc {
00008 
00028 template <typename PFuncInstanceType /*type of PFunc instantiated*/,
00029           typename ForExecutable/*type of the function*/,
00030           typename SpaceType /*type of the space*/>
00031 struct parallel_for : pfunc::virtual_functor {
00032   public:
00033   typedef typename PFuncInstanceType::taskmgr TaskMgrType;
00034   typedef typename PFuncInstanceType::task TaskType;
00035 
00036   private:
00037   SpaceType space; 
00038   const ForExecutable& func;
00039   TaskMgrType& taskmgr;
00040 
00041   public:
00050   parallel_for (SpaceType space, 
00051                 const ForExecutable& func,
00052                 TaskMgrType& taskmgr) : space(space), 
00053                                         func(func), 
00054                                         taskmgr (taskmgr) {}
00055 
00056   void operator() (void) {
00057     if (space.can_split ()) {
00058       // Split into subspaces.
00059       typename SpaceType::subspace_container subspaces = space.split ();
00060       assert (1<=SpaceType::arity);
00061 
00062       // Create a vector of tasks for each subspace but the first one.
00063       const int num_tasks = SpaceType::arity-1;
00064       TaskType subspace_tasks [num_tasks];
00065       parallel_for<PFuncInstanceType, ForExecutable, SpaceType>*
00066             subspace_parallel_fors [num_tasks];
00067 
00068       // Save the first task to execute yourself, but do this last.
00069       typename SpaceType::subspace_container::iterator first=subspaces.begin();
00070       space = *first++;
00071 
00072       // Iterate and launch the tasks
00073       int task_index = 0;
00074       while (first != subspaces.end()) {
00075         subspace_parallel_fors [task_index] = new
00076           parallel_for<PFuncInstanceType, ForExecutable, SpaceType> 
00077             (*first++, func, taskmgr);
00078         pfunc::spawn (taskmgr, // the task manager to use
00079                       subspace_tasks[task_index], // task handle
00080                       *(subspace_parallel_fors[task_index])); 
00081         ++task_index;
00082                             // the subspace for this comptn
00083       }
00084 
00085       (*this)(); // executing this loop ourselves.
00086 
00087       // Wait for completion of other tasks
00088       pfunc::wait_all (taskmgr, // the task manager to use
00089                        subspace_tasks, // beginning
00090                        subspace_tasks+num_tasks); // end
00091 
00092       // Delete the subspace_parallel_fors
00093       for (int i=0; i<num_tasks; ++i) delete subspace_parallel_fors[i];
00094     } else {
00095       // No more splitting --- simply invoke the function on the given space.
00096       func (space);
00097     }
00098   }
00099 };
00100 
00101 } // namespace pfunc
00102 
00103 #endif // PFUNC_PARALLEL_FOR_HPP