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