//************************************************************************************************* // OSSIM // // License: MIT // // Author: Oscar Kramer // //************************************************************************************************* // $Id$ #ifndef ossimImageChainMtAdaptor_HEADER #define ossimImageChainMtAdaptor_HEADER #include #include #include #include #include //************************************************************************************************* //! This class supports multi-threading of image chain getTile() requests and associated chain //! updating. It accepts an original ossimImageChain object which is then cloned (replicated). //! One clone per thread is created, counting the original as clone(0), with all clones //! sharing a common input handler (if directed) so that disk access is serialized and thread-safe. //************************************************************************************************* class OSSIMDLLEXPORT ossimImageChainMtAdaptor : public ossimImageChain { friend class ossimMultiThreadSequencer; //### FOR DEBUG ONLY public: ossimImageChainMtAdaptor(); //! Full constructor accepts the original image chain to clone. //! @param num_threads Total number of cloned chains to make available. //! ossimImageChainMtAdaptor(ossimImageChain* original, ossim_uint32 num_threads=0); ~ossimImageChainMtAdaptor(); //! Alternate way of specifying number of threads to support. This is the same as the number of //! clones that will be available after replicating the original chain. //! @param num_threads Total number of cloned chains to make available. void setNumberOfThreads(ossim_uint32 num_threads); //! Alternate way of specifying the original chain being adapted for multi-threading. //! @param original Image chain to be adapted. void setOriginalChain(ossimImageChain* original); //! Intercepts the getTile because it should never be called directly. The tile request must go //! to the specific chain clone. virtual ossimRefPtr getTile(const ossimIrect& tileRect, ossim_uint32 resLevel=0); //! Adapts call to original chain so that all clones are initialized. virtual void initialize(); //! Adapts call to original chain so that clones are replicated after original's loadState. virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=NULL); //! Adapts call to original chain so that adapter-specific keywords can be added to KWL. virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=NULL)const; //! Adapts the image chain event handler. If the event involves a change to the original image //! chain, then the clones will need to be regenerated here. virtual void processEvent(ossimEvent& event); //! Returns pointer to a specific clone image chain, or NULL if index exceeds the max available. //! The clone at index=0 corresponds to the original, though this detail should be ignored. ossimImageSource* getClone(ossim_uint32 index); //! Returns the number of clones available. The original chain always counts as the first clone. ossim_uint32 getNumberOfClones() const { return (ossim_uint32) m_clones.size(); } //! These overriding access methods greatly facilitate the implementation of an image chain //! adapter class operating on the member original chain. These methods really should be //! "protected" but the compiler complains if the base class declarations are "protected". virtual ossimConnectableObject::ConnectableObjectList& imageChainList(); virtual const ossimConnectableObject::ConnectableObjectList& imageChainList() const; //! Overrides base class implementation in order to make the connection to each clone. This //! connection is typically to the multi-thread sequencer object. virtual ossim_int32 connectMyOutputTo(ossimConnectableObject* outputObject, bool makeInputConnection=true, bool createEventFlag=true); protected: //! Deletes instances of all replicas from the clone list and leaves only the original. void deleteReplicas(); //! Creates clones of original and pushes them onto the clone list. Returns TRUE if successful. bool replicate(); //! Manages reconnecting shared image handlers to a cloned image chain (identified by index) //! after its creation. This is in support of shared image handlers. Returns TRUE if successful. bool connectSharedHandlers(ossim_uint32 index); //! This is the adaptee image chain. ossimRefPtr m_adaptedChain; //! List of replicated child chains' first source (the one receiving the getTile call). The //! first in the list is always the original (adaptee) source. These are owned by the //! m_chainContainers that are maintained here. std::vector< ossimRefPtr > m_clones; //! The container objects must be kept alive in this vector while their child chains in //! m_clones are used. Containers are used because they are the only way of "duping" a complete //! chain with all connections properly done. The containers need to persist in order for the //! chain connections to be maintained (apparent bug in connectable object code). I found it //! impossible to dissociate the chain from its container. As soon as the container disappeared, //! the chain's internal connections would be disrupted. (OLK 11/11) std::vector< ossimRefPtr > m_chainContainers; //! List of handlers that are being shared among all clones (if requested). It is a list since //! the original chain may involve a combiner with multiple image inputs. typedef std::vector > SharedHandlerList; SharedHandlerList m_sharedHandlers; ossim_uint32 m_numThreads; bool d_useSharedHandlers; bool d_debugEnabled; }; #endif /* #ifndef ossimImageChain_HEADER */