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_
1.5.6