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