LCOV - code coverage report
Current view: top level - co - object.h (source / functions) Hit Total Coverage
Test: Collage Lines: 11 13 84.6 %
Date: 2018-01-09 16:37:03 Functions: 11 13 84.6 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2017, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *
       5             :  * This file is part of Collage <https://github.com/Eyescale/Collage>
       6             :  *
       7             :  * This library is free software; you can redistribute it and/or modify it under
       8             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       9             :  * by the Free Software Foundation.
      10             :  *
      11             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      13             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      14             :  * details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public License
      17             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      18             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             :  */
      20             : 
      21             : #ifndef CO_OBJECT_H
      22             : #define CO_OBJECT_H
      23             : 
      24             : #include <co/dispatcher.h> // base class
      25             : #include <co/localNode.h>  // used in RefPtr
      26             : #include <co/types.h>      // for Nodes
      27             : #include <co/version.h>    // used as default parameter
      28             : 
      29             : namespace co
      30             : {
      31             : namespace detail
      32             : {
      33             : class Object;
      34             : }
      35             : class ObjectCM;
      36             : typedef lunchbox::RefPtr<ObjectCM> ObjectCMPtr;
      37             : 
      38             : #define CO_COMMIT_NEXT LB_UNDEFINED_UINT32 //!< the next commit incarnation
      39             : 
      40             : /**
      41             :  * A distributed object.
      42             :  *
      43             :  * Please refer to the Equalizer Programming Guide and examples on how to
      44             :  * develop and use distributed objects. The Serializable implements a typical
      45             :  * common use case based on the basic Object.
      46             :  */
      47             : class Object : public Dispatcher
      48             : {
      49             : public:
      50             :     /** Object change handling characteristics, see Programming Guide */
      51             :     enum ChangeType
      52             :     {
      53             :         NONE,      //!< @internal
      54             :         STATIC,    //!< non-versioned, unbuffered, static object.
      55             :         INSTANCE,  //!< use only instance data
      56             :         DELTA,     //!< use pack/unpack delta
      57             :         UNBUFFERED //!< versioned, but don't retain versions
      58             :     };
      59             : 
      60             :     /** Destruct the distributed object. @version 1.0 */
      61             :     CO_API virtual ~Object();
      62             : 
      63             :     /** @name Data Access */
      64             :     //@{
      65             :     /**
      66             :      * @return true if the object is attached (mapped or registered).
      67             :      * @version 1.0
      68             :      */
      69             :     CO_API bool isAttached() const;
      70             : 
      71             :     /** @return the local node to which this object is attached. @version 1.0 */
      72             :     CO_API LocalNodePtr getLocalNode();
      73             : 
      74             :     /**
      75             :      * Set the object's unique identifier.
      76             :      *
      77             :      * Only to be called on unattached objects. The application has to
      78             :      * ensure the uniqueness of the identifier in the peer-to-peer node
      79             :      * network. By default, each object has an identifier guaranteed to be
      80             :      * unique. During mapping, the identifier of the object will be
      81             :      * overwritten with the identifier of the master object.
      82             :      * @version 1.0
      83             :      */
      84             :     CO_API void setID(const uint128_t& identifier);
      85             : 
      86             :     /** @return the object's unique identifier. @version 1.0 */
      87             :     CO_API const uint128_t& getID() const;
      88             : 
      89             :     /** @return the node-wide unique object instance identifier. @version 1.0 */
      90             :     CO_API uint32_t getInstanceID() const;
      91             : 
      92             :     /** @internal @return if this object keeps instance data buffers. */
      93             :     CO_API bool isBuffered() const;
      94             : 
      95             :     /**
      96             :      * @return true if this instance is a registered master version.
      97             :      * @version 1.0
      98             :      */
      99             :     CO_API bool isMaster() const;
     100             :     //@}
     101             : 
     102             :     /** @name Versioning */
     103             :     //@{
     104             :     /** @return how the changes are to be handled. @version 1.0 */
     105           0 :     virtual ChangeType getChangeType() const { return STATIC; }
     106             :     /**
     107             :      * Limit the number of queued versions on slave instances.
     108             :      *
     109             :      * Changing the return value of this method causes the master instance
     110             :      * to block during commit() if any slave instance has reached the
     111             :      * maximum number of queued versions. The method is called on the slave
     112             :      * instance. Multiple slave instances may use different values.
     113             :      *
     114             :      * Changing the return value at runtime, that is, after the slave
     115             :      * instance has been mapped is unsupported and causes undefined
     116             :      * behavior.
     117             :      *
     118             :      * Not supported on master instances for slave object commits. Open an
     119             :      * issue if you need this.
     120             :      *
     121             :      * @return the number of queued versions a slave instance may have.
     122             :      * @version 1.0
     123             :      */
     124         143 :     virtual uint64_t getMaxVersions() const
     125             :     {
     126         143 :         return std::numeric_limits<uint64_t>::max();
     127             :     }
     128             : 
     129             :     /**
     130             :      * Return the compressor to be used for data transmission.
     131             :      *
     132             :      * This default implementation uses a heuristic to choose the best lossless
     133             :      * compressor in terms of speed and compression ratio. The application may
     134             :      * override this method to deactivate compression by returning the default
     135             :      * pression::Data::CompressorInfo or to select object-specific compressors.
     136             :      * @version 1.6
     137             :      */
     138             :     CO_API virtual CompressorInfo chooseCompressor() const;
     139             : 
     140             :     /**
     141             :      * Return if this object needs a commit.
     142             :      *
     143             :      * This function is used for optimization, to detect early that no
     144             :      * commit is needed. If it returns true, pack() or getInstanceData()
     145             :      * will be executed. The serialization methods can still decide to not
     146             :      * write any data, upon which no new version will be created. If it
     147             :      * returns false, commit() will exit early.
     148             :      *
     149             :      * @return true if a commit is needed.
     150             :      * @version 1.0
     151             :      */
     152         114 :     virtual bool isDirty() const { return true; }
     153             :     /**
     154             :      * Push the instance data of the object to the given nodes.
     155             :      *
     156             :      * Used to push object data from a Node, instead of pulling it during
     157             :      * mapping. Does not establish any mapping, that is, the receiving side
     158             :      * will typically use LocalNode::mapObject with VERSION_NONE to
     159             :      * establish a slave mapping. LocalNode::objectPush() is called once for
     160             :      * each node in the nodes list.
     161             :      *
     162             :      * Buffered objects do not reserialize their instance data. Multicast
     163             :      * connections are preferred, that is, for a set of nodes sharing one
     164             :      * multicast connection the data is only send once.
     165             :      *
     166             :      * @param groupID An identifier to group a set of push operations.
     167             :      * @param objectType A per-push identifier.
     168             :      * @param nodes The vector of nodes to push to.
     169             :      * @version 1.0
     170             :      */
     171             :     CO_API void push(const uint128_t& groupID, const uint128_t& objectType,
     172             :                      const Nodes& nodes);
     173             : 
     174             :     /**
     175             :      * Commit a new version of this object.
     176             :      *
     177             :      * Objects using the change type STATIC can not be committed.
     178             :      *
     179             :      * Master instances will increment new versions continuously, starting at
     180             :      * VERSION_FIRST. If the object has not changed, no new version will
     181             :      * be generated, that is, the current version is returned. The high
     182             :      * value of the returned version will always be 0.
     183             :      *
     184             :      * Slave objects can be committed, but have certain caveats for
     185             :      * serialization. Please refer to the Equalizer Programming Guide for
     186             :      * details. Slave object commits will return a random version on a
     187             :      * successful commit, or VERSION_NONE if the object has not changed since
     188             :      * the last commit. The high value of a successful slave commit will never
     189             :      * be 0.
     190             :      *
     191             :      * The incarnation count is meaningful for buffered master objects. The
     192             :      * commit implementation will keep all instance data committed with an
     193             :      * incarnation count newer than <code>current_incarnation -
     194             :      * getAutoObsolete()</code>. By default, each call to commit creates a new
     195             :      * incarnation, retaining the data from last getAutoObsolete() commit
     196             :      * calls. When the application wishes to auto obsolete by another metric
     197             :      * than commit calls, it has to consistently provide a corresponding
     198             :      * incarnation counter. Buffers with a higher incarnation count than the
     199             :      * current are discarded. A typical use case is to tie the auto obsoletion
     200             :      * to an application-specific frame loop. Decreasing the incarnation counter
     201             :      * will lead to undefined results.
     202             :      *
     203             :      * @param incarnation the commit incarnation for auto obsoletion.
     204             :      * @return the new head version (master) or commit id (slave).
     205             :      * @version 1.0
     206             :      */
     207             :     CO_API virtual uint128_t commit(
     208             :         const uint32_t incarnation = CO_COMMIT_NEXT);
     209             : 
     210             :     /**
     211             :      * Automatically obsolete old versions.
     212             :      *
     213             :      * The versions for the last count incarnations are retained for the
     214             :      * buffered object types INSTANCE and DELTA.
     215             :      *
     216             :      * @param count the number of incarnations to retain.
     217             :      * @version 1.0
     218             :      */
     219             :     CO_API void setAutoObsolete(const uint32_t count);
     220             : 
     221             :     /** @return get the number of retained incarnations. @version 1.0 */
     222             :     CO_API uint32_t getAutoObsolete() const;
     223             : 
     224             :     /**
     225             :      * Sync to a given version.
     226             :      *
     227             :      * Objects using the change type STATIC can not be synced.
     228             :      *
     229             :      * Syncing to VERSION_HEAD syncs all received versions, does not block and
     230             :      * always returns true. Syncing to VERSION_NEXT applies one new version,
     231             :      * potentially blocking. Syncing to VERSION_NONE does nothing.
     232             :      *
     233             :      * Slave objects can be synced to VERSION_HEAD, VERSION_NEXT or to any past
     234             :      * or future version generated by a commit on the master instance. Syncing
     235             :      * to a concrete version applies all pending versions up to this version and
     236             :      * potentially blocks if given a future version.
     237             :      *
     238             :      * Master objects can only be synced to VERSION_HEAD, VERSION_NEXT or to
     239             :      * any version generated by a commit on a slave instance. Syncing to a
     240             :      * concrete version applies only this version and potentially blocks.
     241             :      *
     242             :      * The different sync semantics for concrete versions originate from the
     243             :      * fact that master versions are continous and ordered, while slave
     244             :      * versions are random and unordered.
     245             :      *
     246             :      * This function is not thread safe, that is, calling sync()
     247             :      * simultaneously on the same object from multiple threads has to be
     248             :      * protected by the caller using a mutex.
     249             :      *
     250             :      * @param version the version to synchronize (see above).
     251             :      * @return the last version applied.
     252             :      * @version 1.0
     253             :      */
     254             :     CO_API virtual uint128_t sync(const uint128_t& version = VERSION_HEAD);
     255             : 
     256             :     /** @return the latest available (head) version. @version 1.0 */
     257             :     CO_API uint128_t getHeadVersion() const;
     258             : 
     259             :     /** @return the currently synchronized version. @version 1.0 */
     260             :     CO_API uint128_t getVersion() const;
     261             : 
     262             :     /**
     263             :      * Notification that a new head version was received by a slave object.
     264             :      *
     265             :      * The notification is called from the receiver thread, which is different
     266             :      * from the node main thread. The object cannot be sync()'ed from this
     267             :      * notification, as this might lead to deadlocks and synchronization issues
     268             :      * with the application thread changing the object. It should signal the
     269             :      * application, which then takes the appropriate action. Do not perform any
     270             :      * potentially blocking operations from this method.
     271             :      *
     272             :      * @param version The new head version.
     273             :      * @version 1.0
     274             :      */
     275             :     CO_API virtual void notifyNewHeadVersion(const uint128_t& version);
     276             : 
     277             :     /**
     278             :      * Notification that a new version was received by a master object.
     279             :      * The same constraints as for notifyNewHeadVersion() apply.
     280             :      * @version 1.0
     281             :      */
     282           0 :     virtual void notifyNewVersion() {}
     283             :     //@}
     284             : 
     285             :     /** @name Serialization methods for instantiation and versioning. */
     286             :     //@{
     287             :     /**
     288             :      * Serialize all instance information of this distributed object.
     289             :      *
     290             :      * @param os The output stream.
     291             :      * @version 1.0
     292             :      */
     293           2 :     virtual void getInstanceData(DataOStream& os LB_UNUSED) {}
     294             :     /**
     295             :      * Deserialize the instance data.
     296             :      *
     297             :      * This method is called during object mapping to populate slave
     298             :      * instances with the master object's data.
     299             :      *
     300             :      * @param is the input stream.
     301             :      * @version 1.0
     302             :      */
     303           3 :     virtual void applyInstanceData(DataIStream& is LB_UNUSED) {}
     304             :     /**
     305             :      * Serialize the modifications since the last call to commit().
     306             :      *
     307             :      * No new version will be created if no data is written to the output
     308             :      * stream.
     309             :      *
     310             :      * @param os the output stream.
     311             :      * @version 1.0
     312             :      */
     313           2 :     virtual void pack(DataOStream& os) { getInstanceData(os); }
     314             :     /**
     315             :      * Deserialize a change.
     316             :      *
     317             :      * @param is the input data stream.
     318             :      * @version 1.0
     319             :      */
     320           2 :     virtual void unpack(DataIStream& is) { applyInstanceData(is); }
     321             :     //@}
     322             : 
     323             :     /** @name Messaging API */
     324             :     //@{
     325             :     /**
     326             :      * Send a command with optional data to object instance(s) on another
     327             :      * node.
     328             :      *
     329             :      * The returned command can be used to pass additional data. The data
     330             :      * will be send after the command object is destroyed, aka when it is
     331             :      * running out of scope.
     332             :      *
     333             :      * @param node the node where to send the command to.
     334             :      * @param cmd the object command to execute.
     335             :      * @param instanceID the object instance(s) which should handle the command.
     336             :      * @return the command object to pass additional data to.
     337             :      * @version 1.0
     338             :      */
     339             :     CO_API ObjectOCommand send(NodePtr node, const uint32_t cmd,
     340             :                                const uint32_t instanceID = CO_INSTANCE_ALL);
     341             :     //@}
     342             : 
     343             :     /** @name Notifications */
     344             :     /**
     345             :      * Notify that this object will be registered or mapped.
     346             :      *
     347             :      * The method is called from the thread initiating the registration or
     348             :      * mapping, before the operation is executed.
     349             :      * @version 1.0
     350             :      */
     351          51 :     virtual void notifyAttach() {}
     352             :     /**
     353             :      * Notify that this object has been registered or mapped.
     354             :      *
     355             :      * The method is called from the thread initiating the registration or
     356             :      * mapping, after the operation has been completed successfully.
     357             :      * @sa isMaster()
     358             :      * @version 1.0
     359             :      */
     360          49 :     virtual void notifyAttached() {}
     361             :     /**
     362             :      * Notify that this object will be deregistered or unmapped.
     363             :      *
     364             :      * The method is called from the thread initiating the deregistration or
     365             :      * unmapping, before the operation is executed.
     366             :      * @sa isMaster()
     367             :      * @version 1.0
     368             :      */
     369             :     CO_API virtual void notifyDetach();
     370             : 
     371             :     /**
     372             :      * Notify that this object has been deregistered or unmapped.
     373             :      *
     374             :      * The method is called from the thread initiating the deregistration or
     375             :      * unmapping, after the operation has been executed.
     376             :      * @version 1.0
     377             :      */
     378          50 :     virtual void notifyDetached() {}
     379             :     //@}
     380             : 
     381             :     /** @internal */
     382             :     //@{
     383             :     /** @internal @return the master object instance identifier. */
     384             :     uint32_t getMasterInstanceID() const;
     385             : 
     386             :     /** @internal @return the master object instance identifier. */
     387             :     CO_API NodePtr getMasterNode();
     388             : 
     389             :     /** @internal */
     390             :     CO_API void removeSlave(NodePtr node, const uint32_t instanceID);
     391             :     CO_API void removeSlaves(NodePtr node); //!< @internal
     392             :     void setMasterNode(NodePtr node);       //!< @internal
     393             :     /** @internal */
     394             :     void addInstanceDatas(const ObjectDataIStreamDeque&, const uint128_t&);
     395             : 
     396             :     /**
     397             :      * @internal
     398             :      * Setup the change manager.
     399             :      *
     400             :      * @param type the type of the change manager.
     401             :      * @param master true if this object is the master.
     402             :      * @param localNode the node the object will be attached to.
     403             :      * @param masterInstanceID the instance identifier of the master object,
     404             :      *                         used when master == false.
     405             :      */
     406             :     void setupChangeManager(const Object::ChangeType type, const bool master,
     407             :                             LocalNodePtr localNode,
     408             :                             const uint32_t masterInstanceID);
     409             : 
     410             :     /** @internal Called when object is attached from the receiver thread. */
     411             :     CO_API virtual void attach(const uint128_t& id, const uint32_t instanceID);
     412             :     /**
     413             :      * @internal Called when the object is detached from the local node from the
     414             :      * receiver thread.
     415             :      */
     416             :     CO_API virtual void detach();
     417             : 
     418             :     /** @internal Transfer the attachment from the given object. */
     419             :     void transfer(Object* from);
     420             : 
     421             :     void applyMapData(const uint128_t& version); //!< @internal
     422             :     void sendInstanceData(const Nodes& nodes);   //!< @internal
     423             :     //@}
     424             : 
     425             : protected:
     426             :     /** Construct a new distributed object. @version 1.0 */
     427             :     CO_API Object();
     428             : 
     429             :     /** NOP assignment operator. @version 1.0 */
     430             :     Object& operator=(const Object&) { return *this; }
     431             :     /** Copy construct a new, unattached object. @version 1.0 */
     432             :     CO_API explicit Object(const Object&);
     433             : 
     434             : private:
     435             :     detail::Object* const impl_;
     436             :     void _setChangeManager(ObjectCMPtr cm);
     437             : 
     438             :     ObjectCMPtr _getChangeManager();
     439             :     friend class ObjectStore;
     440             : 
     441         102 :     LB_TS_VAR(_thread);
     442             : };
     443             : 
     444             : /** Output information about the object to the given stream. @version 1.0 */
     445             : CO_API std::ostream& operator<<(std::ostream&, const Object&);
     446             : 
     447             : /** Output object change type in human-readably form. @version 1.0 */
     448             : CO_API std::ostream& operator<<(std::ostream&, const Object::ChangeType&);
     449             : }
     450             : 
     451             : #endif // CO_OBJECT_H

Generated by: LCOV version 1.11