-
Notifications
You must be signed in to change notification settings - Fork 211
/
Copy pathBodyContainer.hpp
95 lines (80 loc) · 3.67 KB
/
BodyContainer.hpp
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
// 2004 © Olivier Galizzi <[email protected]>
// 2004 © Janek Kozicki <[email protected]>
// 2010 © Václav Šmilauer <[email protected]>
#pragma once
#include<yade/lib/serialization/Serializable.hpp>
#include<boost/foreach.hpp>
#ifndef FOREACH
# define FOREACH BOOST_FOREACH
#endif
#include<boost/tuple/tuple.hpp>
class Body;
class InteractionContainer;
#if YADE_OPENMP
#define YADE_PARALLEL_FOREACH_BODY_BEGIN(b_,bodies) const Body::id_t _sz(bodies->size()); _Pragma("omp parallel for") for(Body::id_t _id=0; _id<_sz; _id++){ if(!(*bodies)[_id]) continue; b_((*bodies)[_id]);
#define YADE_PARALLEL_FOREACH_BODY_END() }
#else
#define YADE_PARALLEL_FOREACH_BODY_BEGIN(b,bodies) FOREACH(b,*(bodies)){
#define YADE_PARALLEL_FOREACH_BODY_END() }
#endif
/*
Container of bodies implemented as flat std::vector. It handles body removal and
intelligently reallocates free ids for newly added ones.
The nested iterators and the specialized FOREACH_BODY macros above will silently skip null body pointers which may exist after removal. The null pointers can still be accessed via the [] operator.
Any alternative implementation should use the same API.
*/
class BodyContainer: public Serializable{
private:
typedef std::vector<shared_ptr<Body> > ContainerT;
ContainerT body;
Body::id_t lowestFree;
Body::id_t findFreeId();
public:
friend class InteractionContainer; // accesses the body vector directly
//An iterator that will automatically jump slots with null bodies
class smart_iterator : public ContainerT::iterator {
public:
ContainerT::iterator end;
smart_iterator& operator++() {
ContainerT::iterator::operator++();
while (!(this->operator*()) && end!=(*this)) ContainerT::iterator::operator++();
return *this;}
smart_iterator operator++(int) {smart_iterator temp(*this); operator++(); return temp;}
smart_iterator& operator=(const ContainerT::iterator& rhs) {ContainerT::iterator::operator=(rhs); return *this;}
smart_iterator& operator=(const smart_iterator& rhs) {ContainerT::iterator::operator=(rhs); end=rhs.end; return *this;}
smart_iterator() {}
smart_iterator(const ContainerT::iterator& source) {(*this)=source;}
smart_iterator(const smart_iterator& source) {(*this)=source; end=source.end;}
};
// typedef ContainerT::iterator iterator;
// typedef ContainerT::const_iterator const_iterator;
typedef smart_iterator iterator;
typedef const smart_iterator const_iterator;
BodyContainer();
virtual ~BodyContainer();
Body::id_t insert(shared_ptr<Body>&);
Body::id_t insert(shared_ptr<Body>& b, Body::id_t id);
// mimick some STL api
void clear();
// by using simple vector<>::iterator's, we can hit null bodies
// iterator begin() { return body.begin(); }
// iterator end() { return body.end(); }
// const_iterator begin() const { return body.begin(); }
// const_iterator end() const { return body.end(); }
// //with smart iterators
iterator begin() {
iterator temp(body.begin()); temp.end=body.end();
return (body.begin()==body.end() || *temp)?temp:++temp;}
iterator end() { iterator temp(body.end()); temp.end=body.end(); return temp;}
const_iterator begin() const { return begin();}
const_iterator end() const { return end();}
size_t size() const { return body.size(); }
shared_ptr<Body>& operator[](unsigned int id){ return body[id];}
const shared_ptr<Body>& operator[](unsigned int id) const { return body[id]; }
bool exists(Body::id_t id) const { return (id>=0) && ((size_t)id<body.size()) && ((bool)body[id]); }
bool erase(Body::id_t id);
REGISTER_CLASS_AND_BASE(BodyContainer,Serializable);
REGISTER_ATTRIBUTES(Serializable,(body));
DECLARE_LOGGER;
};
REGISTER_SERIALIZABLE(BodyContainer);