File: Visitor.h

package info (click to toggle)
sofa-framework 1.0~beta4-11
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 88,820 kB
  • ctags: 27,300
  • sloc: cpp: 151,126; ansic: 2,387; xml: 581; sh: 417; makefile: 68
file content (269 lines) | stat: -rw-r--r-- 10,665 bytes parent folder | download | duplicates (5)
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
/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* 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.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_SIMULATION_VISITOR_H
#define SOFA_SIMULATION_VISITOR_H

#include <sofa/simulation/common/common.h>
#include <sofa/simulation/common/Node.h>
#include <sofa/simulation/common/LocalStorage.h>

#include <sofa/core/componentmodel/behavior/BaseMechanicalState.h>

#include <sofa/helper/set.h>
#include <iostream>

#ifdef DUMP_VISITOR_INFO
#include <sofa/helper/system/thread/CTime.h>
#endif

namespace sofa
{

namespace simulation
{

class LocalStorage;

/// Base class for visitors propagated recursively through the scenegraph
class SOFA_SIMULATION_COMMON_API Visitor
{
public:
#ifdef DUMP_VISITOR_INFO   
        typedef sofa::helper::system::thread::CTime CTime; 

        Visitor() {enteringBase=NULL; infoPrinted=false; }
#endif
	virtual ~Visitor() {}
        typedef simulation::Node::ctime_t ctime_t;

	enum Result { RESULT_CONTINUE, RESULT_PRUNE };

	/// Callback method called when decending to a new node. Recursion will stop if this method returns RESULT_PRUNE
	virtual Result processNodeTopDown(simulation::Node* /*node*/) { return RESULT_CONTINUE; }

	/// Callback method called after child node have been processed and before going back to the parent node.
	virtual void processNodeBottomUp(simulation::Node* /*node*/) {}

	/// Return a category name for this visitor
	/// Only used for debugging / profiling purposes
	virtual const char* getCategoryName() const { return "default"; }

	/// Return a class name for this visitor
	/// Only used for debugging / profiling purposes
	virtual const char* getClassName() const { return "Visitor"; }

        /// Return eventual information on the behavior of the visitor
        /// Only used for debugging / profiling purposes
	virtual std::string getInfos() const { return ""; }

#ifdef SOFA_VERBOSE_TRAVERSAL
	void debug_write_state_before( core::objectmodel::BaseObject* obj ) ;
	void debug_write_state_after( core::objectmodel::BaseObject* obj ) ;
#else
	inline void debug_write_state_before( core::objectmodel::BaseObject*  ){}
	inline void debug_write_state_after( core::objectmodel::BaseObject*  ){}
#endif


	/// Helper method to enumerate objects in the given list. The callback gets the pointer to node
	template < class Visit, class Container, class Object >
	  void for_each(Visit* visitor, simulation::Node* node, const Container& list, void (Visit::*fn)(simulation::Node*, Object*))
	{

        if (node->getLogTime())
        {
            const std::string category = getCategoryName();
            ctime_t t0 = node->startTime();
            for (typename Container::iterator it=list.begin(); it != list.end(); ++it)
            {
				if(testTags(*it)){
					debug_write_state_before(*it);
					(visitor->*fn)(node, *it);
					debug_write_state_after(*it);
					t0 = node->endTime(t0, category, *it);
				}
            }
        }
        else
        {
            for (typename Container::iterator it=list.begin(); it != list.end(); ++it)
            {
				if(testTags(*it)){
					debug_write_state_before(*it);
					(visitor->*fn)(node, *it);
					debug_write_state_after(*it);
				}
			}
        }
	}

	/// Helper method to enumerate objects in the given list. The callback gets the pointer to node
        template < class Visit, class Container, class Object >
	  Visitor::Result for_each_r(Visit* visitor, simulation::Node* node, const Container& list, Visitor::Result (Visit::*fn)(simulation::Node*, Object*))
	{

                    Visitor::Result res = Visitor::RESULT_CONTINUE;
                    if (node->getLogTime())
                    {
                        const std::string category = getCategoryName();
                        ctime_t t0 = node->startTime();
						
                        for (typename Container::iterator it=list.begin(); it != list.end(); ++it)
                        {
							if(testTags(*it)){
								debug_write_state_before(*it);
								res = (visitor->*fn)(node, *it);
								debug_write_state_after(*it);
								t0 = node->endTime(t0, category, *it);
							}
                        }
                    }
                    else
                    {
						//bool processObject;
                        for (typename Container::iterator it=list.begin(); it != list.end(); ++it)
                        {
							if(testTags(*it)){
								debug_write_state_before(*it);
								res = (visitor->*fn)(node, *it);
								debug_write_state_after(*it);
							}
						}
                    }
                    return res;

	}


	  //method to compare the tags of the objet with the ones of the visitor
	  // return true if the object has all the tags of the visitor
	  // or if no tag is set to the visitor
	bool testTags(core::objectmodel::BaseObject* obj)
	{
		if(subsetsToManage.empty())
			return true;
		else{
			//for ( sofa::helper::set<unsigned int>::iterator it=subsetsToManage.begin() ; it!=subsetsToManage.end() ; it++)
			//	if(obj->hasTag(*it))
			//		return true;
                    if (obj->getTags().includes(subsetsToManage)) // all tags in subsetsToManage must be included in the list of tags of the object
                        return true;
		}
		return false;
	}


	//template < class Visit, class Container, class Object >
	//void for_each(Visit* visitor, const Container& list, void (Visit::*fn)(Object))
	//{
	//	for (typename Container::iterator it=list.begin(); it != list.end(); ++it)
	//	{
	//		(visitor->*fn)(*it);
	//	}
	//}


	/// Alias for context->executeVisitor(this)
	void execute(core::objectmodel::BaseContext*);
	ctime_t begin(simulation::Node* node, core::objectmodel::BaseObject*
#ifdef DUMP_VISITOR_INFO
                      obj
#endif
                      );
	void end(simulation::Node* node, core::objectmodel::BaseObject* obj, ctime_t t0);


	/// Specify whether this visitor can be parallelized.
	virtual bool isThreadSafe() const { return false; }

	/// Callback method called when decending to a new node. Recursion will stop if this method returns RESULT_PRUNE
	/// This version is offered a LocalStorage to store temporary data
	virtual Result processNodeTopDown(simulation::Node* node, LocalStorage*) { return processNodeTopDown(node); }

	/// Callback method called after child node have been processed and before going back to the parent node.
	/// This version is offered a LocalStorage to store temporary data
	virtual void processNodeBottomUp(simulation::Node* node, LocalStorage*) { processNodeBottomUp(node); }

public:
    typedef sofa::core::objectmodel::Tag Tag;
    typedef sofa::core::objectmodel::TagSet TagSet;
    /// list of the subsets
    TagSet subsetsToManage;
    
    Visitor& setTags(const TagSet& t) { subsetsToManage = t; return *this; }
    Visitor& addTag(Tag t) { subsetsToManage.insert(t); return *this; }
    Visitor& removeTag(Tag t) { subsetsToManage.erase(t); return *this; }

#ifdef DUMP_VISITOR_INFO
        //DEBUG Purposes
    static double getTimeSpent(ctime_t initTime, ctime_t endTime)
    {
      return 1000.0*(endTime-initTime)/((double)CTime::getTicksPerSec());
    }
  protected:
    
        static std::ostream *outputVisitor;  //Ouput stream to dump the info
        static bool printActivated;          //bool to know if the stream is opened or not
        static unsigned int depthLevel;      //Level in the hierarchy
        static ctime_t initDumpTime;

        core::objectmodel::Base* enteringBase;
        bool infoPrinted;

        ctime_t initVisitTime;
        ctime_t initComponentTime;
/*         std::list<ctime_t> initComponentTime; */
  public:
        static void startDumpVisitor(std::ostream *s, double time)
        {
	  depthLevel=0;
          initDumpTime = sofa::helper::system::thread::CTime::getRefTime();
          printActivated=true; outputVisitor=s;
          std::string initDump;
          std::ostringstream ff; ff << "<TraceVisitor time=\"" << time << "\">\n";
          dumpInfo(ff.str()); depthLevel++;
        };
        static void stopDumpVisitor()
        {
          std::ostringstream s;
          s << "<TotalTime value=\"" << getTimeSpent(initDumpTime, sofa::helper::system::thread::CTime::getRefTime()) << "\" />\n";
          s << "</TraceVisitor>\n";
          depthLevel--;  dumpInfo(s.str());
          printActivated=false;
	  depthLevel=0;
        };
        static void dumpInfo( const std::string &info){ if (printActivated) {(*outputVisitor) << info; outputVisitor->flush();}}
        static void printComment(const std::string &s) ;
        static unsigned int getLevel(){return depthLevel;};
        static void resetLevel(){depthLevel=0;};
        virtual void printInfo(const core::objectmodel::BaseContext* context, bool dirDown);
        void setNode(core::objectmodel::Base* c);
#endif
};
} // namespace simulation

} // namespace sofa

#endif