Loading...
Searching...
No Matches
piercedStorage.tpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25#ifndef __BITPIT_CONTAINERS_PIERCED_STORAGE_TPP__
26#define __BITPIT_CONTAINERS_PIERCED_STORAGE_TPP__
27
28namespace bitpit {
29
33template<typename id_t>
35 : m_kernel(nullptr), m_kernelType(KERNEL_NONE)
36{
37}
38
44template<typename id_t>
50
57template<typename id_t>
63
70template<typename id_t>
73{
74 KernelType kernelType = other.getKernelType();
75 switch (kernelType) {
76
77 case KERNEL_STATIC:
78 {
79 setStaticKernel(other.m_kernel);
80 break;
81 }
82
83 case KERNEL_DYNAMIC:
84 {
85 setDynamicKernel(other.m_kernel, other.getSyncMode());
86 break;
87 }
88
89 default:
90 {
91 break;
92 }
93
94 }
95}
96
97/**
98* Constructor.
99*
100* The newly created pierced sync slave will be associated with the given
101* static kernel.
103* \param other is another container of the same type (i.e., instantiated with
104* the same template parameters) whose content is copied in this container
105* \param kernel is the kernel that will be set
106*/
107template<typename id_t>
116/**
117* Constructor.
119* The newly created pierced sync slave will be associated with the given
120* dynamic kernel and will use the specified synchronization mode.
122* \param other is another container of the same type (i.e., instantiated with
123* the same template parameters) whose content is copied in this container
124* \param kernel is the kernel that will be set
125* \param syncMode is the synchronization mode that will be used for the storage
127template<typename id_t>
130{
131 BITPIT_UNUSED(other);
132
133 setDynamicKernel(kernel, syncMode);
134}
135
142template<typename id_t>
145{
146 // Set kernel
147 KernelType kernelType = other.getKernelType();
148 switch (kernelType) {
149
150 case KERNEL_STATIC:
151 {
152 setStaticKernel(other.m_kernel);
153 break;
154 }
155
156 case KERNEL_DYNAMIC:
157 {
158 setDynamicKernel(other.m_kernel, other.getSyncMode());
159 break;
160 }
161
162 default:
163 {
164 break;
165 }
166
167 }
168
169 // Unset kernel of other storage slave
170 other.unsetKernel(true);
171}
172
183template<typename id_t>
186{
187 // Set kernel
188 setStaticKernel(kernel);
189
190 // Unset kernel of other storage slave
191 other.unsetKernel(true);
192}
193
205template<typename id_t>
208{
209 // Set kernel
210 setDynamicKernel(kernel, syncMode);
211
212 // Unset kernel of other storage slave
213 other.unsetKernel(true);
214}
215
219template<typename id_t>
224
237template<typename id_t>
239{
240 // Set the kernel
241 if (!kernel) {
242 throw std::runtime_error("Unable to set the kernel. Provided kernel is not valid.");
243 } else if (m_kernelType != KERNEL_NONE) {
244 throw std::runtime_error("Unable to set the kernel. The kernel of the storage is already set.");
245 }
246
247 m_kernel = kernel;
248 m_kernelType = KERNEL_STATIC;
249
250 // Action to be performed after setting the kernel
252}
253
259template<typename id_t>
261{
262 // Nothing to do
263}
264
277template<typename id_t>
279{
280 // Set the static kernel
281 setStaticKernel(kernel);
282
283 // Update kernel type
284 m_kernelType = KERNEL_DYNAMIC;
285
286 // Register the storage for dynamic synchronization
287 m_kernel->registerSlave(this, syncMode);
288
289 // Action to be performed after setting the kernel
291}
292
296template<typename id_t>
298{
299 // Nothing to do
300}
301
309template<typename id_t>
311{
312 // Detach the kernel
313 detachKernel();
314
315 // Action to be performed after unsetting the kernel
316 _postUnsetKernel(release);
317}
318
326template<typename id_t>
328{
329 BITPIT_UNUSED(release);
330
331 // Nothing to do
332}
333
337template<typename id_t>
339{
340 if (m_kernelType == KERNEL_NONE) {
341 return;
342 }
343
344 if (m_kernelType == KERNEL_DYNAMIC) {
345 if (m_kernel->isSlaveRegistered(this)) {
346 m_kernel->unregisterSlave(this);
350 m_kernel = nullptr;
351 m_kernelType = KERNEL_NONE;
355* Gets a constant reference to the kernel of the storage
357* \result A constant reference to the kernel of the storage.
358*/
359template<typename id_t>
361{
362 return m_kernel;
364
366* Get the type of kernel set for the storage.
368* \return The type of kernel set for the storage.
370template<typename id_t>
371typename PiercedStorageSyncSlave<id_t>::KernelType PiercedStorageSyncSlave<id_t>::getKernelType() const
373 return m_kernelType;
374}
375
376/**
377* Gets the syncronization mode of the storage.
378*
379* \result The synchronization mode of the storage.
381template<typename id_t>
384 if (getKernelType() == KERNEL_NONE || getKernelType() == KERNEL_STATIC) {
385 return PiercedKernel<id_t>::SYNC_MODE_DISABLED;
386 } else {
387 return m_kernel->getSlaveSyncMode(this);
390
391/**
392* Exchanges the content of the storage by the content of x, which is another
393* storage object of the same type. Sizes may differ but the number of fields
394* has to be the same.
395*
396* After the call to this member function, the elements in this storage are
397* those which were in x before the call, and the elements of x are those
398* which were in this. All iterators, references and pointers remain valid
399* for the swapped objects.
401* \param other is another storage of the same type (i.e., instantiated with the
402* same template parameters) whose content is swapped with that of this
403* storage.
405template<typename id_t>
407{
409 std::swap(other.m_kernel, m_kernel);
410 std::swap(other.m_kernelType, m_kernelType);
411}
413/**
414* Constructor.
416template<typename value_t, typename id_t>
418 : PiercedStorageSyncSlave<id_t>(), m_nFields(1)
421
422/**
423* Constructor.
425* \param nFields is the number of fields in the storage
427template<typename value_t, typename id_t>
429 : PiercedStorageSyncSlave<id_t>(), m_nFields(nFields)
430{
432
434* Constructor.
435*
436* \param nFields is the number of fields in the storage
437* \param kernel is the kernel that will be set
439template<typename value_t, typename id_t>
441 : PiercedStorageSyncSlave<id_t>(kernel), m_nFields(nFields)
442{
443 // Base class constructor cannot call virtual functions
445}
450* \param nFields is the number of fields in the storage
451* \param kernel is the kernel that will be set
452* \param syncMode is the synchronization mode that will be used for the storage
454template<typename value_t, typename id_t>
456 : PiercedStorageSyncSlave<id_t>(kernel, syncMode), m_nFields(nFields)
457{
458 // Base class constructor cannot call virtual functions
462
464* Constructor.
465*
466* \param other is another container of the same type (i.e., instantiated with
467* the same template parameters) whose content is copied in this container
469template<typename value_t, typename id_t>
472 m_nFields(other.m_nFields), m_fields(other.m_fields)
474 // Base class constructor cannot call virtual functions
475 if (this->getKernel()) {
478 KernelType kernelType = this->getKernelType();
479 if (kernelType == this->KERNEL_DYNAMIC) {
481 }
482 }
483}
484
495template<typename value_t, typename id_t>
497 : PiercedStorageSyncSlave<id_t>(other, kernel),
498 m_nFields(other.m_nFields), m_fields(other.m_fields)
499{
500 // Base class constructor cannot call virtual functions
501 if (this->getKernel()) {
503 }
504}
505
517template<typename value_t, typename id_t>
519 : PiercedStorageSyncSlave<id_t>(other, kernel, syncMode),
520 m_nFields(other.m_nFields), m_fields(other.m_fields)
521{
522 // Base class constructor cannot call virtual functions
523 if (this->getKernel()) {
525
527 }
528}
529
543template<typename value_t, typename id_t>
545 : PiercedStorageSyncSlave<long>(other),
546 m_nFields(std::move(other.m_nFields)), m_fields(std::move(other.m_fields))
547{
548 // Base class constructor cannot call virtual functions
549 if (this->getKernel()) {
551
552 KernelType kernelType = this->getKernelType();
553 if (kernelType == this->KERNEL_DYNAMIC) {
555 }
556 }
557
558 // Explicitly reset the number of fields of the other storage
559 other.m_nFields = 0;
560}
561
579template<typename value_t, typename id_t>
581 : PiercedStorageSyncSlave<long>(other, kernel),
582 m_nFields(std::move(other.m_nFields)), m_fields(std::move(other.m_fields))
583{
584 // Base class constructor cannot call virtual functions
585 if (this->getKernel()) {
587 }
588
589 // Explicitly reset the number of fields of the other storage
590 other.m_nFields = 0;
591}
592
611template<typename value_t, typename id_t>
613 : PiercedStorageSyncSlave<long>(other, kernel, syncMode),
614 m_nFields(std::move(other.m_nFields)), m_fields(std::move(other.m_fields))
615{
616 // Base class constructor cannot call virtual functions
617 if (this->getKernel()) {
619
621 }
622
623 // Explicitly reset the number of fields of the other storage
624 other.m_nFields = 0;
625}
626
634template<typename value_t, typename id_t>
636{
637 PiercedStorage<value_t, id_t> temporary(other, nullptr);
638 temporary.swap(*this);
639
640 return *this;
641}
642
650template<typename value_t, typename id_t>
652{
653 PiercedStorage<value_t, id_t> temporary(std::move(other));
654 temporary.swap(*this);
655
656 return *this;
657}
658
664template<typename value_t, typename id_t>
666{
667 return m_nFields;
668}
669
670
679template<typename value_t, typename id_t>
681{
682 // Resize the storage
683 rawResize(this->m_kernel->rawSize());
685}
686
692template<typename value_t, typename id_t>
694{
695 // Nothing to do
696}
697
705template<typename value_t, typename id_t>
707{
708 // Clear the storage
709 rawClear(release);
710}
711
722template<typename value_t, typename id_t>
724{
725 return (m_fields.size() / m_nFields);
726}
727
736template<typename value_t, typename id_t>
738{
739 switch (action.type) {
740
741 case PiercedSyncAction::TYPE_CLEAR:
742 {
743 rawClear(true);
744 break;
745 }
746
747 case PiercedSyncAction::TYPE_RESERVE:
748 {
749 rawReserve(action.info[PiercedSyncAction::INFO_SIZE]);
750 break;
751 }
752
753 case PiercedSyncAction::TYPE_RESIZE:
754 {
755 rawResize(action.info[PiercedSyncAction::INFO_SIZE]);
756 break;
757 }
758
759 case PiercedSyncAction::TYPE_SHRINK_TO_FIT:
760 {
762 break;
763 }
764
765 case PiercedSyncAction::TYPE_REORDER:
766 {
767 if (action.data && action.data->size() > 0) {
768 rawReorder(*action.data);
769 }
770 rawResize(action.info[PiercedSyncAction::INFO_SIZE]);
772 break;
773 }
774
775 case PiercedSyncAction::TYPE_APPEND:
776 {
777 // Since we may increase the sotrage by an element at the time calling
778 // a reserve will hurt performance badly because this will prevent the
779 // automatic reallocation of the storage.
781 break;
782 }
783
784 case PiercedSyncAction::TYPE_INSERT:
785 {
786 // Since we may increase the sotrage by an element at the time calling
787 // a reserve will hurt performance badly because this will prevent the
788 // automatic reallocation of the storage.
789 rawEmplace(action.info[PiercedSyncAction::INFO_POS]);
790 break;
791 }
792
793 case PiercedSyncAction::TYPE_OVERWRITE:
794 case PiercedSyncAction::TYPE_OVERWRITE_MULTIPLE:
795 {
796 break;
797 }
798
799 case PiercedSyncAction::TYPE_MOVE_APPEND:
800 {
801 // Since we may increase the sotrage by an element at the time calling
802 // a reserve will hurt performance badly because this will prevent the
803 // automatic reallocation of the storage.
804 rawPushBack(std::move(rawAt(action.info[PiercedSyncAction::INFO_POS_FIRST])));
805 rawEmreplace(action.info[PiercedSyncAction::INFO_POS_FIRST]);
806 break;
807 }
808
809 case PiercedSyncAction::TYPE_MOVE_INSERT:
810 {
811 // Since we may increase the sotrage by an element at the time calling
812 // a reserve will hurt performance badly because this will prevent the
813 // automatic reallocation of the storage.
814 rawInsert(action.info[PiercedSyncAction::INFO_POS_SECOND], 1, std::move(rawAt(action.info[PiercedSyncAction::INFO_POS_FIRST])));
815 rawEmreplace(action.info[PiercedSyncAction::INFO_POS_FIRST]);
816 break;
817 }
818
819 case PiercedSyncAction::TYPE_MOVE_OVERWRITE:
820 {
821 rawSet(action.info[PiercedSyncAction::INFO_POS_SECOND], std::move(rawAt(action.info[PiercedSyncAction::INFO_POS_FIRST])));
822 rawEmreplace(action.info[PiercedSyncAction::INFO_POS_FIRST]);
823 break;
824 }
825
826 case PiercedSyncAction::TYPE_PIERCE:
827 case PiercedSyncAction::TYPE_PIERCE_MULTIPLE:
828 {
829 // Nothing to do. To improve performance the element will not be
830 // cleared.
831 break;
832 }
833
834 case PiercedSyncAction::TYPE_SWAP:
835 {
836 rawSwap(action.info[PiercedSyncAction::INFO_POS_FIRST], action.info[PiercedSyncAction::INFO_POS_SECOND]);
837 break;
838 }
839
840 case PiercedSyncAction::TYPE_NOOP:
841 {
842 break;
843 }
844
845 default:
846 {
847 throw std::runtime_error("Undefined synchronization action.");
848 }
849
850 }
851}
852
859template<typename value_t, typename id_t>
861{
862 m_fields.reserve(m_nFields * n);
863}
864
874template<typename value_t, typename id_t>
876{
877 m_fields.shrink_to_fit();
878}
879
887template<typename value_t, typename id_t>
889{
890 if (release) {
891 std::vector<value_t>().swap(m_fields);
892 } else {
893 m_fields.clear();
894 }
895}
896
903template<typename value_t, typename id_t>
904void PiercedStorage<value_t, id_t>::rawErase(std::size_t pos, std::size_t n)
905{
906 auto itr_begin = m_fields.begin() + pos * m_nFields;
907 auto itr_end = itr_begin + n * m_nFields;
908
909 m_fields.erase(itr_begin, itr_end);
910}
911
921template<typename value_t, typename id_t>
922template<typename T, typename std::enable_if<!std::is_same<T, bool>::value>::type *>
923void PiercedStorage<value_t, id_t>::rawSwap(std::size_t pos_first, std::size_t pos_second)
924{
925 std::size_t firstOffset = pos_first * m_nFields;
926 std::size_t secondOffset = pos_second * m_nFields;
927 for (std::size_t k = 0; k < m_nFields; ++k) {
928 std::swap(m_fields[firstOffset + k], m_fields[secondOffset + k]);
929 }
930}
931
940template<typename value_t, typename id_t>
941template<typename T, typename std::enable_if<std::is_same<T, bool>::value>::type *>
942void PiercedStorage<value_t, id_t>::rawSwap(std::size_t pos_first, std::size_t pos_second)
943{
944 std::size_t firstOffset = pos_first * m_nFields;
945 std::size_t secondOffset = pos_second * m_nFields;
946 for (std::size_t k = 0; k < m_nFields; ++k) {
947 // We cannot use std::swap because it will not work for bool storages
948 //
949 // The [] operator of std::vector<bool> returns a temporary object of a
950 // proxy type called std::vector<bool>::reference, rather than an actual
951 // bool&.
952 //
953 // Although the libstdc++ defines an overload for swapping this type of
954 // proxy objects, this is just an extension to the standard.
955 auto temp = m_fields[firstOffset + k];
956 m_fields[firstOffset + k] = m_fields[secondOffset + k];
957 m_fields[secondOffset + k] = temp;
958 }
959}
960
966template<typename value_t, typename id_t>
967void PiercedStorage<value_t, id_t>::rawReorder(const std::vector<std::size_t> &permutations)
968{
969 std::size_t storageRawSize = rawSize();
970 assert(permutations.size() == storageRawSize);
971
972 // Evaluate the permutation of the fields
973 std::vector<std::size_t> fieldPermutations(storageRawSize * m_nFields);
974 for (std::size_t pos = 0; pos < storageRawSize; ++pos) {
975 std::size_t posOffset = pos * m_nFields;
976 std::size_t permutationOffset = permutations[pos] * m_nFields;
977 for (std::size_t k = 0; k < m_nFields; ++k) {
978 fieldPermutations[posOffset + k] = permutationOffset + k;
979 }
980 }
981
982 // Sort the fields
983 utils::reorderVector<value_t>(fieldPermutations, m_fields, storageRawSize * m_nFields);
984}
985
993template<typename value_t, typename id_t>
994void PiercedStorage<value_t, id_t>::rawResize(std::size_t n, const value_t &value)
995{
996 m_fields.resize(m_nFields * n, value);
997}
998
1005template<typename value_t, typename id_t>
1006template<typename... Args, typename PiercedStorage<value_t>::template EnableIfHasInitialize<Args...> * >
1007void PiercedStorage<value_t, id_t>::rawInitialize(std::size_t pos, Args&&... args)
1008{
1009 if (m_nFields == 0) {
1010 return;
1011 }
1012
1013 rawInitialize(pos, 0, std::forward<Args>(args)...);
1014 for (std::size_t k = 1; k < m_nFields; ++k) {
1015 rawAt(pos, k) = rawAt(pos, k - 1);
1016 }
1017}
1018
1026template<typename value_t, typename id_t>
1027template<typename... Args, typename PiercedStorage<value_t>::template EnableIfHasInitialize<Args...> * >
1028void PiercedStorage<value_t, id_t>::rawInitialize(std::size_t pos, std::size_t k, Args&&... args)
1029{
1030 rawAt(pos, k).initialize(std::forward<Args>(args)...);
1031}
1032
1040template<typename value_t, typename id_t>
1041void PiercedStorage<value_t, id_t>::rawInsert(std::size_t pos, std::size_t n, const value_t &value)
1042{
1043 m_fields.insert(m_fields.begin() + pos * m_nFields, n * m_nFields, value);
1044}
1045
1051template<typename value_t, typename id_t>
1053{
1054 for (std::size_t k = 0; k < m_nFields; ++k) {
1055 m_fields.push_back(value);
1056 }
1057}
1058
1066template<typename value_t, typename id_t>
1067template<typename T, typename std::enable_if<!std::is_same<T, bool>::value>::type *, typename... Args>
1068void PiercedStorage<value_t, id_t>::rawEmplace(std::size_t pos, Args&&... args)
1069{
1070 if (m_nFields == 0) {
1071 return;
1072 }
1073
1074 m_fields.emplace(m_fields.begin() + pos * m_nFields, std::forward<Args>(args)...);
1075 for (std::size_t k = 1; k < m_nFields; ++k) {
1076 m_fields.emplace(m_fields.begin() + pos * m_nFields + k, value_t(rawAt(pos, k - 1)));
1077 }
1078}
1079
1087template<typename value_t, typename id_t>
1088template<typename T, typename std::enable_if<std::is_same<T, bool>::value>::type *>
1089void PiercedStorage<value_t, id_t>::rawEmplace(std::size_t pos, bool value)
1090{
1091 rawInsert(pos, 1, value);
1092}
1093
1101template<typename value_t, typename id_t>
1102template<typename T, typename std::enable_if<!std::is_same<T, bool>::value>::type *, typename... Args>
1104{
1105 if (m_nFields == 0) {
1106 return;
1107 }
1108
1109 m_fields.emplace_back(std::forward<Args>(args)...);
1110 for (std::size_t k = 1; k < m_nFields; ++k) {
1111 m_fields.emplace_back(value_t(m_fields.back()));
1112 }
1113}
1114
1122template<typename value_t, typename id_t>
1123template<typename T, typename std::enable_if<std::is_same<T, bool>::value>::type *>
1125{
1126 rawPushBack(value);
1127}
1128
1137template<typename value_t, typename id_t>
1138template<typename... Args>
1139void PiercedStorage<value_t, id_t>::rawEmreplace(std::size_t pos, Args&&... args)
1140{
1141 if (m_nFields == 0) {
1142 return;
1143 }
1144
1145 rawAt(pos, 0) = value_t(std::forward<Args>(args)...);
1146 for (std::size_t k = 1; k < m_nFields; ++k) {
1147 rawAt(pos, k) = rawAt(pos, k - 1);
1148 }
1149}
1150
1165template<typename value_t, typename id_t>
1167{
1168 // It is only possible to swap two storages with the same number of field.
1169 // If this condition is not fulfilled we can not continue. However, we
1170 // cannot throw an exception because the function is declared snoexcept.
1171 if (other.getFieldCount() != getFieldCount()) {
1172 std::cout << "It is only possible to swap storages with the same number of fields." << std::endl;
1173 assert(false);
1174 exit(EXIT_FAILURE);
1175 }
1176
1178 std::swap(other.m_nFields, m_nFields);
1179 std::swap(other.m_fields, m_fields);
1180}
1181
1187template<typename value_t, typename id_t>
1188void PiercedStorage<value_t, id_t>::fill(const value_t &value)
1189{
1190 std::fill(m_fields.begin(), m_fields.end(), value);
1191}
1192
1200template<typename value_t, typename id_t>
1201__PS_CONST_POINTER__ PiercedStorage<value_t, id_t>::data() const
1202{
1203 return m_fields.data();
1204}
1205
1213template<typename value_t, typename id_t>
1215{
1216 return m_fields.data();
1217}
1218
1226template<typename value_t, typename id_t>
1227__PS_POINTER__ PiercedStorage<value_t, id_t>::data(id_t id, std::size_t offset)
1228{
1229 std::size_t pos = this->m_kernel->getPos(id);
1230
1231 return rawData(pos, offset);
1232}
1233
1241template<typename value_t, typename id_t>
1242__PS_CONST_POINTER__ PiercedStorage<value_t, id_t>::data(id_t id, std::size_t offset) const
1243{
1244 std::size_t pos = this->m_kernel->getPos(id);
1245
1246 return rawData(pos, offset);
1247}
1248
1258template<typename value_t, typename id_t>
1259__PS_POINTER__ PiercedStorage<value_t, id_t>::rawData(std::size_t pos, std::size_t offset)
1260{
1261 return (data() + pos * m_nFields + offset);
1262}
1263
1273template<typename value_t, typename id_t>
1274__PS_CONST_POINTER__ PiercedStorage<value_t, id_t>::rawData(std::size_t pos, std::size_t offset) const
1275{
1276 return (data() + pos * m_nFields + offset);
1277}
1278
1287template<typename value_t, typename id_t>
1288__PS_REFERENCE__ PiercedStorage<value_t, id_t>::front(std::size_t k)
1289{
1290 if (this->m_kernel->empty()) {
1291 throw std::out_of_range("Vector is empty");
1292 }
1293
1294 return rawAt(this->m_kernel->front(), k);
1295}
1296
1305template<typename value_t, typename id_t>
1306__PS_CONST_REFERENCE__ PiercedStorage<value_t, id_t>::front(std::size_t k) const
1307{
1308 if (this->m_kernel->empty()) {
1309 throw std::out_of_range("Vector is empty");
1310 }
1311
1312 return rawAt(this->m_kernel->front(), k);
1313}
1314
1323template<typename value_t, typename id_t>
1324__PS_REFERENCE__ PiercedStorage<value_t, id_t>::back(std::size_t k)
1325{
1326 if (this->m_kernel->empty()) {
1327 throw std::out_of_range("Vector is empty");
1328 }
1329
1330 return rawAt(this->m_kernel->back(), k);
1331}
1332
1341template<typename value_t, typename id_t>
1342__PS_CONST_REFERENCE__ PiercedStorage<value_t, id_t>::back(std::size_t k) const
1343{
1344 if (this->m_kernel->empty()) {
1345 throw std::out_of_range("Vector is empty");
1346 }
1347
1348 return rawAt(this->m_kernel->back(), k);
1349}
1350
1351
1359template<typename value_t, typename id_t>
1360__PS_REFERENCE__ PiercedStorage<value_t, id_t>::at(id_t id, std::size_t k)
1361{
1362 std::size_t pos = this->m_kernel->getPos(id);
1363
1364 return rawAt(pos, k);
1365}
1366
1374template<typename value_t, typename id_t>
1375__PS_CONST_REFERENCE__ PiercedStorage<value_t, id_t>::at(id_t id, std::size_t k) const
1376{
1377 std::size_t pos = this->m_kernel->getPos(id);
1378
1379 return rawAt(pos, k);
1380}
1381
1388template<typename value_t, typename id_t>
1390{
1391 return at(id, 0);
1392}
1393
1400template<typename value_t, typename id_t>
1401__PS_CONST_REFERENCE__ PiercedStorage<value_t, id_t>::operator[](id_t id) const
1402{
1403 return at(id, 0);
1404}
1405
1412template<typename value_t, typename id_t>
1413void PiercedStorage<value_t, id_t>::copy(id_t id, value_t *values) const
1414{
1415 std::size_t pos = this->m_kernel->getPos(id);
1416
1417 rawCopy(pos, getFieldCount(), 0, values);
1418}
1419
1428template<typename value_t, typename id_t>
1429void PiercedStorage<value_t, id_t>::copy(id_t id, std::size_t nFields, std::size_t offset, value_t *values) const
1430{
1431 std::size_t pos = this->m_kernel->getPos(id);
1432
1433 rawCopy(pos, nFields, offset, values);
1434}
1435
1442template<typename value_t, typename id_t>
1443void PiercedStorage<value_t, id_t>::set(id_t id, const value_t &value)
1444{
1445 for (std::size_t k = 0; k < m_nFields; ++k) {
1446 set(id, k, value);
1447 }
1448}
1449
1457template<typename value_t, typename id_t>
1458void PiercedStorage<value_t, id_t>::set(id_t id, std::size_t k, const value_t &value)
1459{
1460 std::size_t pos = this->m_kernel->getPos(id);
1461
1462 rawSet(pos, k, value);
1463}
1464
1471template<typename value_t, typename id_t>
1472void PiercedStorage<value_t, id_t>::set(id_t id, const value_t *values)
1473{
1474 std::size_t pos = this->m_kernel->getPos(id);
1475
1476 rawSet(pos, getFieldCount(), 0, values);
1477}
1478
1487template<typename value_t, typename id_t>
1488void PiercedStorage<value_t, id_t>::set(id_t id, std::size_t nFields, std::size_t offset, const value_t *values)
1489{
1490 std::size_t pos = this->m_kernel->getPos(id);
1491
1492 rawSet(pos, nFields, offset, values);
1493}
1494
1504template<typename value_t, typename id_t>
1505__PS_REFERENCE__ PiercedStorage<value_t, id_t>::rawAt(std::size_t pos, std::size_t k)
1506{
1507 return m_fields[pos * m_nFields + k];
1508}
1509
1519template<typename value_t, typename id_t>
1520__PS_CONST_REFERENCE__ PiercedStorage<value_t, id_t>::rawAt(std::size_t pos, std::size_t k) const
1521{
1522 return m_fields[pos * m_nFields + k];
1523}
1524
1531template<typename value_t, typename id_t>
1532void PiercedStorage<value_t, id_t>::rawCopy(std::size_t pos, value_t *values) const
1533{
1534 rawCopy(pos, getFieldCount(), 0, values);
1535}
1536
1545template<typename value_t, typename id_t>
1546void PiercedStorage<value_t, id_t>::rawCopy(std::size_t pos, std::size_t nFields, std::size_t offset, value_t *values) const
1547{
1548 nFields = std::max(nFields, getFieldCount() - offset);
1549 for (std::size_t k = offset; k < (offset + nFields); ++k) {
1550 values[k] = m_fields[pos * m_nFields + k];
1551 }
1552}
1553
1560template<typename value_t, typename id_t>
1561void PiercedStorage<value_t, id_t>::rawSet(std::size_t pos, const value_t &value)
1562{
1563 for (std::size_t k = 0; k < m_nFields; ++k) {
1564 rawSet(pos, k, value);
1565 }
1566}
1567
1575template<typename value_t, typename id_t>
1576void PiercedStorage<value_t, id_t>::rawSet(std::size_t pos, std::size_t k, const value_t &value)
1577{
1578 m_fields[pos * m_nFields + k] = value;
1579}
1580
1587template<typename value_t, typename id_t>
1588void PiercedStorage<value_t, id_t>::rawSet(std::size_t pos, const value_t *values)
1589{
1590 rawSet(pos, getFieldCount(), 0, values);
1591}
1592
1601template<typename value_t, typename id_t>
1602void PiercedStorage<value_t, id_t>::rawSet(std::size_t pos, std::size_t nFields, std::size_t offset, const value_t *values)
1603{
1604 nFields = std::max(nFields, getFieldCount() - offset);
1605 for (std::size_t k = offset; k < (offset + nFields); ++k) {
1606 m_fields[pos * m_nFields + k] = values[k];
1607 }
1608}
1609
1616template<typename value_t, typename id_t>
1618{
1619 typename PiercedKernel<id_t>::const_iterator iterator = this->m_kernel->find(id);
1620
1621 return rawFind(iterator.getPos());
1622}
1623
1630template<typename value_t, typename id_t>
1632{
1633 typename PiercedKernel<id_t>::const_iterator iterator = this->m_kernel->find(id);
1634
1635 return rawFind(iterator.getPos());
1636}
1637
1644template<typename value_t, typename id_t>
1646{
1647 return iterator(this, pos);
1648}
1649
1656template<typename value_t, typename id_t>
1658{
1659 return const_iterator(this, pos);
1660}
1661
1667template<typename value_t, typename id_t>
1669{
1670 return rawFind(this->m_kernel->m_begin_pos);
1671}
1672
1678template<typename value_t, typename id_t>
1680{
1681 return rawFind(this->m_kernel->m_end_pos);
1682}
1683
1689template<typename value_t, typename id_t>
1694
1702template<typename value_t, typename id_t>
1707
1713template<typename value_t, typename id_t>
1715{
1716 return rawFind(this->m_kernel->m_begin_pos);
1717}
1718
1725template<typename value_t, typename id_t>
1727{
1728 return rawFind(this->m_kernel->m_end_pos);
1729}
1730
1736template<typename value_t, typename id_t>
1741
1749template<typename value_t, typename id_t>
1751{
1752 return m_fields.end();
1753}
1754
1762template<typename value_t, typename id_t>
1767
1775template<typename value_t, typename id_t>
1780
1786template<typename value_t, typename id_t>
1791
1799template<typename value_t, typename id_t>
1801{
1802 return m_fields.cend();
1803}
1804
1810template<typename value_t, typename id_t>
1811template<typename T, typename std::enable_if<std::is_pod<T>::value || PiercedStorage<T, id_t>::has_restore()>::type *>
1813{
1814 // Size
1815 std::size_t nElements;
1816 utils::binary::read(stream, nElements);
1817 rawResize(nElements);
1818
1819 // Fill the storage
1820 for (typename container_t::reference value : m_fields) {
1821 restoreField(stream, value);
1822 }
1823}
1824
1831template<typename value_t, typename id_t>
1832void PiercedStorage<value_t, id_t>::restoreField(std::istream &stream, std::vector<bool>::reference value)
1833{
1834 bool bool_value;
1835 utils::binary::read(stream, bool_value);
1836 value = bool_value;
1837}
1838
1845template<typename value_t, typename id_t>
1846template<typename T, typename std::enable_if<!PiercedStorage<T, id_t>::has_restore()>::type *>
1847void PiercedStorage<value_t, id_t>::restoreField(std::istream &stream, value_t &value)
1848{
1849 utils::binary::read(stream, value);
1850}
1851
1852
1859template<typename value_t, typename id_t>
1860template<typename T, typename std::enable_if<PiercedStorage<T, id_t>::has_restore()>::type *>
1861void PiercedStorage<value_t, id_t>::restoreField(std::istream &stream, value_t &object)
1862{
1863 object.restore(stream);
1864}
1865
1871template<typename value_t, typename id_t>
1872template<typename T, typename std::enable_if<std::is_pod<T>::value || PiercedStorage<T, id_t>::has_dump()>::type *>
1873void PiercedStorage<value_t, id_t>::dump(std::ostream &stream) const
1874{
1875 // Size
1876 utils::binary::write(stream, rawSize());
1877
1878 // Fileds
1879 for (typename container_t::const_reference value : m_fields) {
1880 dumpField(stream, value);
1881 }
1882}
1883
1890template<typename value_t, typename id_t>
1891void PiercedStorage<value_t, id_t>::dumpField(std::ostream &stream, std::vector<bool>::const_reference value) const
1892{
1893 bool bool_value = value;
1894 utils::binary::write(stream, bool_value);
1895}
1896
1903template<typename value_t, typename id_t>
1904template<typename T, typename std::enable_if<!PiercedStorage<T, id_t>::has_dump()>::type *>
1905void PiercedStorage<value_t, id_t>::dumpField(std::ostream &stream, const value_t &value) const
1906{
1907 utils::binary::write(stream, value);
1908}
1909
1916template<typename value_t, typename id_t>
1917template<typename T, typename std::enable_if<PiercedStorage<T, id_t>::has_dump()>::type *>
1918void PiercedStorage<value_t, id_t>::dumpField(std::ostream &stream, const value_t &object) const
1919{
1920 object.dump(stream);
1921}
1922
1923}
1924
1925#endif
Metafunction for generating a pierced kernel.
PiercedKernelIterator< id_t > const_iterator
void setStaticKernel(const PiercedKernel< id_t > *kernel)
const PiercedKernel< id_t > * getKernel() const
PiercedSyncMaster::SyncMode getSyncMode() const
void swap(PiercedStorageSyncSlave< id_t > &other) noexcept
virtual void _postUnsetKernel(bool release=true)
void setDynamicKernel(const PiercedKernel< id_t > *kernel, PiercedSyncMaster::SyncMode syncMode)
void unsetKernel(bool release=true)
Metafunction for generating a pierced storage.
raw_iterator rawBegin() noexcept
raw_iterator rawEnd() noexcept
void restore(std::istream &stream)
std::vector< value_t >::const_iterator raw_const_iterator
const_iterator cend() const noexcept
std::vector< value_t >::iterator raw_iterator
void copy(id_t id, value_t *values) const
void rawClear(bool release)
std::size_t getFieldCount() const
void rawReserve(std::size_t n)
PiercedStorageIterator< value_t, id_t > iterator
void set(id_t id, const value_t &value)
void rawInitialize(std::size_t pos, Args &&... args)
void swap(PiercedStorage &other) noexcept
__PS_REFERENCE__ at(id_t id, std::size_t k=0)
void commitSyncAction(const PiercedSyncAction &action) override
void rawSwap(std::size_t pos_first, std::size_t pos_second)
std::size_t rawSize() const
__PS_REFERENCE__ rawAt(std::size_t pos, std::size_t offset=0)
iterator end() noexcept
static constexpr bool has_dump()
void rawPushBack(const value_t &value)
iterator rawFind(std::size_t pos) noexcept
void rawEmreplace(std::size_t pos, Args &&... args)
void rawCopy(std::size_t pos, value_t *values) const
void rawErase(std::size_t pos, std::size_t n)
__PS_POINTER__ rawData(std::size_t pos, std::size_t offset=0)
void fill(const value_t &value)
iterator find(const id_t &id) noexcept
static constexpr bool has_restore()
iterator begin() noexcept
void _postSetStaticKernel() override
void _postUnsetKernel(bool release=true) override
raw_const_iterator rawCbegin() const noexcept
void rawEmplaceBack(Args &&... args)
void dump(std::ostream &stream) const
void rawEmplace(std::size_t pos, Args &&... args)
const_iterator cbegin() const noexcept
PiercedStorageIterator< const value_t, id_t > const_iterator
void rawInsert(std::size_t pos, std::size_t n, const value_t &value)
void rawReorder(const std::vector< std::size_t > &permutations)
PiercedStorage & operator=(const PiercedStorage &other)
__PS_REFERENCE__ front(std::size_t k=0)
raw_const_iterator rawCend() const noexcept
void rawSet(std::size_t pos, const value_t &value)
void rawResize(std::size_t n, const value_t &value=value_t())
__PS_REFERENCE__ back(std::size_t k=0)
__PS_REFERENCE__ operator[](id_t id)
PiercedStorageSyncSlave< PS_id_t >::KernelType KernelType
Action for pierced synchronization.
void swap(PiercedSyncSlave &other) noexcept
void write(std::ostream &stream, const std::vector< bool > &container)
void read(std::istream &stream, std::vector< bool > &container)
#define BITPIT_UNUSED(variable)
Definition compiler.hpp:63
void reorderVector(std::vector< size_t > &order, std::vector< T > &v, std::size_t size)