Line data Source code
1 :
2 : /* Copyright (c) 2009-2013, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2012, 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 : #include "layout.h"
20 :
21 : #include "commands.h"
22 : #include "elementVisitor.h"
23 : #include "leafVisitor.h"
24 : #include "log.h"
25 : #include "nameFinder.h"
26 : #include "observer.h"
27 : #include "paths.h"
28 :
29 : #include <co/dataIStream.h>
30 : #include <co/dataOStream.h>
31 : #include <co/objectICommand.h>
32 :
33 : #include <lunchbox/stdExt.h>
34 :
35 : namespace eq
36 : {
37 : namespace fabric
38 : {
39 : template< class C, class L, class V >
40 443 : Layout< C, L, V >::Layout( C* config )
41 443 : : _config( config )
42 : {
43 443 : LBASSERT( config );
44 443 : static_cast< L* >( this )->_config->_addLayout( static_cast< L* >( this ));
45 443 : LBLOG( LOG_INIT ) << "New " << lunchbox::className( this ) << std::endl;
46 443 : }
47 :
48 : template< class C, class L, class V >
49 442 : Layout< C, L, V >::~Layout()
50 : {
51 442 : LBLOG( LOG_INIT ) << "Delete " << lunchbox::className( this ) << std::endl;
52 1297 : while( !_views.empty( ))
53 : {
54 413 : V* view = _views.back();
55 413 : LBCHECK( _removeChild( view ));
56 413 : release( view );
57 : }
58 :
59 442 : _config->_removeLayout( static_cast< L* >( this ));
60 884 : }
61 :
62 : template< class C, class L, class V >
63 126 : void Layout< C, L, V >::attach( const uint128_t& id,
64 : const uint32_t instanceID )
65 : {
66 126 : Object::attach( id, instanceID );
67 :
68 126 : co::CommandQueue* queue = _config->getMainThreadQueue();
69 126 : LBASSERT( queue );
70 :
71 126 : registerCommand( CMD_LAYOUT_NEW_VIEW,
72 : CmdFunc( this, &Layout< C, L, V >::_cmdNewView ), queue );
73 126 : registerCommand( CMD_LAYOUT_NEW_VIEW_REPLY,
74 : CmdFunc( this, &Layout< C, L, V >::_cmdNewViewReply ), 0 );
75 126 : }
76 :
77 : template< class C, class L, class V >
78 73487 : uint128_t Layout< C, L, V >::commit( const uint32_t incarnation )
79 : {
80 : // Always traverse views: view proxy objects may be dirty
81 73487 : commitChildren< V >( _views, CMD_LAYOUT_NEW_VIEW, incarnation );
82 73487 : return Object::commit( incarnation );
83 : }
84 :
85 : template< class C, class L, class V >
86 275 : void Layout< C, L, V >::serialize( co::DataOStream& os,
87 : const uint64_t dirtyBits )
88 : {
89 275 : Object::serialize( os, dirtyBits );
90 :
91 275 : if( dirtyBits & DIRTY_VIEWS && isMaster( ))
92 219 : os.serializeChildren( _views );
93 275 : }
94 :
95 : template< class C, class L, class V >
96 196 : void Layout< C, L, V >::deserialize( co::DataIStream& is,
97 : const uint64_t dirtyBits )
98 : {
99 196 : Object::deserialize( is, dirtyBits );
100 :
101 196 : if( dirtyBits & DIRTY_VIEWS )
102 : {
103 196 : if( isMaster( ))
104 56 : syncChildren( _views );
105 : else
106 : {
107 140 : Views result;
108 140 : is.deserializeChildren( this, _views, result );
109 140 : _views.swap( result );
110 : }
111 : }
112 196 : }
113 :
114 : template< class C, class L, class V >
115 1355 : void Layout< C, L, V >::setDirty( const uint64_t dirtyBits )
116 : {
117 1355 : Object::setDirty( dirtyBits );
118 1355 : _config->setDirty( C::DIRTY_LAYOUTS );
119 1355 : }
120 :
121 : template< class C, class L, class V >
122 126 : void Layout< C, L, V >::notifyDetach()
123 : {
124 126 : Object::notifyDetach();
125 126 : releaseChildren< L, V >( _views );
126 126 : }
127 :
128 : template< class C, class L, class V >
129 63 : void Layout< C, L, V >::create( V** view )
130 : {
131 63 : *view = getConfig()->getServer()->getNodeFactory()->createView(
132 : static_cast< L* >( this ));
133 63 : }
134 :
135 : template< class C, class L, class V >
136 476 : void Layout< C, L, V >::release( V* view )
137 : {
138 476 : getConfig()->getServer()->getNodeFactory()->releaseView( view );
139 476 : }
140 :
141 : namespace
142 : {
143 : template< class L, class V >
144 14880 : VisitorResult _accept( L* layout, V& visitor )
145 : {
146 14880 : VisitorResult result = visitor.visitPre( layout );
147 14880 : if( result != TRAVERSE_CONTINUE )
148 1084 : return result;
149 :
150 13796 : const typename L::Views& views = layout->getViews();
151 85908 : for( typename L::Views::const_iterator i = views.begin();
152 57272 : i != views.end(); ++i )
153 : {
154 14840 : switch( (*i)->accept( visitor ))
155 : {
156 : case TRAVERSE_TERMINATE:
157 0 : return TRAVERSE_TERMINATE;
158 :
159 : case TRAVERSE_PRUNE:
160 0 : result = TRAVERSE_PRUNE;
161 0 : break;
162 :
163 : case TRAVERSE_CONTINUE:
164 : default:
165 14840 : break;
166 : }
167 : }
168 :
169 13796 : switch( visitor.visitPost( layout ))
170 : {
171 : case TRAVERSE_TERMINATE:
172 0 : return TRAVERSE_TERMINATE;
173 :
174 : case TRAVERSE_PRUNE:
175 0 : return TRAVERSE_PRUNE;
176 :
177 : case TRAVERSE_CONTINUE:
178 : default:
179 13796 : break;
180 : }
181 :
182 13796 : return result;
183 : }
184 : }
185 :
186 : template< class C, class L, class V >
187 14880 : VisitorResult Layout< C, L, V >::accept( Visitor& visitor )
188 : {
189 14880 : return _accept( static_cast< L* >( this ), visitor );
190 : }
191 :
192 : template< class C, class L, class V >
193 0 : VisitorResult Layout< C, L, V >::accept( Visitor& visitor ) const
194 : {
195 0 : return _accept( static_cast< const L* >( this ), visitor );
196 : }
197 :
198 : template< class C, class L, class V >
199 477 : void Layout< C, L, V >::_addChild( V* view )
200 : {
201 477 : LBASSERT( view );
202 477 : LBASSERT( view->getLayout() == this );
203 477 : _views.push_back( view );
204 477 : setDirty( DIRTY_VIEWS );
205 477 : }
206 :
207 : template< class C, class L, class V >
208 952 : bool Layout< C, L, V >::_removeChild( V* view )
209 : {
210 952 : typename Views::iterator i = lunchbox::find( _views, view );
211 952 : if( i == _views.end( ))
212 476 : return false;
213 :
214 476 : LBASSERT( view->getLayout() == this );
215 476 : _views.erase( i );
216 476 : setDirty( DIRTY_VIEWS );
217 476 : if( !isMaster( ))
218 476 : postRemove( view );
219 476 : return true;
220 : }
221 :
222 : template< class C, class L, class V >
223 0 : template< class O > void Layout< C, L, V >::_removeObserver( const O* observer )
224 : {
225 0 : for( typename Views::const_iterator i = _views.begin();
226 0 : i != _views.end(); ++i )
227 : {
228 0 : V* view = *i;
229 0 : if( view->getObserver() == observer )
230 : {
231 0 : LBINFO << "Removing " << lunchbox::disableHeader << *observer
232 0 : << " used by " << *view << std::endl
233 0 : << lunchbox::enableHeader;
234 0 : view->setObserver( 0 );
235 : }
236 : }
237 0 : }
238 :
239 : template< class C, class L, class V >
240 7 : bool Layout< C, L, V >::isActive() const
241 : {
242 7 : const typename C::Canvases& canvases = _config->getCanvases();
243 39 : for( typename C::Canvases::const_iterator i = canvases.begin();
244 26 : i != canvases.end(); ++i )
245 : {
246 7 : if( (*i)->getActiveLayout() == this )
247 1 : return true;
248 : }
249 6 : return false;
250 : }
251 :
252 : template< class C, class L, class V >
253 1410 : V* Layout< C, L, V >::getView( const ViewPath& path )
254 : {
255 1410 : LBASSERTINFO( _views.size() > path.viewIndex,
256 : _views.size() << " <= " << path.viewIndex << " " << this );
257 :
258 1410 : if( _views.size() <= path.viewIndex )
259 0 : return 0;
260 :
261 1410 : return _views[ path.viewIndex ];
262 : }
263 :
264 : template< class C, class L, class V >
265 562 : LayoutPath Layout< C, L, V >::getPath() const
266 : {
267 562 : LBASSERT( _config );
268 562 : const std::vector< L* >& layouts = _config->getLayouts();
269 : typename std::vector< L* >::const_iterator i = std::find( layouts.begin(),
270 : layouts.end(),
271 562 : this );
272 562 : LBASSERT( i != layouts.end( ));
273 :
274 562 : LayoutPath path;
275 562 : path.layoutIndex = std::distance( layouts.begin(), i );
276 562 : return path;
277 : }
278 :
279 : template< class C, class L, class V >
280 0 : V* Layout< C, L, V >::findView( const std::string& name )
281 : {
282 0 : NameFinder< V, Visitor > finder( name );
283 0 : accept( finder );
284 0 : return finder.getResult();
285 : }
286 :
287 : //----------------------------------------------------------------------
288 : // ICommand handlers
289 : //----------------------------------------------------------------------
290 : template< class C, class L, class V > bool
291 0 : Layout< C, L, V >::_cmdNewView( co::ICommand& cmd )
292 : {
293 0 : co::ObjectICommand command( cmd );
294 :
295 0 : V* view = 0;
296 0 : create( &view );
297 0 : LBASSERT( view );
298 :
299 0 : getLocalNode()->registerObject( view );
300 0 : view->setAutoObsolete( _config->getLatency() + 1 );
301 0 : LBASSERT( view->isAttached() );
302 :
303 0 : send( command.getRemoteNode(), CMD_LAYOUT_NEW_VIEW_REPLY )
304 0 : << command.read< uint32_t >() << view->getID();
305 :
306 0 : return true;
307 : }
308 :
309 : template< class C, class L, class V > bool
310 0 : Layout< C, L, V >::_cmdNewViewReply( co::ICommand& cmd )
311 : {
312 0 : co::ObjectICommand command( cmd );
313 0 : const uint32_t requestID = command.read< uint32_t >();
314 0 : const uint128_t& result = command.read< uint128_t >();
315 :
316 0 : getLocalNode()->serveRequest( requestID, result );
317 :
318 0 : return true;
319 : }
320 :
321 : template< class C, class L, class V >
322 282 : std::ostream& operator << ( std::ostream& os, const Layout< C, L, V >& layout )
323 : {
324 282 : os << lunchbox::disableFlush << lunchbox::disableHeader << "layout"
325 : << std::endl;
326 282 : os << "{" << std::endl << lunchbox::indent;
327 :
328 282 : const std::string& name = layout.getName();
329 282 : if( !name.empty( ))
330 196 : os << "name \"" << name << "\"" << std::endl;
331 :
332 282 : const std::vector< V* >& views = layout.getViews();
333 1743 : for( typename std::vector< V* >::const_iterator i = views.begin();
334 1162 : i != views.end(); ++i )
335 : {
336 299 : os << **i;
337 : }
338 282 : os << lunchbox::exdent << "}" << std::endl << lunchbox::enableHeader
339 : << lunchbox::enableFlush;
340 282 : return os;
341 : }
342 :
343 : }
344 : }
|