CnC
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends
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 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_
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends