cnc.h

00001 //********************************************************************************
00002 // Copyright 2007-2010 Intel Corporation All Rights Reserved.                   **
00003 //                                                                              **
00004 // The source code contained or described herein and all documents related to   **
00005 // the source code ("Material") are owned by Intel Corporation or its suppliers **
00006 // or licensors. Title to the Material remains with Intel Corporation or its    **
00007 // suppliers and licensors. The Material contains trade secrets and proprietary **
00008 // and confidential information of Intel or its suppliers and licensors. The    **
00009 // Material is protected by worldwide copyright and trade secret laws and       **
00010 // treaty provisions. No part of the Material may be used, copied, reproduced,  **
00011 // modified, published, uploaded, posted, transmitted, distributed, or          **
00012 // disclosed in any way without Intel's prior express written permission.       **
00013 //                                                                              **
00014 // No license under any patent, copyright, trade secret or other intellectual   **
00015 // property right is granted to or conferred upon you by disclosure or delivery **
00016 // of the Materials, either expressly, by implication, inducement, estoppel or  **
00017 // otherwise. Any license under such intellectual property rights must be       **
00018 // express and approved by Intel in writing.                                    **
00019 //********************************************************************************
00020 
00021 #ifndef _CnC_H_
00022 #define _CnC_H_
00023 
00024 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
00025     // Workaround for overzealous compiler warnings 
00026 # pragma warning (push)
00027 # pragma warning (disable: 4251 4275)
00028 #endif
00029 
00030 
00031 #include <cnc/internal/tag_collection_base.h>
00032 #include <cnc/internal/item_collection_base.h>
00033 #include <cnc/internal/context_base.h>
00034 #include <cnc/internal/no_range.h>
00035 
00036 namespace CnC {
00037 
00038     typedef int error_type;
00039     // forward declaration
00040     template< class T > class context;
00041     struct debug;
00042 
00043     /// Steps return CNC_Success if execution was successful
00044     const int CNC_Success = 0;
00045     /// Steps return CNC_Failure if execution failed
00046     const int CNC_Failure = 1;
00047 
00048     /// \brief A tag collection is a set of tags of the same type. It is
00049     /// used to prescribe steps.  By default, it is not stored.
00050     ///
00051     /// Tag must provide copy and default constructors and the assigment
00052     /// operator.
00053     ///
00054     /// If Tag is not convertable into size_t, a suitable hash_compare
00055     /// class must be provided which satisifies the requirements for
00056     /// tbb::concurrent_hash_map.  The default cnc_tag_hash_compare works
00057     /// for types that can be converted to size_t and have an
00058     /// operator==. You can provide a specialized template for
00059     /// cnc_tag_hash_compare or specify and implement your own compatible
00060     /// class.
00061     template< typename Tag, typename Range = Internal::no_range, typename hash_compare = cnc_tag_hash_compare< Tag > >
00062     class /*CNC_API*/ tag_collection
00063     {
00064     public:
00065         /// the tag type
00066         typedef Tag tag_type;
00067 
00068         /// const forward iterator as in STL
00069         class const_iterator;
00070 
00071         /// \brief constructor which registers collection with given context
00072         ///
00073         /// \param ctxt the context this collection belongs to
00074         /// \param preserveTags when requested, the tag collection can preserve tags, by default tags are not stored
00075         template< class Derived >
00076         tag_collection( context< Derived > * ctxt, bool preserveTags = false );
00077 
00078         /// \brief prescribe the associated step.  If we are preserving tags for this collection, make a copy of the tag and store it in the collection.
00079         /// \param  t the tag to be put
00080         void put( const Tag & t );
00081 
00082         /// \brief prescribe an entire range of tags
00083         ///
00084         /// \param r  A range, which is potentially splittible through a partitioner.
00085         ///           Following the TBB range/splittable concept, extended by STL container requirements, 
00086         ///           a range R must provide the following interface:
00087         ///              - R::R( const R& ) : Copy constructor.
00088         ///              - bool R::empty() const : true if range is empty.
00089         ///              - bool R::is_divisible() const : true if range can be partitioned into two subranges.
00090         ///              - R::R( R& r, tbb::split ) : Split r into two subranges.
00091         ///              - const_iterator : forward iterator (operator++, operator tag_type() const)
00092         ///                                 to make it work with tbb::blocked_range, the cast operator is used instead of operator*().
00093         ///              - const_iterator begin() : first member of range
00094         ///              - const_iterator end() : Exclusive upper bound on range
00095         /// \param part optionally a partitioner can be specified, \see default_partitioner for the expected interface
00096         void put_range( const Range & r );
00097         void put_range( const Internal::no_range & ) const;
00098 
00099         /// \brief Declare the prescription relationship between a tag collection
00100         /// and a step collection.
00101         ///
00102         /// \param s class representing step collection. s is required to
00103         /// provide the following const method, where Arg a is the optional
00104         /// parameter described below.
00105         ///   \code
00106         ///   int execute( const Tag & tag, Arg & a ) const;
00107         ///   \endcode
00108         /// A copy of s will be created by calling its copy constructor.
00109         ///
00110         /// \param tuner You can use default_tuner or define your own tuner to
00111         /// specify the scheduling priority for the excution of a step, and also
00112         /// the data dependencies for the step.
00113         ///
00114         /// \param arg This argument will be the parameter passed to
00115         ///            Step::execute and the tuner methods.  The object must exist as
00116         ///            long as instances of the given step might be executed. Usually
00117         ///            arg will be the containing context.
00118         ///
00119         /// \return 0 if succeeded, error code otherwise
00120         template< typename Step, typename Tuner, typename Arg >
00121         error_type prescribe( const Step & s, const Tuner & t, Arg & arg );
00122 
00123         /// \brief returns begin() as in STL containers
00124         /// \note iteration through collections is not thread safe, use it only between calls to CnC::context::wait() and putting tags
00125         const_iterator begin() const;
00126 
00127         /// \brief returns end() as in STL containers
00128         /// \note iteration through collections is not thread safe, use it only between calls to CnC::context::wait() and putting tags
00129         const_iterator end() const;
00130 
00131         /// \brief removes all of the tag instances from the collection
00132         void reset();
00133 
00134         /// returns number of elements in collection
00135         size_t size();
00136 
00137         /// returns true if size()==0, false otherwise
00138         bool empty();
00139 
00140     private:
00141         Internal::tag_collection_base< Tag, Range, hash_compare > m_tagCollection;
00142         //template< class T > friend class context;
00143         friend struct ::CnC::debug;
00144     };
00145 
00146     /// \brief An item collection is a mapping from tags to items.
00147     ///
00148     /// Tag and Item must provide copy and default constructors and the
00149     /// assigment operator.
00150     ///
00151     /// If Tag is not convertable into size_t, a suitable
00152     /// cnc_tag_hash_compare struct must be provided which satisifies the
00153     /// requirements for tbb::concurrent_hash_map. The default
00154     /// cnc_tag_hash_compare works for types that can be converted to
00155     /// size_t and have an operator==. You can provide a specialized
00156     /// template for cnc_tag_hash_compare or specify and implement your own
00157     /// compatible class.
00158     /// 
00159     /// The CnC runtime will make a copy of your item when it is 'put' into
00160     /// the item_collection.  The CnC runtime will delete the copied item
00161     /// copy once the get-count reaches 0 (or, if no get-count was
00162     /// provided, once the collection is destroyed).  If the item-type is a
00163     /// pointer type, the runtime will not delete the memory the item
00164     /// points to.  
00165     template< typename Tag, typename Item, typename hash_compare = cnc_tag_hash_compare< Tag > >
00166     class /*CNC_API*/ item_collection
00167     {
00168     public:
00169         /// the tag type
00170         typedef Tag tag_ype;
00171 
00172         /// const forward iterator as in STL
00173         class const_iterator;
00174 
00175         /// \brief constructor which registers collection with given context
00176         ///
00177         /// \param ctxt the context this collection belongs to
00178         template< class Derived >
00179         item_collection( context< Derived > * ctxt );
00180 
00181         /// \brief make copies of the item and the tag and store them in the collection.
00182         /// \param tag        the tag identifying the item
00183         /// \param item       the item to be copied and stored
00184         /// \param get_count  after get_count many 'get()'s the item can be removed
00185         ///                  by default, the item is not removed until the collection is deleted.
00186         void put( const Tag & tag, const Item & item, int get_count = -1 );
00187 
00188         /// \brief get an item
00189         /// \param  tag the tag identifying the item
00190         /// \param  item reference to item to store result in
00191         /// \throw DataNotReady throws exception if data not yet available.
00192         void get( const Tag & tag, Item & item ) const;
00193 
00194         /// \brief try to get an item and store it in given object (non-blocking)
00195         ///        
00196         /// \attention This method is unsafe: you can create non-deterministic results if you decide to 
00197         ///            to perform semantically relevant actions if an item is unavailable (returns false)
00198         ///
00199         /// If the item is unavailable, it does not change item.
00200         /// Make sure you call flush_gets() after last call to this method (of any item collection) within a step.
00201         /// In any case, you must check the return value before accessing the item.
00202         /// \param  tat the tag identifying the item
00203         /// \param  item reference to item to store result in
00204         /// \return true if item is available
00205         /// \throw DataNotReady might throw exception if data not available (yet)
00206         bool unsafe_get( const Tag & t, Item & i ) const;
00207 
00208         /// \brief returns begin() as in STL containers
00209         /// \note iteration through collections is not thread safe, use it only between calls to CnC::context::wait() and putting tags
00210         const_iterator begin() const;
00211 
00212         /// \brief returns end() as in STL containers
00213         /// \note iteration through collections is not thread safe, use it only between calls to CnC::context::wait() and putting tags
00214         const_iterator end() const;
00215 
00216         /// \brief removes all of the item instances from the collection
00217         void reset();
00218 
00219         /// returns number of elements in collection
00220         size_t size();
00221 
00222         /// returns true if size()==0, false otherwise
00223         bool empty();
00224 
00225     private:
00226         Internal::item_collection_base< Tag, Item, hash_compare > m_itemCollection;
00227         friend struct ::CnC::debug;
00228         friend class Internal::step_delayer;
00229         friend class const_iterator;
00230     };
00231 
00232     namespace Internal {
00233         class distributor;
00234         template< class T > class creator;
00235     }
00236 
00237     /// \brief CnC context bringing together collections and steps and
00238     /// specifies the prescription relationship.
00239     ///
00240     /// The user needs to derive his or her own context from the CnC::context.
00241     /// The template argument to context is the user's context class itself.
00242     ///
00243     /// For example,
00244     /// @code
00245     ///   struct my_context : public CnC::context< my_context >
00246     ///   {
00247     ///      CnC::tag_collection<int> oddNums;
00248     ///      CnC::item_collection<int,int> primes;
00249     ///      my_context() 
00250     ///          : CnC::context< my_context >(),
00251     ///            oddNums( this ),
00252     ///            primes( this )
00253     ///      {
00254     ///          prescribe( oddNums, FindPrimes() );
00255     ///      }
00256     ///   };
00257     /// @endcode
00258     ///
00259     /// Several contexts can be created and executed simultaneously.
00260     ///
00261     /// Execution starts as soon as a step is prescribed.
00262     /// All ready steps will be executed even if CnC::context::wait() is never be called.
00263     ///
00264     /// It is recommended to declare collections as members of a context derived from CnC::context.
00265     /// This yields more maintanable code and future versions of CnC may require this convention.
00266     template< class Derived >
00267     class /*CNC_API*/ context : private Internal::context_base
00268     {
00269     public:
00270         /// default constructor
00271         context();
00272         /// destructor
00273         virtual ~context() {}
00274 
00275         /// \brief Convenient was to declare the prescription relationship between a tag
00276         /// collection and a step collection.
00277         ///
00278         /// \see tag_collection::prescribe
00279         ///
00280         /// \param step class/object representing step collection. 
00281         /// \param tuner is optional.  By default this argument is CnC:default_tuner. 
00282         /// \param arg is optional.  By default this argument is the derived context class. 
00283         /// \return 0 if succeeded, error code otherwise
00284         ///
00285         // default template arguments for functions not available before C++0X, need to replicate 'prescribe'
00286         template< typename TagColl, typename Step, typename Tuner, typename Arg >
00287         error_type prescribe( TagColl & tc, const Step & step, const Tuner & tuner, Arg & arg );
00288         template< typename TagColl, typename Step, typename Tuner >
00289         error_type prescribe( TagColl & tc, const Step & step, const Tuner & tuner);
00290         template< typename TagColl, typename Step >
00291         error_type prescribe( TagColl & tc, const Step & step );
00292 
00293         /// \brief wait until all the steps prescribed by this context have completed execution.
00294         /// \return 0 if succeeded, error code otherwise
00295         error_type wait();
00296 
00297         /// \brief used with the preschedule tuner to finalize 'gets' in the pre-execution of a step
00298         ///
00299         /// Call this after last call to the non-blocking item_collection::unsafe_get method.
00300         void flush_gets();
00301 
00302         /// reset all collections of this context
00303         void reset();
00304 
00305         /// \brief Execute f( i ) for every i in {first <= i=first+step*x < last and 0 <= x}.
00306         ///
00307         /// For different values of i, function execution might occur in parallel.
00308         /// Returns functor object ocne all iterations have been executed.
00309         /// Type Index must support operator+.
00310         /// It uses the tuner default_tuner< Index, derived >
00311         /// \param first  starting index of parallel iteration
00312         /// \param last   iteration stops before reaching last
00313         /// \param step   iteration step: increase ireation index by step in each iteration
00314         /// \param f      function to be executed
00315         /// \param gets_items      true (default) if function gets items, false otherwise (might perform better)
00316         template< class Index, class Functor >
00317         Functor parallel_for( Index first, Index last, Index step, const Functor & f, bool gets_items = true );
00318 
00319         /// \brief Execute f( i ) for every i in {first <= i=first+step*x < last and 0 <= x}.
00320         ///
00321         /// For different values of i, function execution might occur in parallel.
00322         /// Returns functor object ocne all iterations have been executed.
00323         /// Type Index must support operator+.
00324         /// \param first  starting index of parallel iteration
00325         /// \param last   iteration stops before reaching last
00326         /// \param step   iteration step: increase ireation index by step in each iteration
00327         /// \param f      function to be executed
00328         /// \param tuner  tuner, must accept Index as tag and derived as Arg
00329         template< class Index, class Functor, class Tuner >
00330         Functor parallel_for( Index first, Index last, Index step, const Functor & f, const Tuner & tuner );
00331 
00332     private:
00333         virtual int factory_id();
00334         template< class Range, class Coll >
00335         void divide_and_put( Range & range, int grain, Coll * coll, Internal::scheduler_i * sched );
00336         friend struct ::CnC::debug;
00337         friend class ::CnC::Internal::distributor;
00338         template< class T > friend class ::CnC::Internal::creator;
00339     };
00340 
00341     /// \brief Execute f( i ) for every i in {first <= i=first+step*x < last and 0 <= x}.
00342     ///
00343     /// For different values of i, function execution might occur in parallel.
00344     /// Returns functor object ocne all iterations have been executed.
00345     /// Type Index must support operator+.
00346     /// \param first  starting index of parallel iteration
00347     /// \param last   iteration stops before reaching last
00348     /// \param f      function to be executed
00349     /// \param gets_items  true (default) if function gets items, false otherwise (might perform better)
00350     template< class Index, class Functor >
00351     Functor parallel_for( Index first, Index last, Index step, const Functor & f, bool gets_items = true );
00352 
00353 } // namespace cnc
00354 
00355 #include <cnc/internal/tag_collection.h>
00356 #include <cnc/internal/item_collection.h>
00357 #include <cnc/internal/context.h>
00358 #include <cnc/internal/parallel_for.h>
00359 
00360 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
00361 # pragma warning (pop)
00362 # pragma warning( disable : 4355 )
00363 #endif // warnings 4251 4275 are back, 4355 is hidden
00364 
00365 #endif // _CnC_H_

Generated on Tue Aug 31 15:30:27 2010 for CnC by  doxygen 1.5.6