CnC
cnc.h
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_