LCOV - code coverage report
Current view: top level - eq/fabric - object.h (source / functions) Hit Total Coverage
Test: Equalizer Lines: 37 52 71.2 %
Date: 2017-12-16 05:07:20 Functions: 49 100 49.0 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2016, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *                          Daniel Nachbaur <danielnachbaur@gmail.com>
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or modify it under
       6             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       7             :  * by the Free Software Foundation.
       8             :  *
       9             :  * This library is distributed in the hope that it will be useful, but WITHOUT
      10             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      11             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      12             :  * details.
      13             :  *
      14             :  * You should have received a copy of the GNU Lesser General Public License
      15             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      16             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             :  */
      18             : 
      19             : #ifndef EQFABRIC_OBJECT_H
      20             : #define EQFABRIC_OBJECT_H
      21             : 
      22             : #include <co/objectOCommand.h> // used inline send()
      23             : #include <co/objectVersion.h>  // member
      24             : #include <co/serializable.h>   // base class
      25             : #include <eq/fabric/api.h>
      26             : #include <eq/fabric/error.h> // enum
      27             : #include <eq/fabric/types.h>
      28             : 
      29             : namespace eq
      30             : {
      31             : namespace fabric
      32             : {
      33             : namespace detail
      34             : {
      35             : class Object;
      36             : }
      37             : 
      38             : /**
      39             :  * Internal base class for all distributed, inheritable Equalizer objects.
      40             :  *
      41             :  * This class provides common data storage used by all Equalizer resource
      42             :  * entities. Do not subclass directly.
      43             :  */
      44             : class Object : public co::Serializable
      45             : {
      46             : public:
      47             :     /** @name Data Access. */
      48             :     //@{
      49             :     /** Set the name of the object. @version 1.0 */
      50             :     EQFABRIC_API virtual void setName(const std::string& name);
      51             : 
      52             :     /** @return the name of the object. @version 1.0 */
      53             :     EQFABRIC_API const std::string& getName() const;
      54             : 
      55             :     /**
      56             :      * Set user-specific data.
      57             :      *
      58             :      * Registration, mapping, commit and sync of the user data object are
      59             :      * automatically executed when committing and syncing this object. Not all
      60             :      * instances of the object have to set a user data object. All instances
      61             :      * have to set the same type of object.
      62             :      * @version 1.0
      63             :      */
      64             :     EQFABRIC_API void setUserData(co::Object* userData);
      65             : 
      66             :     /** @return the user-specific data. @version 1.0 */
      67             :     EQFABRIC_API co::Object* getUserData();
      68             : 
      69             :     /** @return the user-specific data. @version 1.0 */
      70             :     EQFABRIC_API const co::Object* getUserData() const;
      71             :     //@}
      72             : 
      73             :     /** @name Data Access */
      74             :     //@{
      75             :     /**
      76             :      * Return the set of tasks this channel might execute in the worst case.
      77             :      *
      78             :      * It is not guaranteed that all the tasks will be actually executed during
      79             :      * rendering.
      80             :      *
      81             :      * @return the tasks.
      82             :      * @warning Experimental - may not be supported in the future
      83             :      */
      84             :     EQFABRIC_API uint32_t getTasks() const;
      85             : 
      86             :     EQFABRIC_API uint32_t getSerial() const; //!< @internal unique serial number
      87             :     //@}
      88             : 
      89             :     /** @return true if the object has data to commit. @version 1.0 */
      90             :     EQFABRIC_API bool isDirty() const override;
      91             : 
      92             :     /** @internal */
      93             :     EQFABRIC_API uint128_t
      94             :         commit(const uint32_t incarnation = CO_COMMIT_NEXT) override;
      95             : 
      96             :     /** @internal Back up app-specific data, excluding child data. */
      97             :     EQFABRIC_API virtual void backup();
      98             : 
      99             :     /** @internal Restore the last backup. */
     100             :     EQFABRIC_API virtual void restore();
     101             : 
     102             :     /**
     103             :      * The changed parts of the object since the last pack().
     104             :      *
     105             :      * Subclasses should define their own bits, starting at DIRTY_CUSTOM.
     106             :      */
     107             :     enum DirtyBits
     108             :     {
     109             :         DIRTY_NAME = Serializable::DIRTY_CUSTOM << 0,     // 1
     110             :         DIRTY_USERDATA = Serializable::DIRTY_CUSTOM << 1, // 2
     111             :         DIRTY_TASKS = Serializable::DIRTY_CUSTOM << 2,    // 4
     112             :         DIRTY_REMOVED = Serializable::DIRTY_CUSTOM << 3,  // 8
     113             :         DIRTY_SERIAL = Serializable::DIRTY_CUSTOM << 4,   // 16
     114             :         // Leave room for binary-compatible patches
     115             :         DIRTY_CUSTOM = Serializable::DIRTY_CUSTOM << 6, // 64
     116             :         DIRTY_OBJECT_BITS = DIRTY_NAME | DIRTY_USERDATA
     117             :     };
     118             : 
     119             : protected:
     120             :     /** Construct a new Object. */
     121             :     EQFABRIC_API Object();
     122             : 
     123             :     /** Construct an unmapped, unregistered copy of an object. */
     124             :     EQFABRIC_API Object(const Object&);
     125             : 
     126             :     /** Destruct the object. */
     127             :     EQFABRIC_API virtual ~Object();
     128             : 
     129             :     /** NOP assignment operator. @version 1.1.1 */
     130             :     EQFABRIC_API Object& operator=(const Object& from);
     131             : 
     132             :     /**
     133             :      * @return true if this instance shall hold the master instance of the
     134             :      *         user data object, false otherwise.
     135             :      */
     136           0 :     virtual bool hasMasterUserData() { return false; }
     137             :     /** @return the latency to be used for keeping user data versions. */
     138           0 :     virtual uint32_t getUserDataLatency() const { return 0; }
     139             :     /** @internal Set the tasks this entity might potentially execute. */
     140             :     EQFABRIC_API void setTasks(const uint32_t tasks);
     141             : 
     142             :     EQFABRIC_API void notifyDetach() override;
     143             : 
     144             :     EQFABRIC_API void serialize(co::DataOStream& os,
     145             :                                 const uint64_t dirtyBits) override;
     146             :     EQFABRIC_API void deserialize(co::DataIStream& is,
     147             :                                   const uint64_t dirtyBits) override;
     148             : 
     149             :     /** @internal @return the bits to be re-committed by the master. */
     150           0 :     virtual uint64_t getRedistributableBits() const
     151             :     {
     152           0 :         return DIRTY_OBJECT_BITS;
     153             :     }
     154             : 
     155             :     /**
     156             :      * @internal
     157             :      * Remove the given child on the master during the next commit.
     158             :      * @sa removeChild
     159             :      */
     160             :     EQFABRIC_API void postRemove(Object* child);
     161             : 
     162             :     /** @internal Execute the slave remove request. @sa postRemove */
     163           0 :     virtual void removeChild(const uint128_t&) { LBUNIMPLEMENTED; }
     164             :     /** @internal commit, register child slave instance with the server. */
     165             :     template <class C, class S>
     166             :     void commitChild(C* child, S* sender, uint32_t cmd,
     167             :                      const uint32_t incarnation);
     168             : 
     169             :     /** @internal commit slave instance to the server. */
     170             :     template <class C>
     171           0 :     inline void commitChild(C* child, const uint32_t incarnation)
     172             :     {
     173           0 :         LBASSERT(child->isAttached());
     174           0 :         child->commit(incarnation);
     175           0 :     }
     176             : 
     177             :     /** @internal commit, register child slave instances with the server. */
     178             :     template <class C, class S>
     179             :     void commitChildren(const std::vector<C*>& children, S* sender,
     180             :                         uint32_t cmd, const uint32_t incarnation);
     181             : 
     182             :     /** @internal commit, register child slave instances with the server. */
     183             :     template <class C>
     184         133 :     void commitChildren(const std::vector<C*>& children, uint32_t cmd,
     185             :                         const uint32_t incarnation)
     186             :     {
     187         133 :         commitChildren<C, Object>(children, this, cmd, incarnation);
     188         133 :     }
     189             : 
     190             :     /** @internal commit all children. */
     191             :     template <class C>
     192             :     void commitChildren(const std::vector<C*>& children,
     193             :                         const uint32_t incarnation);
     194             : 
     195             :     /** @internal sync all children to head version. */
     196             :     template <class C>
     197             :     void syncChildren(const std::vector<C*>& children);
     198             : 
     199             :     /** @internal unmap/deregister all children. */
     200             :     template <class P, class C>
     201             :     inline void releaseChildren(const std::vector<C*>& children);
     202             : 
     203             :     /** @internal sync master object to the given slave commit. */
     204             :     EQFABRIC_API bool _cmdSync(co::ICommand& command);
     205             : 
     206             :     EQFABRIC_API void updateEvent(Event& event, int64_t time); //!< @internal
     207             : 
     208             : private:
     209             :     detail::Object* const _impl;
     210             : };
     211             : 
     212             : // Template Implementation
     213             : template <class C, class S>
     214         307 : inline void Object::commitChild(C* child, S* sender, uint32_t cmd,
     215             :                                 const uint32_t incarnation)
     216             : {
     217         307 :     if (!child->isAttached())
     218             :     {
     219           0 :         LBASSERT(!isMaster());
     220           0 :         co::LocalNodePtr localNode = child->getConfig()->getLocalNode();
     221             :         lunchbox::Request<uint128_t> request =
     222           0 :             localNode->registerRequest<uint128_t>();
     223           0 :         co::NodePtr node = child->getServer().get();
     224           0 :         sender->send(node, cmd) << request;
     225             : 
     226           0 :         LBCHECK(localNode->mapObject(child, request.wait(), co::VERSION_NONE));
     227             :     }
     228         307 :     child->commit(incarnation);
     229         307 : }
     230             : 
     231             : template <class C, class S>
     232         167 : inline void Object::commitChildren(const std::vector<C*>& children, S* sender,
     233             :                                    uint32_t cmd, const uint32_t incarnation)
     234             : {
     235             :     // TODO Opt: async register and commit
     236        1422 :     for (typename std::vector<C*>::const_iterator i = children.begin();
     237         948 :          i != children.end(); ++i)
     238             :     {
     239         307 :         C* child = *i;
     240         307 :         commitChild<C, S>(child, sender, cmd, incarnation);
     241             :     }
     242         167 : }
     243             : 
     244             : template <class C>
     245          16 : inline void Object::commitChildren(const std::vector<C*>& children,
     246             :                                    const uint32_t incarnation)
     247             : {
     248             :     // TODO Opt: async commit
     249         120 :     for (typename std::vector<C*>::const_iterator i = children.begin();
     250          80 :          i != children.end(); ++i)
     251             :     {
     252          24 :         C* child = *i;
     253          24 :         LBASSERT(child->isAttached());
     254          24 :         child->commit(incarnation);
     255             :     }
     256          16 : }
     257             : 
     258             : template <class C>
     259          34 : inline void Object::syncChildren(const std::vector<C*>& children)
     260             : {
     261         318 :     for (typename std::vector<C*>::const_iterator i = children.begin();
     262         212 :          i != children.end(); ++i)
     263             :     {
     264          72 :         C* child = *i;
     265          72 :         LBASSERT(child->isMaster()); // slaves are synced using version
     266          72 :         child->sync();
     267             :     }
     268          34 : }
     269             : 
     270             : template <class P, class C>
     271          24 : inline void Object::releaseChildren(const std::vector<C*>& children)
     272             : {
     273          48 :     for (size_t i = children.size(); i > 0; --i)
     274             :     {
     275          24 :         C* child = children[i - 1];
     276             : 
     277          24 :         if (child->isAttached())
     278             :         {
     279           8 :             getLocalNode()->releaseObject(child);
     280           8 :             if (!isMaster())
     281             :             {
     282           8 :                 static_cast<P*>(this)->_removeChild(child);
     283           8 :                 static_cast<P*>(this)->release(child);
     284             :             }
     285             :         }
     286             :         else
     287             :         {
     288          16 :             LBASSERT(isMaster());
     289             :         }
     290             :     }
     291          24 : }
     292             : }
     293             : }
     294             : #endif // EQFABRIC_OBJECT_H

Generated by: LCOV version 1.11