24 #ifndef PXR_USD_SDF_PATH_TABLE_H 25 #define PXR_USD_SDF_PATH_TABLE_H 28 #include "pxr/usd/sdf/api.h" 29 #include "pxr/usd/sdf/path.h" 30 #include "pxr/base/tf/pointerAndBits.h" 31 #include "pxr/base/tf/functionRef.h" 33 #include <boost/iterator/iterator_facade.hpp> 34 #include <boost/noncopyable.hpp> 40 PXR_NAMESPACE_OPEN_SCOPE
44 void Sdf_VisitPathTableInParallel(
void **,
size_t,
TfFunctionRef<
void(
void*&)>);
84 template <
class MappedType>
90 typedef MappedType mapped_type;
91 typedef std::pair<key_type, mapped_type> value_type;
99 struct _Entry : boost::noncopyable {
100 _Entry(value_type
const &value, _Entry *n)
103 , firstChild(
nullptr)
104 , nextSiblingOrParent(
nullptr,
false) {}
106 _Entry(value_type &&value, _Entry *n)
107 : value(std::move(value))
109 , firstChild(
nullptr)
110 , nextSiblingOrParent(
nullptr,
false) {}
114 _Entry *GetNextSibling() {
115 return nextSiblingOrParent.template BitsAs<bool>() ?
116 nextSiblingOrParent.Get() : 0;
120 _Entry
const *GetNextSibling()
const {
121 return nextSiblingOrParent.template BitsAs<bool>() ?
122 nextSiblingOrParent.Get() : 0;
127 _Entry *GetParentLink() {
128 return nextSiblingOrParent.template BitsAs<bool>() ? 0 :
129 nextSiblingOrParent.Get();
133 _Entry
const *GetParentLink()
const {
134 return nextSiblingOrParent.template BitsAs<bool>() ? 0 :
135 nextSiblingOrParent.Get();
140 void SetSibling(_Entry *sibling) {
141 nextSiblingOrParent.Set(sibling,
true);
146 void SetParentLink(_Entry *parent) {
147 nextSiblingOrParent.Set(parent,
false);
151 void AddChild(_Entry *child) {
155 child->SetSibling(firstChild);
157 child->SetParentLink(
this);
161 void RemoveChild(_Entry *child) {
163 if (child == firstChild) {
164 firstChild = child->GetNextSibling();
168 _Entry *prev, *cur = firstChild;
171 cur = prev->GetNextSibling();
172 }
while (cur != child);
173 prev->nextSiblingOrParent = cur->nextSiblingOrParent;
196 typedef std::vector<_Entry *> _BucketVec;
202 template <
class,
class>
friend class Iterator;
203 template <
class ValType,
class EntryPtr>
205 public boost::iterator_facade<Iterator<ValType, EntryPtr>,
206 ValType, boost::forward_traversal_tag>
214 template <
class OtherVal,
class OtherEntryPtr>
215 Iterator(Iterator<OtherVal, OtherEntryPtr>
const &other)
216 : _entry(other._entry)
222 Iterator GetNextSubtree()
const {
225 if (EntryPtr sibling = _entry->GetNextSibling()) {
227 result._entry = sibling;
231 for (EntryPtr p = _entry->GetParentLink(); p;
232 p = p->GetParentLink()) {
233 if (EntryPtr sibling = p->GetNextSibling()) {
234 result._entry = sibling;
245 bool HasChild()
const {
246 return bool(_entry->firstChild);
250 friend class boost::iterator_core_access;
252 template <
class,
class>
friend class Iterator;
254 explicit Iterator(EntryPtr entry)
262 inline void increment() {
264 _entry = _entry->firstChild ? _entry->firstChild :
265 GetNextSubtree()._entry;
270 template <
class OtherVal,
class OtherEntryPtr>
271 bool equal(Iterator<OtherVal, OtherEntryPtr>
const &other)
const {
272 return _entry == other._entry;
276 ValType &dereference()
const {
277 return _entry->value;
284 typedef Iterator<value_type, _Entry *> iterator;
285 typedef Iterator<const value_type, const _Entry *> const_iterator;
303 New(value_type
const &value) {
305 ret._unlinkedEntry.reset(
new _Entry(value,
nullptr));
313 ret._unlinkedEntry.reset(
new _Entry(std::move(value),
nullptr));
320 return New({ key, mapped });
327 return _unlinkedEntry->value.first;
334 return _unlinkedEntry->value.first;
341 return _unlinkedEntry->value.second;
348 return _unlinkedEntry->value.second;
354 return static_cast<bool>(_unlinkedEntry);
359 explicit operator bool()
const {
366 _unlinkedEntry.reset();
370 std::unique_ptr<_Entry> _unlinkedEntry;
378 : _buckets(other._buckets.
size())
384 for (const_iterator i = other.
begin(),
end = other.
end();
386 iterator j = _InsertInTable(*i).first;
388 if (i._entry->firstChild && !j._entry->firstChild) {
389 j._entry->firstChild =
390 _InsertInTable(i._entry->firstChild->value).first._entry;
393 if (i._entry->nextSiblingOrParent.Get() &&
394 !j._entry->nextSiblingOrParent.Get()) {
395 j._entry->nextSiblingOrParent.Set(
396 _InsertInTable(i._entry->nextSiblingOrParent.
397 Get()->value).first._entry,
398 i._entry->nextSiblingOrParent.template BitsAs<bool>());
405 : _buckets(std::move(other._buckets))
455 const_iterator
end()
const {
456 return const_iterator(0);
466 iterator i =
find(path);
482 _Entry *
const entry = i._entry;
483 _EraseSubtree(entry);
484 _RemoveFromParent(entry);
485 _EraseFromTable(entry);
493 for (_Entry *e = _buckets[_Hash(path)]; e; e = e->next) {
494 if (e->value.first == path)
506 for (_Entry
const *e = _buckets[_Hash(path)]; e; e = e->next) {
507 if (e->value.first == path)
508 return const_iterator(e);
517 std::pair<iterator, iterator>
519 std::pair<iterator, iterator> result;
520 result.first =
find(path);
521 result.second = result.first.GetNextSubtree();
528 std::pair<const_iterator, const_iterator>
530 std::pair<const_iterator, const_iterator> result;
531 result.first =
find(path);
532 result.second = result.first.GetNextSubtree();
542 inline size_t size()
const {
return _size; }
563 _UpdateTreeForNewEntry(result);
579 _UpdateTreeForNewEntry(result);
589 return insert(value_type(path, mapped_type())).first->second;
598 for (
size_t i = 0, n = _buckets.size(); i != n; ++i) {
599 _Entry *entry = _buckets[i];
601 _Entry *next = entry->next;
614 [](
void*& voidEntry) {
615 _Entry *entry = static_cast<_Entry *>(voidEntry);
617 _Entry *next = entry->next;
623 Sdf_VisitPathTableInParallel(reinterpret_cast<void **>(_buckets.data()),
624 _buckets.size(), visitFn);
630 _buckets.swap(other._buckets);
637 std::vector<size_t> sizes(_buckets.size(), 0u);;
638 for (
size_t i = 0, n = _buckets.size(); i != n; ++i) {
639 for (_Entry *entry = _buckets[i]; entry; entry = entry->next) {
657 for (iterator i=range.first; i!=range.second; ++i) {
659 i->first.ReplacePrefix(oldName, newName),
663 if (range.first != range.second)
672 template <
typename Callback>
675 [&visitFn](
void*& voidEntry) {
676 _Entry *entry = static_cast<_Entry *>(voidEntry);
678 visitFn(std::cref(entry->value.first),
679 std::ref(entry->value.second));
683 Sdf_VisitPathTableInParallel(reinterpret_cast<void **>(_buckets.data()),
684 _buckets.size(), lambda);
689 template <
typename Callback>
692 [&visitFn](
void*& voidEntry) {
693 const _Entry *entry = static_cast<const _Entry *>(voidEntry);
695 visitFn(std::cref(entry->value.first),
696 std::cref(entry->value.second));
700 Sdf_VisitPathTableInParallel(
702 reinterpret_cast<void **>(const_cast<_Entry**>(_buckets.data())),
703 _buckets.size(), lambda);
717 _Entry *
const newEntry = iresult.first._entry;
718 SdfPath const &parentPath = _GetParentPath(newEntry->value.first);
721 insert(value_type(parentPath, mapped_type())).first;
723 parIter._entry->AddChild(newEntry);
729 template <
class MakeEntryFn>
731 MakeEntryFn &&makeEntry) {
737 _Entry **bucketHead = &(_buckets[_Hash(key)]);
738 for (_Entry *e = *bucketHead; e; e = e->next) {
739 if (e->value.first == key) {
748 bucketHead = &(_buckets[_Hash(key)]);
752 *bucketHead = std::forward<MakeEntryFn>(makeEntry)(*bucketHead);
762 return _InsertInTableImpl(
763 value.first, [&value](_Entry *next) {
764 return new _Entry(value, next);
769 return _InsertInTableImpl(
770 node.GetKey(), [&node](_Entry *next)
mutable {
771 node._unlinkedEntry->next = next;
772 return node._unlinkedEntry.release();
777 void _EraseFromTable(_Entry *entry) {
779 _Entry **cur = &_buckets[_Hash(entry->value.first)];
780 while (*cur != entry)
781 cur = &((*cur)->next);
791 void _EraseSubtree(_Entry *entry) {
793 if (_Entry *
const firstChild = entry->firstChild) {
794 _EraseSubtreeAndSiblings(firstChild);
795 _EraseFromTable(firstChild);
801 void _EraseSubtreeAndSiblings(_Entry *entry) {
803 _EraseSubtree(entry);
806 _Entry *sibling = entry->GetNextSibling();
807 _Entry *nextSibling = sibling ? sibling->GetNextSibling() :
nullptr;
809 _EraseSubtree(sibling);
810 _EraseFromTable(sibling);
811 sibling = nextSibling;
812 nextSibling = sibling ? sibling->GetNextSibling() :
nullptr;
818 void _RemoveFromParent(_Entry *entry) {
823 iterator parIter =
find(_GetParentPath(entry->value.first));
826 parIter._entry->RemoveChild(entry);
838 _mask = std::max(
size_t(7), (_mask << 1) + 1);
839 _BucketVec newBuckets(_mask + 1);
842 for (
size_t i = 0, n = _buckets.size(); i != n; ++i) {
843 _Entry *elem = _buckets[i];
846 _Entry *next = elem->next;
849 _Entry *&m = newBuckets[_Hash(elem->value.first)];
861 _buckets.swap(newBuckets);
865 bool _IsTooFull()
const {
866 return _size > _buckets.size();
870 inline size_t _Hash(
SdfPath const &path)
const {
871 return path.GetHash() & _mask;
881 PXR_NAMESPACE_CLOSE_SCOPE
883 #endif // PXR_USD_SDF_PATH_TABLE_H key_type const & GetKey() const
Return a const reference to this NodeHandle's key.
const_iterator end() const
Return a const_iterator denoting the end of the table.
size_t size() const
Return the number of elements in the table.
void UpdateForRename(const SdfPath &oldName, const SdfPath &newName)
Replaces all prefixes from oldName to newName.
SdfPathTable & operator=(SdfPathTable &&other)
Move assignment.
size_t count(SdfPath const &path) const
Return 1 if there is an element for path in the table, otherwise 0.
~SdfPathTable()
Destructor.
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
SdfPathTable & operator=(SdfPathTable const &other)
Copy assignment.
mapped_type & operator[](SdfPath const &path)
Shorthand for the following, where t is an SdfPathTable<T>.
const_iterator find(SdfPath const &path) const
Return a const_iterator to the element corresponding to path, or end() if there is none.
std::pair< iterator, bool > _IterBoolPair
Result type for insert().
SDF_API SdfPath GetParentPath() const
Return the path that identifies this path's namespace parent.
This class provides a non-owning reference to a type-erased callable object with a specified signatur...
static NodeHandle New(value_type &&value)
SdfPathTable(SdfPathTable const &other)
Copy constructor.
_IterBoolPair insert(NodeHandle &&node)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void ParallelForEach(Callback const &visitFn) const
ParallelForEach: const version, runnable on a const path table and taking a (const SdfPath&,...
SdfPathTable(SdfPathTable &&other)
Move constructor.
std::pair< const_iterator, const_iterator > FindSubtreeRange(SdfPath const &path) const
Return a pair of const_iterators [b, e), describing the maximal range such that for all i in the rang...
void reset()
Delete any owned path table entry.
mapped_type & GetMutableMapped()
Return a mutable reference to this NodeHandle's mapped object.
void swap(UsdStageLoadRules &l, UsdStageLoadRules &r)
Swap the contents of rules l and r.
bool empty() const
Return true if this table is empty.
iterator end()
Return an iterator denoting the end of the table.
bool erase(SdfPath const &path)
Remove the element with path path from the table as well as all elements whose paths are prefixed by ...
void ParallelForEach(Callback const &visitFn)
ParallelForEach: parallel iteration over all of the key-value pairs in the path table.
const_iterator begin() const
Return a const_iterator to the start of the table.
static NodeHandle New(key_type const &key, mapped_type const &mapped)
A path value used to locate objects in layers or scenegraphs.
A handle owning a path table node that may be used to "reserve" a stable memory location for key & ma...
iterator begin()
Return an iterator to the start of the table.
_IterBoolPair insert(value_type const &value)
Insert value into the table, and additionally insert default entries for all ancestral paths of value...
mapped_type const & GetMapped() const
Return a const reference to this NodeHandle's mapped object.
void clear()
Remove all elements from the table, leaving size() == 0.
SdfPathTable()
Default constructor.
std::vector< size_t > GetBucketSizes() const
Return a vector of the count of elements in each bucket.
static SDF_API const SdfPath & AbsoluteRootPath()
The absolute path representing the top of the namespace hierarchy.
void swap(SdfPathTable &other)
Swap this table's contents with other.
iterator find(SdfPath const &path)
Return an iterator to the element corresponding to path, or end() if there is none.
bool IsValid() const
Return true if this NodeHandle owns a path table entry, false otherwise.
static NodeHandle New(value_type const &value)
Create a new NodeHandle for a table entry.
A mapping from SdfPath to MappedType, somewhat similar to map<SdfPath, MappedType> and TfHashMap<SdfP...
std::pair< iterator, iterator > FindSubtreeRange(SdfPath const &path)
Return a pair of iterators [b, e), describing the maximal range such that for all i in the range,...
key_type & GetMutableKey()
Return a mutable reference to this NodeHandle's key.
void erase(iterator const &i)
Remove the element pointed to by i from the table as well as all elements whose paths are prefixed by...
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
void ClearInParallel()
Equivalent to clear(), but destroy contained objects in parallel.