Geogram Version 1.10.1
A programming library of geometric algorithms
Loading...
Searching...
No Matches
attributes.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40
41#ifndef GEOGRAM_BASIC_ATTRIBUTES
42#define GEOGRAM_BASIC_ATTRIBUTES
43
51
52#include <map>
53#include <typeinfo>
54#include <set>
55#include <type_traits>
56
62namespace GEO {
63
64 class AttributeStore;
65
70 class GEOGRAM_API AttributeStoreObserver {
71 public:
72
77 base_addr_(nullptr), size_(0), dimension_(0),
78 disconnected_(false) {
79 }
80
88 void notify(
89 Memory::pointer base_addr, index_t size, index_t dim
90 ) {
91 base_addr_ = base_addr;
92 size_ = size;
93 dimension_ = dim;
94 }
95
100 index_t size() const {
101 return size_;
102 }
103
109 return dimension_;
110 }
111
119 return size_ * dimension_;
120 }
121
127 return base_addr_;
128 }
129
135
141
149 void disconnect() {
150 base_addr_ = nullptr;
151 size_ = 0;
152 dimension_ = 0;
153 disconnected_ = true;
154 }
155
162 bool disconnected() const {
163 return disconnected_;
164 }
165
166 protected:
167 Memory::pointer base_addr_;
168 index_t size_;
169 index_t dimension_;
170 bool disconnected_;
171 };
172
173
174 /*********************************************************************/
175
176
181 class GEOGRAM_API AttributeStoreCreator : public Counted {
182 public:
183
188
195
203 virtual bool elements_are_trivially_copyable() const = 0;
204
205 private:
206 std::string element_type_name_;
207 std::string element_typeid_name_;
208 };
209
215
221 class GEOGRAM_API AttributeStore {
222 public:
232 AttributeStore(size_t elemsize, index_t dim=1);
233
238
239
250 const std::string& type_name
251 ) const = 0;
252
258 virtual std::string element_typeid_name() const = 0;
259
267 virtual std::string user_element_typeid_name() const = 0;
268
273 index_t size() const {
274 return cached_size_;
275 }
276
283 return cached_capacity_;
284 }
285
290 virtual void resize(index_t new_size) = 0;
291
297 virtual void reserve(index_t new_capacity) = 0;
298
304 virtual void clear(bool keep_memory = false) = 0;
305
311 bool has_observers() const {
312 return !observers_.empty();
313 }
314
321 return dimension_;
322 }
323
333 virtual void redim(index_t dim) = 0;
334
335
351 virtual void apply_permutation(
352 const vector<index_t>& permutation
353 );
354
355
371 virtual void compress(const vector<index_t>& old2new);
372
377 virtual void zero();
378
384 virtual AttributeStore* clone() const = 0;
385
386
392 void copy_item(index_t to, index_t from) {
393 geo_debug_assert(from < cached_size_);
394 geo_debug_assert(to < cached_size_);
395 size_t item_size = element_size_ * dimension_;
396 if(lifecycle_.is_null()) {
397 Memory::copy(
398 cached_base_addr_+to*item_size,
399 cached_base_addr_+from*item_size,
400 item_size
401 );
402 } else {
403 lifecycle_->assign(
404 cached_base_addr_+to*item_size,
405 cached_base_addr_+from*item_size
406 );
407 }
408 }
409
415 geo_debug_assert(to < cached_size_);
416 size_t item_size = element_size_ * dimension_;
417 if(lifecycle_.is_null()) {
418 Memory::clear(
419 cached_base_addr_+to*item_size,
420 item_size
421 );
422 } else {
423 lifecycle_->reset(cached_base_addr_+to*item_size);
424 }
425 }
426
434 virtual void scale_item(index_t to, double s);
435
444 virtual void madd_item(index_t to, double s, index_t from);
445
451
456 void* data() {
457 return cached_base_addr_;
458 }
459
464 const void* data() const {
465 return cached_base_addr_;
466 }
467
472 size_t element_size() const {
473 return element_size_;
474 }
475
485 const std::string& element_type_name
486 ) {
487 return (
488 type_name_to_creator_.find(element_type_name) !=
489 type_name_to_creator_.end()
490 );
491 }
492
502 const std::string& element_typeid_name
503 ) {
504 return (
505 typeid_name_to_type_name_.find(element_typeid_name) !=
506 typeid_name_to_type_name_.end()
507 );
508 }
509
520 const std::string& element_type_name
521 ) {
522 geo_debug_assert(element_type_name_is_known(element_type_name));
523 return (
524 type_name_to_creator_[
525 element_type_name
526 ]->elements_are_trivially_copyable()
527 );
528 }
529
540 const std::string& element_typeid_name
541 ) {
542 geo_debug_assert(element_typeid_name_is_known(element_typeid_name));
543 std::string element_type_name =
544 typeid_name_to_type_name_[element_typeid_name];
545 return element_by_type_name_is_trivially_copyable(element_type_name);
546 }
547
555 const std::string& element_type_name,
556 index_t dimension
557 ) {
558 geo_assert(element_type_name_is_known(element_type_name));
559 return type_name_to_creator_[element_type_name]->
560 create_attribute_store(dimension);
561 }
562
571 const std::string& element_typeid_name
572 ) {
573 geo_assert(element_typeid_name_is_known(element_typeid_name));
574 return typeid_name_to_type_name_[element_typeid_name];
575 }
576
586 const std::string& element_type_name
587 ) {
588 geo_assert(element_type_name_is_known(element_type_name));
589 return type_name_to_typeid_name_[element_type_name];
590 }
591
603 AttributeStoreCreator* creator,
604 const std::string& element_type_name,
605 const std::string& element_typeid_name
606 );
607
616 return lifecycle_;
617 }
618
619 protected:
620
627 const vector<index_t>& permutation
628 );
629
638 virtual void notify(
639 Memory::pointer base_addr, index_t size, index_t dim
640 );
641
651
660
661
662 protected:
663 size_t element_size_;
664 index_t dimension_;
665 Memory::pointer cached_base_addr_;
666 index_t cached_size_;
667 index_t cached_capacity_;
668 LifeCycle_var lifecycle_;
669 std::set<AttributeStoreObserver*> observers_;
670 Process::spinlock lock_;
671
672 static std::map<std::string, AttributeStoreCreator_var>
673 type_name_to_creator_;
674
675 static std::map<std::string, std::string>
676 typeid_name_to_type_name_;
677
678 static std::map<std::string, std::string>
679 type_name_to_typeid_name_;
680
681 friend class AttributeStoreObserver;
682 };
683
684 /*********************************************************************/
685
692 template <class ST> class TypedAttributeStore : public AttributeStore {
693 public:
694
705 index_t dim=1, const std::type_info& user_type_info = typeid(ST)
706 ) :
707 AttributeStore(sizeof(ST),dim),
708 storage_type_(typeid(ST)),
709 user_type_(user_type_info) {
710 if(!std::is_trivially_copyable<ST>::value) {
711 lifecycle_ = new GenericLifeCycle<ST>();
712 }
713 }
714
715 void resize(index_t new_size) override {
716 store_.resize(new_size*dimension_);
717 notify(
718 store_.empty() ? nullptr : Memory::pointer(store_.data()),
719 new_size,
720 dimension_
721 );
722 }
723
724 void reserve(index_t new_capacity) override {
725 if(new_capacity > capacity()) {
726 store_.reserve(new_capacity*dimension_);
727 cached_capacity_ = new_capacity;
728 notify(
729 store_.empty() ? nullptr : Memory::pointer(store_.data()),
730 size(),
731 dimension_
732 );
733 }
734 }
735
736 void clear(bool keep_memory=false) override {
737 if(keep_memory) {
738 store_.resize(0);
739 } else {
740 store_.clear();
741 }
742 notify(nullptr, 0, dimension_);
743 }
744
745 void redim(index_t dim) override {
746 if(dim == dimension()) {
747 return;
748 }
749 vector<ST> new_store(size()*dim);
750 new_store.reserve(capacity()*dim);
751 index_t copy_dim = std::min(dim, dimension());
752 for(index_t i = 0; i < size(); ++i) {
753 for(index_t c = 0; c < copy_dim; ++c) {
754 new_store[dim * i + c] = store_[dimension_ * i + c];
755 }
756 }
757 store_.swap(new_store);
758 notify(
759 store_.empty() ? nullptr : Memory::pointer(store_.data()),
760 size(),
761 dim
762 );
763 }
764
765 bool elements_type_matches(const std::string& type_name) const override {
766 return (
767 type_name == storage_type_.name() ||
768 type_name == user_type_.name()
769 );
770 }
771
772 std::string element_typeid_name() const override {
773 return storage_type_.name();
774 }
775
776 std::string user_element_typeid_name() const override {
777 return user_type_.name();
778 }
779
780 AttributeStore* clone() const override {
782 new TypedAttributeStore<ST>(dimension(), user_type_);
783 result->resize(size());
784 result->store_ = store_;
785 result->lifecycle_ = lifecycle_;
786 return result;
787 }
788
789 vector<ST>& get_vector() {
790 return store_;
791 }
792
793 void scale_item(index_t to, double s) override {
794 geo_assert(to < size());
795 for(index_t i=0; i<dimension_; ++i) {
796 scale_value(store_[to*dimension_+i], s);
797 }
798 }
799
800 void madd_item(index_t to, double s, index_t from) override {
801 geo_assert(from < size());
802 geo_assert(to < size());
803 for(index_t i=0; i<dimension_; ++i) {
804 madd_value(
805 store_[to*dimension_+i], s, store_[from*dimension_+i]
806 );
807 }
808 }
809
810 protected:
811 void notify(
812 Memory::pointer base_addr, index_t size, index_t dim
813 ) override {
814 AttributeStore::notify(base_addr, size, dim);
815 geo_assert(size*dim <= store_.size());
816 }
817
818 template<class TT> static void scale_value(TT& to, double s) {
819 geo_argused(to);
820 geo_argused(s);
821 }
822
823 static void scale_value(uint8_t& to, double s) {
824 to = uint8_t(double(to)*s != 0.0);
825 }
826
827 static void scale_value(int32_t& to, double s) {
828 to = int32_t(double(to)*s);
829 }
830
831 static void scale_value(uint32_t& to, double s) {
832 to = uint32_t(double(to)*s);
833 }
834
835 static void scale_value(float& to, double s) {
836 to = float(double(to)*s);
837 }
838
839 static void scale_value(double& to, double s) {
840 to *= s;
841 }
842
843 template<class TT> static void madd_value(TT& to, double s, TT& from) {
844 geo_argused(to);
845 geo_argused(s);
846 geo_argused(from);
847 }
848
849 static void madd_value(uint8_t& to, double s, uint8_t& from) {
850 to = uint8_t(double(to) + s*double(from) != 0.0);
851 }
852
853 static void madd_value(int32_t& to, double s, int32_t& from) {
854 to = int32_t(double(to) + s*double(from));
855 }
856
857 static void madd_value(uint32_t& to, double s, uint32_t& from) {
858 to = uint32_t(double(to) + s*double(from));
859 }
860
861 static void madd_value(float& to, double s, float& from) {
862 to = float(double(to) + s*double(from));
863 }
864
865 static void madd_value(double& to, double s, double& from) {
866 to += s*from;
867 }
868
869 private:
870 vector<ST> store_;
871 const std::type_info& storage_type_;
872 const std::type_info& user_type_;
873 };
874
875 /*********************************************************************/
876
882 template <class UT, class ST=UT>
884 public:
889 return new TypedAttributeStore<ST>(dim,typeid(UT));
890 }
891
895 bool elements_are_trivially_copyable() const override {
896 return(std::is_trivially_copyable<ST>::value);
897 }
898 };
899
900 /*********************************************************************/
901
909 template <class UT, class ST=UT> class geo_register_attribute_type {
910 public:
920 geo_register_attribute_type(const std::string& type_name) {
923 type_name, typeid(UT).name()
924 );
925 if(type_name == "bool") {
927 type_name,
930 );
931 } else {
933 type_name,
934 read_ascii_attribute<UT>,
935 write_ascii_attribute<UT>
936 );
937 }
938 }
939 };
940
941 /*********************************************************************/
942
947 class GEOGRAM_API AttributesManager {
948 public:
953
954
959
965 index_t nb() const {
966 return index_t(attributes_.size());
967 }
968
975
982 index_t size() const {
983 return size_;
984 }
985
992 return capacity_;
993 }
994
1001 void resize(index_t new_size);
1002
1009 void reserve(index_t new_capacity);
1010
1019 void clear(bool keep_attributes, bool keep_memory = false);
1020
1021
1025 void zero();
1026
1035 void bind_attribute_store(const std::string& name, AttributeStore* as);
1036
1043 AttributeStore* find_attribute_store(const std::string& name);
1044
1052 const std::string& name, vector<double>& out, index_t& dim
1053 ) const;
1054
1061 const std::string& name, const vector<double>& in, index_t dim
1062 );
1063
1071 const std::string& name
1072 ) const;
1073
1074
1081 bool is_defined(const std::string& name) const {
1082 return (find_attribute_store(name) != nullptr);
1083 }
1084
1090 void delete_attribute_store(const std::string& name);
1091
1098
1115 const vector<index_t>& permutation
1116 );
1117
1133 void compress(const vector<index_t>& old2new);
1134
1139 void copy(const AttributesManager& rhs);
1140
1141
1148 void copy_item(index_t to, index_t from);
1149
1156
1157
1163
1171 void scale_item(index_t to, double s);
1172
1181 void madd_item(index_t to, double s, index_t from);
1182
1192 const std::string& name, const std::string& new_name
1193 );
1194
1204 const std::string& old_name, const std::string& new_name
1205 );
1206
1207 private:
1215 AttributesManager(const AttributesManager& rhs) = delete;
1216
1224 const AttributesManager& operator=(const AttributesManager& rhs) = delete;
1225
1226 private:
1227 index_t size_;
1228 index_t capacity_;
1229 std::map<std::string, AttributeStore*> attributes_;
1230 } ;
1231
1232
1233 /*********************************************************************/
1234
1235
1242 template <class UT, class ST = UT>
1244 public:
1245
1250 manager_(nullptr),
1251 store_(nullptr),
1252 existed_already_(false) {
1253 }
1254
1264 AttributeBase(AttributesManager& manager, const std::string& name) :
1265 manager_(nullptr),
1266 store_(nullptr),
1267 existed_already_(false) {
1268 bind(manager, name);
1269 }
1270
1276 bool is_bound() const {
1277 return (store_ != nullptr && !disconnected_);
1278 }
1279
1287 bool existed_already() const {
1288 return existed_already_;
1289 }
1290
1295 void unbind() {
1297 // If the AttributesManager was destroyed before, do not
1298 // do anything. This can occur in Lua scripting when using
1299 // Attribute wrapper objects.
1300 if(!disconnected_) {
1301 unregister_me(store_);
1302 }
1303 manager_ = nullptr;
1304 store_ = nullptr;
1305 existed_already_ = false;
1306 }
1307
1317 void bind(AttributesManager& manager, const std::string& name) {
1318 geo_assert(!is_bound());
1319 manager_ = &manager;
1320 store_ = manager_->find_attribute_store(name);
1321 if(store_ == nullptr) {
1322 store_ = new TypedAttributeStore<ST>(1,typeid(UT));
1323 manager_->bind_attribute_store(name,store_);
1324 existed_already_ = false;
1325 } else {
1326 geo_assert(can_bind_to(store_));
1327 existed_already_ = true;
1328 }
1329 register_me(store_);
1330 }
1331
1332
1342 AttributesManager& manager, const std::string& name
1343 ) {
1344 geo_assert(!is_bound());
1345 manager_ = &manager;
1346 store_ = manager_->find_attribute_store(name);
1347 if(store_ != nullptr) {
1348 geo_assert(can_bind_to(store_));
1349 register_me(store_);
1350 existed_already_ = true;
1351 return true;
1352 }
1353 existed_already_ = false;
1354 return false;
1355 }
1356
1366 AttributesManager& manager, const std::string& name
1367 ) {
1368 if( is_bound() ) {
1369 unbind();
1370 }
1371 store_ = manager.find_attribute_store(name);
1372 if(store_ != nullptr) {
1373 existed_already_ = true;
1374 if(!can_bind_to(store_)) {
1375 store_ = nullptr;
1376 return false;
1377 }
1378 manager_ = &manager;
1379 register_me(store_);
1380 return true;
1381 }
1382 existed_already_ = false;
1383 return false;
1384 }
1385
1394 const std::string& name,
1396 ) {
1397 geo_assert(!is_bound());
1398 manager_ = &manager;
1399 geo_assert(manager_->find_attribute_store(name) == nullptr);
1400 store_ = new TypedAttributeStore<ST>(dimension,typeid(UT));
1401 manager_->bind_attribute_store(name,store_);
1402 register_me(store_);
1403 }
1404
1411 void destroy() {
1413 unregister_me(store_);
1414 manager_->delete_attribute_store(store_);
1415 store_ = nullptr;
1416 manager_ = nullptr;
1417 }
1418
1428 void redim(index_t new_dim) {
1430 store_->redim(new_dim);
1431 }
1432
1441 if(is_bound()) {
1442 unbind();
1443 }
1444 }
1445
1446
1454 static bool is_defined(
1455 AttributesManager& manager, const std::string& name,
1456 index_t dim = 0
1457 ) {
1459 return (
1460 store != nullptr &&
1461 can_bind_to(store) &&
1462 ((dim == 0) || (store->dimension() == dim))
1463 );
1464 }
1465
1470 index_t size() const {
1471 return size_;
1472 }
1473
1478 void zero() {
1480 store_->zero();
1481 }
1482
1493 return(
1494 dynamic_cast<TypedAttributeStore<ST>*>(store_) != nullptr
1495 );
1496 }
1497
1509 TypedAttributeStore<ST>* typed_store =
1510 dynamic_cast<TypedAttributeStore<ST>*>(store_);
1511 geo_assert(typed_store != nullptr);
1512 return typed_store->get_vector();
1513 }
1514
1521 const vector<ST>& get_vector() const {
1522 TypedAttributeStore<ST>* typed_store =
1523 dynamic_cast<TypedAttributeStore<ST>*>(store_);
1524 geo_assert(typed_store != nullptr);
1525 return typed_store->get_vector();
1526 }
1527
1533 return manager_;
1534 }
1535
1536 protected:
1537
1544 static bool can_bind_to(const AttributeStore* store) {
1545 return (
1546 store->elements_type_matches(typeid(UT).name()) ||
1547 store->elements_type_matches(typeid(ST).name())
1548 );
1549 }
1550
1551 protected:
1552 AttributesManager* manager_;
1553 AttributeStore* store_;
1554 bool existed_already_;
1555 } ;
1556
1557 /*********************************************************************/
1558
1565 template <class T> class Attribute : public AttributeBase<T> {
1566 public:
1568
1573 }
1574
1584 Attribute(AttributesManager& manager, const std::string& name) :
1585 superclass(manager, name) {
1586 }
1587
1596 return ((T*)(void*)superclass::base_addr_)[i];
1597 }
1598
1604 const T& operator[](index_t i) const {
1607 return ((const T*)(void*)superclass::base_addr_)[i];
1608 }
1609
1615 void fill(const T& val) {
1617 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1618 (*this)[i] = val;
1619 }
1620 }
1621
1628 void copy(const Attribute<T>& rhs) {
1629 geo_assert(rhs.size() == superclass::size());
1631 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1632 (*this)[i] = rhs[i];
1633 }
1634 }
1635
1640 T* data() {
1641 return (T*)AttributeStoreObserver::base_addr_;
1642 }
1643
1648 const T* data() const {
1649 return (const T*)AttributeStoreObserver::base_addr_;
1650 }
1651
1652
1653 private:
1657 Attribute(const Attribute<T>& rhs) = delete;
1661 Attribute<T>& operator=(const Attribute<T>& rhs) = delete;
1662 };
1663
1664 /*********************************************************************/
1665
1674 template <> class Attribute<bool> :
1675 public AttributeBase<bool,Numeric::uint8> {
1676 public:
1678
1679 Attribute() : superclass() {
1680 }
1681
1682 Attribute(AttributesManager& manager, const std::string& name) :
1683 superclass(manager,name) {
1684 }
1685
1686 class BoolAttributeAccessor;
1687
1692 class ConstBoolAttributeAccessor {
1693 public:
1698 const Attribute<bool>& attribute,
1699 index_t index
1700 ) :
1701 attribute_(&attribute),
1702 index_(index) {
1703 }
1704
1709 operator bool() const {
1710 return (attribute_->element(index_) != 0);
1711 }
1712
1713 private:
1714 const Attribute<bool>* attribute_;
1715 index_t index_;
1716
1717 friend class BoolAttributeAccessor;
1718 };
1719
1724 class BoolAttributeAccessor {
1725 public:
1730 Attribute<bool>& attribute,
1731 index_t index
1732 ) :
1733 attribute_(&attribute),
1734 index_(index) {
1735 }
1736
1741 operator bool() const {
1742 return (attribute_->element(index_) != 0);
1743 }
1744
1750 BoolAttributeAccessor(const BoolAttributeAccessor& rhs) {
1751 attribute_ = rhs.attribute_;
1752 index_ = rhs.index_;
1753 }
1754
1759 BoolAttributeAccessor& operator=(bool x) {
1760 attribute_->element(index_) = Numeric::uint8(x);
1761 return *this;
1762 }
1763
1769 BoolAttributeAccessor& operator=(
1770 const BoolAttributeAccessor& rhs
1771 ) {
1772 if(&rhs != this) {
1773 attribute_->element(index_) =
1774 rhs.attribute_->element(rhs.index_);
1775 }
1776 return *this;
1777 }
1778
1784 BoolAttributeAccessor& operator=(
1785 const ConstBoolAttributeAccessor& rhs
1786 ) {
1787 attribute_->element(index_) =
1788 rhs.attribute_->element(rhs.index_);
1789 return *this;
1790 }
1791
1792 private:
1793 Attribute<bool>* attribute_;
1794 index_t index_;
1795 };
1796
1797
1798 BoolAttributeAccessor operator[](index_t i) {
1799 return BoolAttributeAccessor(*this,i);
1800 }
1801
1802 ConstBoolAttributeAccessor operator[](index_t i) const {
1803 return ConstBoolAttributeAccessor(*this,i);
1804 }
1805
1811 void fill(bool val) {
1812 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1813 element(i) = Numeric::uint8(val);
1814 }
1815 }
1816
1823 void copy(const Attribute<bool>& rhs) {
1824 geo_assert(rhs.size() == superclass::size());
1826 for(index_t i=0; i<superclass::nb_elements(); ++i) {
1827 element(i) = rhs.element(i);
1828 }
1829 }
1830
1831 protected:
1832
1833 friend class BoolAttributeAccessor;
1834 friend class ConstBoolAttributeAccessor;
1835
1843 return ((Numeric::uint8*)superclass::base_addr_)[i];
1844 }
1845
1853 return ((const Numeric::uint8*)superclass::base_addr_)[i];
1854 }
1855
1856 private:
1860 Attribute(const Attribute<bool>& rhs) = delete;
1864 Attribute<bool>& operator=(const Attribute<bool>& rhs) = delete;
1865 } ;
1866
1867 /***********************************************************/
1868
1873 class GEOGRAM_API ScalarAttributeAdapterBase :
1874 public AttributeStoreObserver {
1875
1876 public:
1881 ET_NONE=0,
1882 ET_UINT8=1,
1883 ET_INT8=2,
1884 ET_UINT32=3,
1885 ET_INT32=4,
1886 ET_FLOAT32=5,
1887 ET_FLOAT64=6,
1888 ET_VEC2=7,
1889 ET_VEC3=8
1890 };
1891
1892
1897 class Accessor {
1898 public:
1899 Accessor(
1900 ScalarAttributeAdapterBase& attribute,
1901 index_t index
1902 ) : attribute_(attribute), index_(index) {
1903 }
1904
1905 operator double() const {
1906 return attribute_.get_element_as_double(index_);
1907 }
1908
1909 void operator=(double x) {
1910 attribute_.set_element_as_double(index_, x);
1911 }
1912
1913 private:
1914 ScalarAttributeAdapterBase& attribute_;
1915 index_t index_;
1916 };
1917
1923 public:
1925 const ScalarAttributeAdapterBase& attribute,
1926 index_t index
1927 ) : attribute_(attribute), index_(index) {
1928 }
1929
1930 operator double() const {
1931 return attribute_.get_element_as_double(index_);
1932 }
1933
1934 private:
1935 const ScalarAttributeAdapterBase& attribute_;
1936 index_t index_;
1937 };
1938
1943 manager_(nullptr),
1944 store_(nullptr),
1945 element_type_(ET_NONE),
1946 element_index_(index_t(-1)) {
1947 }
1948
1959 const AttributesManager& manager, const std::string& name
1960 ) :
1961 manager_(nullptr),
1962 store_(nullptr) {
1963 bind_if_is_defined(manager, name);
1964 }
1965
1971 bool is_bound() const {
1972 return (store_ != nullptr);
1973 }
1974
1979 void unbind() {
1980 geo_assert(is_bound());
1981 unregister_me(const_cast<AttributeStore*>(store_));
1982 manager_ = nullptr;
1983 store_ = nullptr;
1984 element_type_ = ET_NONE;
1985 element_index_ = index_t(-1);
1986 }
1987
1998 const AttributesManager& manager, const std::string& name
1999 );
2000
2009 if(is_bound()) {
2010 unbind();
2011 }
2012 }
2013
2023 static bool is_defined(
2024 const AttributesManager& manager, const std::string& name
2025 );
2026
2031 index_t size() const {
2032 return (store_ == nullptr) ? 0 : store_->size();
2033 }
2034
2043 return element_type_;
2044 }
2045
2053 return element_index_;
2054 }
2055
2061 return store_;
2062 }
2063
2064
2072 static bool can_be_bound_to(const AttributeStore* store) {
2073 return element_type(store) != ET_NONE;
2074 }
2075
2084
2085 protected:
2094 static std::string attribute_base_name(const std::string& name);
2095
2104 static index_t attribute_element_index(const std::string& name);
2105
2114
2123 double result = 0.0;
2124 switch(element_type()) {
2125 case ET_UINT8:
2126 result = double(get_element<Numeric::uint8>(i));
2127 break;
2128 case ET_INT8:
2129 result = double(get_element<Numeric::int8>(i));
2130 break;
2131 case ET_UINT32:
2132 result = double(get_element<Numeric::uint32>(i));
2133 break;
2134 case ET_INT32:
2135 result = double(get_element<Numeric::int32>(i));
2136 break;
2137 case ET_FLOAT32:
2138 result = double(get_element<Numeric::float32>(i));
2139 break;
2140 case ET_FLOAT64:
2141 result = double(get_element<Numeric::float64>(i));
2142 break;
2143 case ET_VEC2:
2144 result = double(get_element<Numeric::float64>(i,2));
2145 break;
2146 case ET_VEC3:
2147 result = double(get_element<Numeric::float64>(i,3));
2148 break;
2149 case ET_NONE:
2151 }
2152 return result;
2153 }
2154
2163 template <class T> T get_element(index_t i,index_t multiplier=1) const {
2164 geo_debug_assert(is_bound());
2165 geo_debug_assert(i < size());
2166 return static_cast<const T*>(store_->data())[
2167 (i * store_->dimension() * multiplier) +
2168 element_index_
2169 ];
2170 }
2171
2178 double set_element_as_double(index_t i, double value) {
2179 double result = 0.0;
2180 switch(element_type()) {
2181 case ET_UINT8:
2182 set_element<Numeric::uint8>(Numeric::uint8(value), i);
2183 break;
2184 case ET_INT8:
2185 set_element<Numeric::int8>(Numeric::int8(value),i);
2186 break;
2187 case ET_UINT32:
2188 set_element<Numeric::uint32>(Numeric::uint32(value),i);
2189 break;
2190 case ET_INT32:
2191 set_element<Numeric::int32>(Numeric::int32(value),i);
2192 break;
2193 case ET_FLOAT32:
2194 set_element<Numeric::float32>(Numeric::float32(value),i);
2195 break;
2196 case ET_FLOAT64:
2197 set_element<Numeric::float64>(Numeric::float64(value),i);
2198 break;
2199 case ET_VEC2:
2200 set_element<Numeric::float64>(Numeric::float64(value),i,2);
2201 break;
2202 case ET_VEC3:
2203 set_element<Numeric::float64>(Numeric::float64(value),i,3);
2204 break;
2205 case ET_NONE:
2207 }
2208 return result;
2209 }
2210
2220 template <class T> void set_element(
2221 T value, index_t i, index_t multiplier=1
2222 ) const {
2223 geo_debug_assert(is_bound());
2224 geo_debug_assert(i < size());
2225 const_cast<T*>(static_cast<const T*>(store_->data()))[
2226 (i * store_->dimension() * multiplier) +
2227 element_index_
2228 ] = value;
2229 }
2230
2231 protected:
2232 const AttributesManager* manager_;
2233 const AttributeStore* store_;
2234 ElementType element_type_;
2235 index_t element_index_;
2236 };
2237
2238 /***********************************************************/
2239
2245 public:
2247 }
2248
2250 const AttributesManager& manager, const std::string& name
2251 ) : ScalarAttributeAdapterBase(manager, name) {
2252 }
2253
2262 return get_element_as_double(i);
2263 }
2264 };
2265
2266 /***********************************************************/
2267
2273 public:
2275 }
2276
2278 const AttributesManager& manager, const std::string& name
2279 ) : ScalarAttributeAdapterBase(manager, name) {
2280 }
2281
2282 Accessor operator[](index_t i) {
2283 return Accessor(*this, i);
2284 }
2285
2286 ConstAccessor operator[](index_t i) const {
2287 return ConstAccessor(*this, i);
2288 }
2289
2290 protected:
2291 };
2292
2293
2294}
2295
2296#endif
#define geo_assert_not_reached
Sets a non reachable point in the program.
Definition assert.h:177
#define geo_assert(x)
Verifies that a condition is met.
Definition assert.h:149
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
Base class for Attributes, that manipulates an attribute stored in an AttributesManager.
bool can_get_vector()
Tests whether get_vector() can be called on this Attribute.
void zero()
Sets all the elements of this Attribute to zero.
void bind(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager.
AttributeBase(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
vector< ST > & get_vector()
Gets a reference to the internal vector<T> used to store the attribute.
bool bind_if_is_compatible(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager and types ...
bool is_bound() const
Tests whether an Attribute is bound.
void redim(index_t new_dim)
Sets the dimension.
static bool can_bind_to(const AttributeStore *store)
Tests whether this Attribute can be bound to an AttributeStore.
AttributeBase()
Creates an uninitialized (unbound) Attribute.
AttributesManager * manager() const
Gets the AttributesManager this Attribute is bound to.
void destroy()
Destroys this attribute in the AttributesManager.
static bool is_defined(AttributesManager &manager, const std::string &name, index_t dim=0)
Tests whether an attribute with the specified name and with corresponding type exists in an Attribute...
~AttributeBase()
Attribute destructor.
index_t size() const
Gets the size.
bool existed_already() const
Tests whether the latest bound attribute existed already.
void unbind()
Unbinds this Attribute.
const vector< ST > & get_vector() const
Gets a const reference to the internal vector<T> used to store the attribute.
bool bind_if_is_defined(AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager.
void create_vector_attribute(AttributesManager &manager, const std::string &name, index_t dimension)
Creates and binds a new vector attribute.
Internal class for creating an AttributeStore from the type name of its elements.
Definition attributes.h:181
~AttributeStoreCreator() override
AttributeStoreCreator destructor.
virtual bool elements_are_trivially_copyable() const =0
Tests whether elements of this attribute can be trivially copyable.
virtual AttributeStore * create_attribute_store(index_t dimension)=0
Creates a new attribute store.
Base class for attributes. They are notified whenever the AttributeStore is modified.
Definition attributes.h:70
AttributeStoreObserver()
Creates a new uninitialied AttributeStore.
Definition attributes.h:76
void register_me(AttributeStore *store)
Registers this observer to an AttributeStore.
index_t size() const
Gets the size.
Definition attributes.h:100
void notify(Memory::pointer base_addr, index_t size, index_t dim)
Callback function, called by the AttributeStore whenever it is modified.
Definition attributes.h:88
index_t nb_elements() const
Gets the total number of elements.
Definition attributes.h:118
bool disconnected() const
Tests whether this AttributeStoreObserver was disconnected.
Definition attributes.h:162
void disconnect()
Disconnects this AttributeStoreObserver from its AttributeStore.
Definition attributes.h:149
void unregister_me(AttributeStore *store)
Unregisters this observer from an AttributeStore.
index_t dimension() const
Gets the dimension.
Definition attributes.h:108
Memory::pointer base_addr() const
Gets a pointer to the storage.
Definition attributes.h:126
Notifies a set of AttributeStoreObservers each time the stored array changes size and/or base address...
Definition attributes.h:221
void * data()
Gets a pointer to the stored data.
Definition attributes.h:456
static AttributeStore * create_attribute_store_by_element_type_name(const std::string &element_type_name, index_t dimension)
Creates an attribute store of a given type.
Definition attributes.h:554
bool has_observers() const
Tests whether observers listen to this AttributeStore.
Definition attributes.h:311
void zero_item(index_t to)
Sets an item to zero.
Definition attributes.h:414
virtual ~AttributeStore()
AttributeStore destructor.
static std::string element_typeid_name_by_element_type_name(const std::string &element_type_name)
Gets an element mangled type name from its C++ name.
Definition attributes.h:585
static void register_attribute_creator(AttributeStoreCreator *creator, const std::string &element_type_name, const std::string &element_typeid_name)
Registers a new element type.
index_t size() const
Gets the size.
Definition attributes.h:273
const void * data() const
Gets a pointer to the stored data.
Definition attributes.h:464
virtual void clear(bool keep_memory=false)=0
Resizes this AttributeStore to 0.
virtual void notify(Memory::pointer base_addr, index_t size, index_t dim)
If size or base address differ from the cached values, notify all the observers, and update the cache...
AttributeStore(size_t elemsize, index_t dim=1)
AttributeStore constructor.
index_t capacity() const
Gets the capacity.
Definition attributes.h:282
virtual void madd_item(index_t to, double s, index_t from)
Adds a scaled item to another item \detais item[to] += s * item[from].
static bool element_by_typeid_name_is_trivially_copyable(const std::string &element_typeid_name)
Tests whether an element type is trivially copyable.
Definition attributes.h:539
static bool element_type_name_is_known(const std::string &element_type_name)
Tests whether a given element type is registered in the system.
Definition attributes.h:484
void apply_permutation_with_lifecycle(const vector< index_t > &permutation)
implementation of apply_permutation() used when there is a lifecycle, that is, when attribute type is...
virtual void compress(const vector< index_t > &old2new)
Compresses the stored attributes, by applying an index mapping that fills-in the gaps.
LifeCycle * lifecycle() const
Gets the LifeCycle.
Definition attributes.h:615
virtual std::string element_typeid_name() const =0
Gets the typeid name of the element type stored in this AttributeStore.
void copy_item(index_t to, index_t from)
Copies an item.
Definition attributes.h:392
virtual AttributeStore * clone() const =0
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
static bool element_typeid_name_is_known(const std::string &element_typeid_name)
Tests whether a given element type is registered in the system.
Definition attributes.h:501
virtual std::string user_element_typeid_name() const =0
Gets the user typeid name of the element type stored in this AttributeStore.
void register_observer(AttributeStoreObserver *observer)
Registers an observer.
virtual void apply_permutation(const vector< index_t > &permutation)
Applies a permutation to the stored attributes.
virtual void resize(index_t new_size)=0
Resizes this AttributeStore.
virtual void scale_item(index_t to, double s)
Scales an item.
void unregister_observer(AttributeStoreObserver *observer)
Unregisters an observer.
virtual void redim(index_t dim)=0
Sets the dimension.
index_t dimension() const
Gets the dimension.
Definition attributes.h:320
static std::string element_type_name_by_element_typeid_name(const std::string &element_typeid_name)
Gets an element type name from its mangled name.
Definition attributes.h:570
virtual bool elements_type_matches(const std::string &type_name) const =0
Tests whether this AttributeStore stores elements of a given type.
void swap_items(index_t i, index_t j)
Swaps two items.
static bool element_by_type_name_is_trivially_copyable(const std::string &element_type_name)
Tests whether an element type is trivially copyable.
Definition attributes.h:519
size_t element_size() const
Gets the element size.
Definition attributes.h:472
virtual void reserve(index_t new_capacity)=0
Reserves memory.
virtual void zero()
Zeroes all the memory associated with this AttributeStore.
BoolAttributeAccessor(Attribute< bool > &attribute, index_t index)
BoolAttributeAccessor constructor.
BoolAttributeAccessor & operator=(const BoolAttributeAccessor &rhs)
Copies a bool from another attribute.
BoolAttributeAccessor & operator=(const ConstBoolAttributeAccessor &rhs)
Copies a bool from another attribute.
BoolAttributeAccessor & operator=(bool x)
Assigns a bool to a BoolAttributeAccessor.
BoolAttributeAccessor(const BoolAttributeAccessor &rhs)
Copy-constructor.
ConstBoolAttributeAccessor(const Attribute< bool > &attribute, index_t index)
ConstBoolAttributeAccessor constructor.
Numeric::uint8 & element(index_t i)
Gets a modifiable element by index.
void fill(bool val)
Sets all the elements in this attribute to a specified value.
const Numeric::uint8 & element(index_t i) const
Gets an element by index.
void copy(const Attribute< bool > &rhs)
Copies all the values from another attribute.
Manages an attribute attached to a set of object.
Attribute(AttributesManager &manager, const std::string &name)
Creates or retrieves a persistent attribute attached to a given AttributesManager.
const T & operator[](index_t i) const
Gets an element by index.
Attribute()
Creates an uninitialized (unbound) Attribute.
T * data()
Gets the pointer to the data.
void fill(const T &val)
Sets all the elements in this attribute to a specified value.
const T * data() const
Gets the pointer to the data.
T & operator[](index_t i)
Gets a modifiable element by index.
void copy(const Attribute< T > &rhs)
Copies all the values from another attribute.
Manages a set of attributes attached to an object.
Definition attributes.h:947
void delete_attribute_store(AttributeStore *as)
Deletes an AttributeStore.
void compress(const vector< index_t > &old2new)
Compresses the stored attributes, by applying an index mapping that fills-in the gaps.
void zero_item(index_t to)
Sets an item to zero.
void copy(const AttributesManager &rhs)
Copies all the attributes from another AttributesManager.
bool get_doubles(const std::string &name, vector< double > &out, index_t &dim) const
Reads a double-typed attribute into a vector.
AttributesManager()
Constructs a new empty AttributesManager.
index_t nb() const
Gets the number of attributes.
Definition attributes.h:965
bool rename_attribute(const std::string &old_name, const std::string &new_name)
Renames an attribute.
void scale_item(index_t to, double s)
Scales an item.
const AttributeStore * find_attribute_store(const std::string &name) const
Finds an AttributeStore by name.
void apply_permutation(const vector< index_t > &permutation)
Applies a permutation to the stored attributes.
AttributeStore * find_attribute_store(const std::string &name)
Finds an AttributeStore by name.
void bind_attribute_store(const std::string &name, AttributeStore *as)
Binds an AttributeStore with the specified name. Ownership of this AttributeStore is transferred to t...
bool set_doubles(const std::string &name, const vector< double > &in, index_t dim)
Writes a double-typed attribute, creating it if needed.
void list_attribute_names(vector< std::string > &names) const
Gets the names of all the attributes in this AttributeStore.
~AttributesManager()
AttributesManager destructor.
void copy_item(index_t to, index_t from)
Copies all the attributes of an item into another one.
void madd_item(index_t to, double s, index_t from)
Adds a scaled item to another item \detais item[to] += s * item[from].
bool is_defined(const std::string &name) const
Tests whether an attribute is defined.
void swap_items(index_t i, index_t j)
Swaps all the attributes of two items.
index_t size() const
Gets the size.
Definition attributes.h:982
void clear(bool keep_attributes, bool keep_memory=false)
Clears this AttributesManager.
index_t capacity() const
Gets the capacity.
Definition attributes.h:991
void delete_attribute_store(const std::string &name)
Deletes an AttributeStore by name.
bool copy_attribute(const std::string &name, const std::string &new_name)
Copies an attribute.
void zero()
Zeroes all the attributes.
void reserve(index_t new_capacity)
Pre-allocates memory for a number of items.
void resize(index_t new_size)
Resizes all the attributes managed by this AttributesManager.
Base class for reference-counted objects.
Definition counted.h:71
Concrete implementation of LifeCycle.
Definition life_cycle.h:252
static void register_ascii_attribute_serializer(const std::string &type_name, AsciiAttributeReadSerializer read, AsciiAttributeWriteSerializer write)
Declares a new attribute type that can be read from and written to ascii files.
Manages the life cycle of an object.
Definition life_cycle.h:66
Readonly access to an attribute as a double regardless its type.
double operator[](index_t i)
Gets a property value.
Readwrite access to an attribute as a double regardless its type.
Accessor class used by ScalarAttributeAdapter to implement indexing operator.
Accessor class used by ScalarAttributeAdapter to implement indexing operator (const version).
Access to an attribute as a double regardless its type.
index_t element_index() const
Gets the element index.
T get_element(index_t i, index_t multiplier=1) const
Gets an element.
ElementType
Internal representation of the attribute.
static std::string attribute_base_name(const std::string &name)
Gets the base attribute name from a compound name.
void bind_if_is_defined(const AttributesManager &manager, const std::string &name)
Binds this Attribute to an AttributesManager if it already exists in the AttributesManager.
bool is_bound() const
Tests whether an Attribute is bound.
static index_t nb_scalar_elements_per_item(const AttributeStore *store)
Gets the number of scalar components per item in an AttributeStore.
double get_element_as_double(index_t i) const
Gets an attribute value.
~ScalarAttributeAdapterBase()
ReadonlyScalarAttributeAdapterBase destructor.
static ElementType element_type(const AttributeStore *store)
Gets the element type stored in an AttributeStore.
const AttributeStore * attribute_store() const
Gets the AttributeStore.
ScalarAttributeAdapterBase()
ScalarAttributeAdapterBase constructor.
static bool can_be_bound_to(const AttributeStore *store)
Tests whether a ScalarAttributeAdapterBase can be bound to a given attribute store.
void unbind()
Unbinds this Attribute.
static bool is_defined(const AttributesManager &manager, const std::string &name)
Tests whether an attribute with the specified name and with a type that can be converted to double ex...
ScalarAttributeAdapterBase(const AttributesManager &manager, const std::string &name)
ScalarAttributeAdapterBase constructor.
double set_element_as_double(index_t i, double value)
Sets an attribute value.
void set_element(T value, index_t i, index_t multiplier=1) const
Sets an element.
static index_t attribute_element_index(const std::string &name)
Gets the base attribute name from a compound name.
index_t size() const
Gets the size.
ElementType element_type() const
Gets the internal representation of the elements.
A smart pointer with reference-counted copy semantics.
Implementation of AttributeStoreCreator for a specific type.
Definition attributes.h:883
AttributeStore * create_attribute_store(index_t dim) override
Creates a new attribute store.
Definition attributes.h:888
bool elements_are_trivially_copyable() const override
Tests whether elements of this attribute can be trivially copyable.
Definition attributes.h:895
Stores an array of elements of a given type, and notifies a set of AttributeStoreObservers each time ...
Definition attributes.h:692
AttributeStore * clone() const override
Creates a new AttributeStore that is a carbon copy of this AttributeStore.
Definition attributes.h:780
void madd_item(index_t to, double s, index_t from) override
Adds a scaled item to another item \detais item[to] += s * item[from].
Definition attributes.h:800
void resize(index_t new_size) override
Resizes this AttributeStore.
Definition attributes.h:715
TypedAttributeStore(index_t dim=1, const std::type_info &user_type_info=typeid(ST))
Creates a new empty attribute store.
Definition attributes.h:704
void reserve(index_t new_capacity) override
Reserves memory.
Definition attributes.h:724
bool elements_type_matches(const std::string &type_name) const override
Tests whether this AttributeStore stores elements of a given type.
Definition attributes.h:765
void clear(bool keep_memory=false) override
Resizes this AttributeStore to 0.
Definition attributes.h:736
std::string user_element_typeid_name() const override
Gets the user typeid name of the element type stored in this AttributeStore.
Definition attributes.h:776
void notify(Memory::pointer base_addr, index_t size, index_t dim) override
If size or base address differ from the cached values, notify all the observers, and update the cache...
Definition attributes.h:811
std::string element_typeid_name() const override
Gets the typeid name of the element type stored in this AttributeStore.
Definition attributes.h:772
void redim(index_t dim) override
Sets the dimension.
Definition attributes.h:745
void scale_item(index_t to, double s) override
Scales an item.
Definition attributes.h:793
Helper class to register new attribute types.
Definition attributes.h:909
geo_register_attribute_type(const std::string &type_name)
geo_register_attribute_type constructor
Definition attributes.h:920
Vector with aligned memory allocation.
Definition memory.h:703
T * data()
Gets a pointer to the array of elements.
Definition memory.h:849
index_t size() const
Gets the number of elements.
Definition memory.h:749
Functions to read and write structured files.
Common include file, providing basic definitions. Should be included before anything else by all head...
Implementation of generic object lifecycle service.
Generic logging mechanism.
Types and functions for memory manipulation.
byte * pointer
Pointer to unsigned byte(s)
Definition memory.h:105
float float32
Definition numeric.h:151
uint8_t uint8
Definition numeric.h:139
int8_t int8
Definition numeric.h:127
double float64
Definition numeric.h:154
int32_t int32
Definition numeric.h:133
uint32_t uint32
Definition numeric.h:145
std::atomic_flag spinlock
A lightweight synchronization structure.
Global Vorpaline namespace.
Definition basic.h:55
void geo_argused(const T &)
Suppresses compiler warnings about unused parameters.
Definition argused.h:60
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:340
SmartPointer< AttributeStoreCreator > AttributeStoreCreator_var
An automatic reference-counted pointer to an AttributeStoreCreator.
Definition attributes.h:214
bool read_ascii_attribute< bool >(FILE *file, Memory::pointer base_addr, index_t nb_elements)
Reads an ASCII attribute from a file.
Definition geofile.h:208
bool write_ascii_attribute< bool >(FILE *file, Memory::const_pointer base_addr, index_t nb_elements)
Writes an ASCII attribute to a file.
Definition geofile.h:232
Types and functions for numbers manipulation.
Function and classes for process manipulation.