CnC
|
00001 /* ******************************************************************************* 00002 * Copyright (c) 2007-2014, Intel Corporation 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are met: 00006 * 00007 * * Redistributions of source code must retain the above copyright notice, 00008 * this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of Intel Corporation nor the names of its contributors 00013 * may be used to endorse or promote products derived from this software 00014 * without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 00020 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00021 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00022 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00023 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00024 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00025 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 ********************************************************************************/ 00027 00028 /* 00029 Main include file for using CnC. 00030 Provides all CnC classes except debug things. 00031 See CnC::context for a very brief description on how to write a CnC program. 00032 */ 00033 00034 #ifndef _CnC_H_ALREADY_INCLUDED_ 00035 #define _CnC_H_ALREADY_INCLUDED_ 00036 00037 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 00038 // Workaround for overzealous compiler warnings 00039 # pragma warning (push) 00040 # pragma warning (disable: 4251 4275 4290) 00041 #endif 00042 00043 #include <cnc/internal/tag_collection_base.h> 00044 #include <cnc/internal/item_collection_base.h> 00045 #include <cnc/internal/context_base.h> 00046 #include <cnc/internal/no_range.h> 00047 00048 /// \brief CnC API 00049 namespace CnC { 00050 00051 typedef int error_type; 00052 00053 // forward declarations 00054 template< class T > class context; 00055 struct debug; 00056 template< typename Tag, typename Tuner > class tag_collection; 00057 template< typename Tag, typename Item, typename Tuner > class item_collection; 00058 00059 /// Steps return CNC_Success if execution was successful 00060 const int CNC_Success = 0; 00061 /// Steps return CNC_Failure if execution failed 00062 const int CNC_Failure = 1; 00063 00064 /// \brief A step collection is logical set of step instances. 00065 /// 00066 /// A step-collection must be prescribed by a tag-collection and it 00067 /// can be part of consumer/producer relationships with item-collections. 00068 /// Additionally, it can be the controller in control-dependencies (e.g. produce tags). 00069 template< typename UserStep, typename Tuner = step_tuner<> > 00070 class step_collection : public virtual Internal::traceable 00071 { 00072 public: 00073 /// the type of the step as provided by the user 00074 typedef UserStep step_type; 00075 /// the type of the tuner as provided by the user 00076 typedef Tuner tuner_type; 00077 00078 /// \brief constructor which registers collection with given context 00079 /// 00080 /// \param ctxt the context this collection belongs to 00081 /// \param name an optional name, used for debug output and tracing 00082 /// \param userStep an optional user step argument, a copy will be created through copy-construction 00083 /// \param tnr an optional tuner object which must persist throughout the lifetime of the step-collection 00084 /// by default a default-constructed tuner will be used. 00085 template< typename Derived > 00086 step_collection( context< Derived > & ctxt, const std::string & name, const step_type & userStep, const tuner_type & tnr ); 00087 template< typename Derived > 00088 step_collection( context< Derived > & ctxt ); 00089 template< typename Derived > 00090 step_collection( context< Derived > & ctxt, const std::string & name ); 00091 template< typename Derived > 00092 step_collection( context< Derived > & ctxt, const tuner_type & tnr, const std::string & name = std::string() ); 00093 template< typename Derived > 00094 step_collection( context< Derived > & ctxt, const std::string & name, const step_type & userStep ); 00095 00096 ~step_collection(); 00097 00098 /// Declare this step-collecation as consumer of given item-collection 00099 template< typename DataTag, typename Item, typename ITuner > 00100 void consumes( CnC::item_collection< DataTag, Item, ITuner > & ); 00101 00102 /// Declare this step-collecation as producer for given item-collection 00103 template< typename DataTag, typename Item, typename ITuner > 00104 void produces( CnC::item_collection< DataTag, Item, ITuner > & ); 00105 00106 /// Declare this step-collection as controller of given tag-collection 00107 template< typename ControlTag, typename TTuner > 00108 void controls( CnC::tag_collection< ControlTag, TTuner > & ); 00109 00110 private: 00111 const step_type m_userStep; 00112 const tuner_type & m_tuner; 00113 Internal::distributable_context & m_context; 00114 template< class Tag, class Step, class Arg, class TTuner, class STuner > friend class Internal::step_launcher; 00115 }; 00116 00117 /// \brief A tag collection is a set of tags of the same type. It is 00118 /// used to prescribe steps. By default, tags are not stored. 00119 /// 00120 /// Tag must provide copy and default constructors and the assigment 00121 /// operator. 00122 /// 00123 /// If Tag is not convertable into size_t, a suitable hash_compare 00124 /// class must be provided which satisifies the requirements for 00125 /// tbb::concurrent_hash_map. The default cnc_tag_hash_compare works 00126 /// for types that can be converted to size_t and have an 00127 /// operator==. You can provide specialized templates for 00128 /// cnc_hash and/or cnc_equal or cnc_tag_hash_compare 00129 /// or specify and implement your own compatible class. 00130 template< typename Tag, typename Tuner = tag_tuner<> > 00131 class /*CNC_API*/ tag_collection 00132 { 00133 public: 00134 /// the tag type 00135 typedef Tag tag_type; 00136 00137 /// \brief constructor which registers collection with given context 00138 /// 00139 /// \param ctxt the context this collection belongs to 00140 /// \param name an optional name, used for debug output and tracing 00141 /// \param tnr an optional tuner object which must persist throughout the lifetime of the tag-collection 00142 /// by default a default-constructed tuner will be used. 00143 template< class Derived > 00144 tag_collection( context< Derived > & ctxt, const std::string & name, const Tuner & tnr ); 00145 template< class Derived > 00146 tag_collection( context< Derived > & ctxt, const std::string & name = std::string() ); 00147 template< class Derived > 00148 tag_collection( context< Derived > & ctxt, const Tuner & tnr ); 00149 00150 ~tag_collection(); 00151 00152 /// \brief Declare the prescription relationship between the tag collection 00153 /// and a step collection. 00154 /// 00155 /// \param s class representing step collection. s is required to 00156 /// provide the following const method, where Arg a is the optional 00157 /// parameter described below. 00158 /// 00159 /// \code int execute( const Tag & tag, Arg & a ) const; \endcode 00160 /// 00161 /// A copy of s will be created by calling its copy constructor. 00162 /// 00163 /// \param arg This argument will be the parameter passed to 00164 /// Step::execute and the tuner methods. The object must exist as 00165 /// long as instances of the given step might be executed. Usually 00166 /// arg will be the containing context. 00167 /// 00168 /// \return 0 if succeeded, error code otherwise 00169 template< typename UserStep, typename STuner, typename Arg > 00170 error_type prescribes( const step_collection< UserStep, STuner > & s, Arg & arg ); 00171 00172 /// \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. 00173 /// \param t the tag to be put 00174 void put( const Tag & t ); 00175 00176 /// \brief prescribe an entire range of tags 00177 /// 00178 /// \param r A range, which is potentially splittible through a partitioner. 00179 /// Following the TBB range/splittable concept, extended by STL container requirements, 00180 /// a range R must provide the following interface: 00181 /// - R::R( const R& ) : Copy constructor. 00182 /// - int size() : return number of elements (tags) in range 00183 /// - const_iterator : forward iterator (operator++, operator tag_type() const) 00184 /// to make it work with tbb::blocked_range, the cast operator is used instead of operator*(). 00185 /// - const_iterator begin() const : first member of range 00186 /// - const_iterator end() const : Exclusive upper bound on range 00187 /// Using it with the default_partitioner also requires 00188 /// - R::R( R& r, tbb::split ) : Split r into two subranges. 00189 /// - bool R::is_divisible() const : true if range can be partitioned into two subranges. 00190 void put_range( const typename Tuner::range_type & r ); 00191 void put_range( const Internal::no_range & ) const; 00192 00193 /// const forward iterator as in STL 00194 typedef typename Tuner::tag_table_type::const_iterator const_iterator; 00195 00196 /// \brief returns begin() as in STL containers 00197 /// \note iteration through collections is not thread safe; 00198 /// use it only between calls to CnC::context::wait() and putting tags 00199 const_iterator begin() const; 00200 00201 /// \brief returns end() as in STL containers 00202 /// \note iteration through collections is not thread safe; 00203 /// use it only between calls to CnC::context::wait() and putting tags 00204 const_iterator end() const; 00205 00206 /// \brief removes all of the tag instances from the collection 00207 /// \note not thread-safe, to be called in safe state only 00208 /// (between program start or calling context::wait() and putting the first tag or item). 00209 void unsafe_reset(); 00210 00211 /// returns number of elements in collection 00212 size_t size(); 00213 00214 /// returns true if size()==0, false otherwise 00215 bool empty(); 00216 00217 /// callback type for tag-collections 00218 /// \see register_callback 00219 typedef typename Internal::tag_collection_base< Tag, Tuner >::callback_type callback_type; 00220 00221 /// Call this to register a on-put-callback for the tag-collection. 00222 /// When registered, callback.on_put( tag ) gets called when a tag was put successfully. 00223 /// e.g. it will not get called a second time on a second put if memoization is enabled. 00224 /// The call is blocking, e.g. the triggering/calling "put" will not return to its caller 00225 /// until the callback has terminated. 00226 /// The provided object will be deleted when the collection is deleted. 00227 /// \see graph for more details, in particular about thread-safety issues 00228 /// \note not thread-safe, to be called in safe state only 00229 /// (between program start or calling context::wait() and putting the first tag or item). 00230 /// \note not needed for regular CnC 00231 void on_put( callback_type * cb ); 00232 00233 private: 00234 Internal::tag_collection_base< Tag, Tuner > m_tagCollection; 00235 //template< class T > friend class context; 00236 friend struct ::CnC::debug; 00237 }; 00238 00239 /// \brief An item collection is a mapping from tags to items. 00240 /// 00241 /// Tag and Item must provide copy and default constructors and the 00242 /// assigment operator. 00243 /// 00244 /// Th last template argument is an optional tuner. The tuner provides 00245 /// tuning hints, such as the type of the data store or information about 00246 /// its use in distributed environments. Most importantly it tells the runtime 00247 /// and compiler which type of data store it should use. By default that's 00248 /// a hash-map (hashmap_tuner). For non default-supported tag types (e.g. those that are 00249 /// not convertable into size_t) a suitable cnc_hash template 00250 /// specialization must be provided. If in addition your type does not support std::equal_to 00251 /// you also need to specialize cnc_equal. 00252 /// For the vector-based data store (vector_tuner) that's not 00253 /// necessary, but the tag-type must then be convertible to and from size_t. 00254 /// \see CnC::item_tuner for more information. 00255 /// 00256 /// The CnC runtime will make a copy of your item when it is 'put' into 00257 /// the item_collection. The CnC runtime will delete the copied item 00258 /// copy once the get-count reaches 0 (or, if no get-count was 00259 /// provided, once the collection is destroyed). If the item-type is a 00260 /// pointer type, the runtime will not delete the memory the item 00261 /// points to. If you store pointeres, you have to care for the appropriate 00262 /// garbage collection, e.g. you might consider using smart pointers. 00263 template< typename Tag, typename Item, typename Tuner = hashmap_tuner > 00264 class /*CNC_API*/ item_collection 00265 { 00266 typedef Internal::item_collection_base< Tag, Item, Tuner > base_coll_type; 00267 public: 00268 /// the tag type 00269 typedef Tag tag_type; 00270 /// the data/item type 00271 typedef Item data_type; 00272 00273 /// const forward iterator as in STL 00274 class const_iterator; 00275 00276 /// \brief constructor which registers collection with given context 00277 /// 00278 /// \param ctxt the context this collection belongs to 00279 /// \param name an optional name, used for debug output and tracing 00280 /// \param tnr a tuner object which must persist throughout the lifetime of the step-collection 00281 /// by default a default-constructed tuner will be used. 00282 template< class Derived > 00283 item_collection( context< Derived > & ctxt, const std::string & name, const Tuner & tnr ); 00284 template< class Derived > 00285 item_collection( context< Derived > & ctxt, const std::string & name = std::string() ); 00286 template< class Derived > 00287 item_collection( context< Derived > & ctxt, const Tuner & tnr ); 00288 00289 ~item_collection(); 00290 00291 /// \brief Declares the maxium tag value. 00292 /// 00293 /// Must be called prior to accessing the collection if the data store is a vector. 00294 /// Useful only for dense tag-spaces. 00295 /// \param mx the largest tag-value ever used for this collection 00296 void set_max( size_t mx ); 00297 00298 /// \brief make copies of the item and the tag and store them in the collection. 00299 /// \param tag the tag identifying the item 00300 /// \param item the item to be copied and stored 00301 void put( const Tag & tag, const Item & item ); 00302 00303 /// \brief get an item 00304 /// \param tag the tag identifying the item 00305 /// \param item reference to item to store result in 00306 /// \throw DataNotReady throws exception if data not yet available. 00307 void get( const Tag & tag, Item & item ) const; 00308 00309 /// \brief try to get an item and store it in given object (non-blocking) 00310 /// 00311 /// \attention This method is unsafe: you can create non-deterministic results if you decide to 00312 /// to perform semantically relevant actions if an item is unavailable (returns false) 00313 /// 00314 /// If the item is unavailable, it does not change item. 00315 /// Make sure you call flush_gets() after last call to this method (of any item collection) within a step. 00316 /// In any case, you must check the return value before accessing the item. 00317 /// \param tag the tag identifying the item 00318 /// \param item reference to item to store result in 00319 /// \return true if item is available 00320 /// \throw DataNotReady might throw exception if data not available (yet) 00321 bool unsafe_get( const Tag & tag, Item & item ) const; 00322 00323 /// \brief returns begin() as in STL containers 00324 /// \note iteration through collections is not thread safe; 00325 /// use it only between calls to CnC::context::wait() and putting tags 00326 const_iterator begin() const; 00327 00328 /// \brief returns end() as in STL containers 00329 /// \note iteration through collections is not thread safe; 00330 /// use it only between calls to CnC::context::wait() and putting tags 00331 const_iterator end() const; 00332 00333 /// \brief removes all of the item instances from the collection 00334 /// \note not thread-safe, to be called in safe state only 00335 /// (between program start or calling context::wait() and putting the first tag or item). 00336 void unsafe_reset(); 00337 00338 /// returns number of elements in collection 00339 size_t size(); 00340 00341 /// returns true if size()==0, false otherwise 00342 bool empty(); 00343 00344 /// callback type for item-collections. 00345 /// \see register_callback 00346 typedef typename base_coll_type::callback_type callback_type; 00347 00348 /// Call this to register a on-put-callback for the item-collection. 00349 /// When registered, callback.on_put( tag, item ) gets called when an item was put successfully. 00350 /// The call is blocking, e.g. the triggering/calling "put" will not return to its caller 00351 /// until the callback has terminated. 00352 /// 00353 /// The provided object will be deleted when the collection is deleted. 00354 /// 00355 /// In distCnC, the callback will be executed on the (first) process returned 00356 /// by tuner::consumed_on (which defaults to execution on the process which puts the item). 00357 /// 00358 /// \see graph for more details, in particular about thread-safety issues 00359 /// \note not thread-safe, to be called in safe state only 00360 /// (between program start or calling context::wait() and putting the first tag or item). 00361 /// \note not needed for regular CnC 00362 void on_put( callback_type * cb ); 00363 00364 private: 00365 base_coll_type m_itemCollection; 00366 friend struct ::CnC::debug; 00367 friend class Internal::step_delayer; 00368 friend class const_iterator; 00369 }; 00370 00371 00372 /// \brief Base class for defining and using CnC (sub-)graphs. 00373 /// 00374 /// Derive from this class to define your own graph. It might 00375 /// cooperate with other CnC graphs in the same context. A graph 00376 /// can either be a normal CnC graph or anything else that uses 00377 /// CnC collections as input and output. 00378 /// 00379 /// It is recommended to always use CnC types (e.g. collections) 00380 /// to implement a graph. It facilitates implementation because 00381 /// the CnC semantics allow automatically managing various tasks, 00382 /// like distribution and termination detection. 00383 /// 00384 /// The fundamental communication channel between graphs and their 00385 /// input/output collections are the normal get and put calls. 00386 /// 00387 /// The following paragraphs explain specifics needed to write 00388 /// graphs which do not adhere to core CnC semantics. None of 00389 /// this is needed for graphs that internally are "normal", fully 00390 /// CnC compliant constructs. 00391 /// 00392 /// Besides get calls, tag- and item-collections also provide a 00393 /// callback mechanism. Such callbacks can be registered for any 00394 /// (input) collection individually (item_collection::on_put and 00395 /// tag_collection::on_put). The registered callback will then be 00396 /// called for every incoming item/tag after it was succesfully 00397 /// put. The callback might (or might not) be called 00398 /// asynchronously. 00399 /// 00400 /// \note multiple calls to the same or different callbacks might 00401 /// be issued simultaneously. Hence your callbacks must 00402 /// either have no side effects (other than through CnC) or 00403 /// take care of adequate protection/synchronization 00404 /// 00405 /// \note If your graph executes anything outside of CnC steps or 00406 /// outside callbacks (e.g. if spawns threads or alike), then 00407 /// termination/quiescence handling needs to be addressed 00408 /// explicitly (see graph::enter_quiescence and 00409 /// graph::leave_quiescence). Graphs are born in 00410 /// quiescent state! 00411 /// 00412 /// If you're using non-CnC data structures you will probably need 00413 /// to explicitly take of distributed memory. A clone of the graph 00414 /// gets instantiated on each process. You can send essages between 00415 /// siblings through serializers which get instantiated through 00416 /// graph::new_serializer. After marshalling the desired data 00417 /// (CnC::serializer), the messages can be sent to individual 00418 /// processes (graph::send_msg) or they may be broadcasted 00419 /// (graph::bcast_msg). Messages can only be send from one 00420 /// instance of a graph to its siblings on other processes. 00421 /// Receiving messages is done by overwriting the graph::recv_msg 00422 /// callback. 00423 /// 00424 /// Callbacks are executed on the first process of the list of 00425 /// consumers/executing processes as provided by the collection's 00426 /// tuner. If no consumer/executing process is provided /e.g. the default) 00427 /// the callback is executed on the process where the item/tag is 00428 /// produced. 00429 class graph : public Internal::distributable 00430 { 00431 public: 00432 /// \brief A graph requires a context and a name for its initialization. 00433 /// 00434 /// Do all your initialization/start-up stuff in the 00435 /// constructor of your derived class. This implies that your 00436 /// constructor needs to accept and wire all input-and 00437 /// output-collections. The constructor must also call the 00438 /// respective consumes/produces/prescribes calls. If your 00439 /// graph operates/computes outside the steps and callbacks 00440 /// you need to explicitly handle/manage quiescence (see 00441 /// graph::enter_quiescence, graph::leave_quiescence). 00442 template< typename Ctxt > 00443 graph( CnC::context< Ctxt > & ctxt, const std::string & name = "" ); 00444 00445 virtual ~graph(); 00446 00447 /// \brief Tell the runtime that the graph reached (temporary) quiescence. 00448 /// \note Entering quiescence means that it will not return to activity unless 00449 /// new data arrives through a callback (to be registered with graph::register_callback). 00450 /// \note Explicit quiescence handling is not needed if the graph operates/computes 00451 /// only within the callbacks. 00452 /// \note graphs are born in quiescent state. A call 00453 /// to enter_quiescence must be paired with exactly one preceeding call to leave_quiescence 00454 void enter_quiescence() const; 00455 00456 /// \brief Tell the runtime that the graph leaves quiescence and goes back to activity. 00457 /// Must be called only within a on_put callback (to be 00458 /// registered through item_collection::on_put, 00459 /// tag_collection::on_put) or within a CnC step. Leaving 00460 /// quiescence outside a callback/step leads to undefined 00461 /// behaviour (like dead-locks or worse). 00462 /// \note Explicit quiescence handling is not needed if the 00463 /// graph operates/computes only within the callbacks. 00464 /// \note graphs are born in quiescent state. 00465 void leave_quiescence() const; 00466 00467 /// cleanup, e.g. collect garbage 00468 virtual void cleanup(); 00469 00470 /// reset instance, e.g. remove entries from collection 00471 /// \param dist if false, the current context is actually not distributed -> don't sync with remote siblings 00472 virtual void unsafe_reset( bool dist ); 00473 00474 /// \brief Overwrite this if you need to exchange messages on distributed memory. 00475 /// Each graph must implement its own "protocol" Sending 00476 /// message is done through graph::new_serializer followed by 00477 /// graph::send_msg / graph::bcast_msg. 00478 /// \note not needed for regular CnC 00479 virtual void recv_msg( serializer * ); 00480 00481 /// \brief Get a serializer 00482 /// Caller must pass it to send/bcast or delete it. 00483 /// Receiving messages is done in recv_msg callback. 00484 /// \note not needed for regular CnC 00485 serializer * new_serializer() const; 00486 00487 /// \brief send a message (in serializer) to given recipient 00488 /// Receiving messages is done in recv_msg callback. 00489 /// \note not needed for regular CnC 00490 void send_msg( serializer * ser, int rcver ) const; 00491 00492 /// \brief broadcast message (in serializer) to all (other) ranks/processes 00493 /// Receiving messages is done in recv_msg callback. 00494 /// \note not needed for regular CnC 00495 void bcast_msg( serializer * ser ) const; 00496 00497 /// \brief broadcast message (in serializer) to given recipients 00498 /// Receiving messages is done in recv_msg callback. 00499 /// \note not needed for regular CnC 00500 bool bcast_msg( serializer *ser , const int * rcvers, int nrecvrs ) const; 00501 00502 /// \brief Flush a potentially hidden graph. 00503 /// Usually is a nop. 00504 /// Our reduction uses this to finalize all pending reductions. 00505 /// (e.g. when the number of reduced items per reduction cannot be determined). 00506 /// \note To be called in safe state only 00507 /// (between program start or calling context::wait() and putting the first tag or item). 00508 virtual void flush() {}; 00509 00510 private: 00511 Internal::context_base & m_context; 00512 }; 00513 00514 namespace Internal { 00515 class distributor; 00516 template< class T > class creator; 00517 template< class Index, class Functor, class Tuner, typename Increment > class pfor_context; 00518 } 00519 00520 /** 00521 \brief CnC context bringing together collections (for steps, items and tags). 00522 00523 The user needs to derive his or her own context from the CnC::context. 00524 The template argument to context is the user's context class itself. 00525 00526 For example, 00527 \code 00528 struct my_context : public CnC::context< my_context > 00529 { 00530 CnC::step_collection< FindPrimes > steps; 00531 CnC::tag_collection< int > oddNums; 00532 CnC::item_collection< int,int > primes; 00533 my_context() 00534 : CnC::context< my_context >(), 00535 steps( this ), 00536 oddNums( this ), 00537 primes( this ) 00538 { 00539 oddNums.prescribes( steps ); 00540 } 00541 }; 00542 \endcode 00543 00544 Several contexts can be created and executed simultaneously. 00545 00546 Execution starts as soon as a step(-instance) is prescribed through putting a tag. 00547 All ready steps will be executed even if CnC::context::wait() is never be called. 00548 00549 It is recommended to declare collections as members of a context derived from CnC::context. 00550 This yields more maintanable code and future versions of CnC may require this convention. 00551 **/ 00552 template< class Derived > 00553 class /*CNC_API*/ context : protected Internal::context_base 00554 { 00555 public: 00556 /// default constructor 00557 context(); 00558 /// destructor 00559 virtual ~context(); 00560 00561 /// \brief wait until all the steps prescribed by this context have completed execution. 00562 /// \return 0 if succeeded, error code otherwise 00563 error_type wait(); 00564 00565 /// \brief used with the preschedule tuner to finalize 'gets' in the pre-execution of a step 00566 /// 00567 /// Call this after last call to the non-blocking item_collection::unsafe_get method. 00568 void flush_gets(); 00569 00570 /// reset all collections of this context 00571 /// \note not thread-safe, to be called in safe state only 00572 /// (between program start or calling context::wait() and putting the first tag or item). 00573 void unsafe_reset(); 00574 00575 /// (distCnC) overload this if default construction on remote processes is not enough. 00576 virtual void serialize( serializer & ){} 00577 00578 private: 00579 void init(); 00580 virtual void unsafe_reset( bool ); 00581 context( bool ); 00582 virtual int factory_id(); 00583 template< class Range, class Coll > 00584 void divide_and_put( Range & range, int grain, Coll * coll, Internal::scheduler_i * sched ); 00585 friend struct ::CnC::debug; 00586 friend class ::CnC::Internal::distributor; 00587 friend class ::CnC::tuner_base; 00588 friend class ::CnC::graph; 00589 template< typename Tag, bool check_deps, typename Hasher, typename Equality > friend class ::CnC::cancel_tuner; 00590 template< class T > friend class ::CnC::Internal::creator; 00591 template< class Index, class Functor, class Tuner, typename Increment > friend class ::CnC::Internal::pfor_context; 00592 template< typename Tag, typename Tuner > friend class tag_collection; 00593 template< typename Step, typename Tuner > friend class step_collection; 00594 template< typename Tag, typename Item, typename Tuner > friend class item_collection; 00595 }; 00596 00597 /// \brief Execute f( i ) for every i in {first <= i=first+step*x < last and 0 <= x}. 00598 /// 00599 /// For different values of i, function execution might occur in parallel. 00600 /// Returns functor object ocne all iterations have been executed. 00601 /// Type Index must support operator+(increment) and operator-(Index), like C++ random access iterators do. 00602 /// Executes on the local process only. No distribution to other processes supported. 00603 /// \param first starting index of parallel iteration 00604 /// \param last iteration stops before reaching last 00605 /// \param incr increment index by this value in each iteration 00606 /// \param f function to be executed 00607 /// \param tuner defaults to pfor_tuner<> 00608 template< class Index, class Functor, class Tuner, typename Increment > 00609 void parallel_for( Index first, Index last, Increment incr, const Functor & f, const Tuner & tuner ); 00610 template< class Index, class Functor, typename Increment > 00611 void parallel_for( Index first, Index last, Increment incr, const Functor & f ); 00612 00613 } // namespace cnc 00614 00615 #include <cnc/internal/step_collection.h> 00616 #include <cnc/internal/tag_collection.h> 00617 #include <cnc/internal/item_collection.h> 00618 #include <cnc/internal/graph.h> 00619 #include <cnc/internal/context.h> 00620 #include <cnc/internal/parallel_for.h> 00621 #include <cnc/internal/hash_item_table.h> 00622 #include <cnc/internal/vec_item_table.h> 00623 00624 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 00625 # pragma warning (pop) 00626 # pragma warning( disable : 4355 ) 00627 #endif // warnings 4251 4275 4290 are back, 4355 is hidden 00628 00629 #endif // _CnC_H_ALREADY_INCLUDED_