PMDK C++ bindings  1.13.0-git107.g7e59f08f
This is the C++ bindings documentation for PMDK's libpmemobj.
array.hpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 /* Copyright 2018-2021, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_CPP_ARRAY_HPP
10 #define LIBPMEMOBJ_CPP_ARRAY_HPP
11 
12 #include <algorithm>
13 #include <functional>
14 #include <initializer_list>
15 
19 #include <libpmemobj++/pext.hpp>
20 #include <libpmemobj++/slice.hpp>
22 #include <libpmemobj++/utils.hpp>
23 #include <libpmemobj/base.h>
24 
25 namespace pmem
26 {
27 
28 namespace obj
29 {
30 
56 template <typename T, std::size_t N>
57 struct array {
58 
59  template <typename Y, std::size_t M>
60  struct standard_array_traits {
61  using type = Y[N];
62  };
63 
64  /* zero-sized array support */
65  template <typename Y>
66  struct standard_array_traits<Y, 0> {
67  struct _alignment_struct {
68  Y _data[1];
69  };
70 
71  struct alignas(_alignment_struct) type {
72  char _data[sizeof(_alignment_struct)];
73  };
74  };
75 
76  /* Member types */
77  using value_type = T;
78  using pointer = value_type *;
79  using const_pointer = const value_type *;
80  using reference = value_type &;
81  using const_reference = const value_type &;
83  using const_iterator = const_pointer;
84  using size_type = std::size_t;
85  using difference_type = std::ptrdiff_t;
86  using reverse_iterator = std::reverse_iterator<iterator>;
87  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
90 
91  /* Underlying array */
92  typename standard_array_traits<T, N>::type _data;
93 
97  array() = default;
98 
102  array(const array &) = default;
103 
110  array(array &&) = default;
111 
112 #if __cplusplus > 201703L
119  array(std::initializer_list<T> list)
120  {
121  if constexpr (N > 0) {
122  size_t i = 0;
123  for (auto &v : list) {
124  (*this)[i] = v;
125  i++;
126  }
127  }
128  }
129 #endif /* __cplusplus */
130 
141  array &
142  operator=(const array &other)
143  {
144  /*
145  * _get_pool should be called before self assignment check to
146  * maintain the same behaviour for all arguments.
147  */
148  auto pop = _get_pool();
149 
150  if (this == &other)
151  return *this;
152 
153  flat_transaction::run(pop, [&] {
155  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
156  std::copy(other.cbegin(), other.cend(), _get_data());
157  });
158 
159  return *this;
160  }
161 
172  array &
173  operator=(array &&other)
174  {
175  /*
176  * _get_pool should be called before self assignment check to
177  * maintain the same behaviour for all arguments.
178  */
179  auto pop = _get_pool();
180 
181  if (this == &other)
182  return *this;
183 
184  flat_transaction::run(pop, [&] {
186  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
188  &other, 1, POBJ_XADD_ASSUME_INITIALIZED);
189  std::move(other._get_data(), other._get_data() + size(),
190  _get_data());
191  });
192 
193  return *this;
194  }
195 
203  reference
204  at(size_type n)
205  {
206  if (n >= N)
207  throw std::out_of_range("array::at");
208 
209  detail::conditional_add_to_tx(_get_data() + n, 1,
210  POBJ_XADD_ASSUME_INITIALIZED);
211 
212  return _get_data()[n];
213  }
214 
220  const_reference
221  at(size_type n) const
222  {
223  if (n >= N)
224  throw std::out_of_range("array::at");
225 
226  return _get_data()[n];
227  }
228 
234  const_reference
235  const_at(size_type n) const
236  {
237  if (n >= N)
238  throw std::out_of_range("array::const_at");
239 
240  return _get_data()[n];
241  }
242 
250  reference operator[](size_type n)
251  {
252  detail::conditional_add_to_tx(_get_data() + n, 1,
253  POBJ_XADD_ASSUME_INITIALIZED);
254 
255  return _get_data()[n];
256  }
257 
262  const_reference operator[](size_type n) const
263  {
264  return _get_data()[n];
265  }
266 
274  T *
276  {
278  POBJ_XADD_ASSUME_INITIALIZED);
279  return _get_data();
280  }
281 
285  const T *
286  data() const noexcept
287  {
288  return _get_data();
289  }
290 
294  const T *
295  cdata() const noexcept
296  {
297  return _get_data();
298  }
299 
306  iterator
308  {
309  return iterator(_get_data());
310  }
311 
318  iterator
319  end()
320  {
321  return iterator(_get_data() + size());
322  }
323 
327  const_iterator
328  begin() const noexcept
329  {
330  return const_iterator(_get_data());
331  }
332 
336  const_iterator
337  cbegin() const noexcept
338  {
339  return const_iterator(_get_data());
340  }
341 
345  const_iterator
346  end() const noexcept
347  {
348  return const_iterator(_get_data() + size());
349  }
350 
354  const_iterator
355  cend() const noexcept
356  {
357  return const_iterator(_get_data() + size());
358  }
359 
366  reverse_iterator
368  {
369  return reverse_iterator(iterator(_get_data() + size()));
370  }
371 
378  reverse_iterator
380  {
381  return reverse_iterator(iterator(_get_data()));
382  }
383 
387  const_reverse_iterator
388  rbegin() const noexcept
389  {
390  return const_reverse_iterator(cend());
391  }
392 
396  const_reverse_iterator
397  crbegin() const noexcept
398  {
399  return const_reverse_iterator(cend());
400  }
401 
405  const_reverse_iterator
406  rend() const noexcept
407  {
408  return const_reverse_iterator(cbegin());
409  }
410 
414  const_reverse_iterator
415  crend() const noexcept
416  {
417  return const_reverse_iterator(cbegin());
418  }
419 
426  reference
428  {
429  detail::conditional_add_to_tx(_get_data(), 1,
430  POBJ_XADD_ASSUME_INITIALIZED);
431  return _get_data()[0];
432  }
433 
440  reference
442  {
443  detail::conditional_add_to_tx(&_get_data()[size() - 1], 1,
444  POBJ_XADD_ASSUME_INITIALIZED);
445  return _get_data()[size() - 1];
446  }
447 
451  const_reference
452  front() const
453  {
454  return _get_data()[0];
455  }
456 
460  const_reference
461  cfront() const
462  {
463  return _get_data()[0];
464  }
465 
469  const_reference
470  back() const
471  {
472  return _get_data()[size() - 1];
473  }
474 
478  const_reference
479  cback() const
480  {
481  return _get_data()[size() - 1];
482  }
483 
496  range(size_type start, size_type n)
497  {
498  if (start + n > N)
499  throw std::out_of_range("array::range");
500 
501  detail::conditional_add_to_tx(_get_data() + start, n,
502  POBJ_XADD_ASSUME_INITIALIZED);
503 
504  return {_get_data() + start, _get_data() + start + n};
505  }
506 
524  range(size_type start, size_type n, size_type snapshot_size)
525  {
526  if (start + n > N)
527  throw std::out_of_range("array::range");
528 
529  if (snapshot_size > n)
530  snapshot_size = n;
531 
532  return {range_snapshotting_iterator(_get_data() + start,
533  _get_data() + start, n,
534  snapshot_size),
535  range_snapshotting_iterator(_get_data() + start + n,
536  _get_data() + start, n,
537  snapshot_size)};
538  }
539 
552  range(size_type start, size_type n) const
553  {
554  if (start + n > N)
555  throw std::out_of_range("array::range");
556 
557  return {const_iterator(_get_data() + start),
558  const_iterator(_get_data() + start + n)};
559  }
560 
573  crange(size_type start, size_type n) const
574  {
575  if (start + n > N)
576  throw std::out_of_range("array::crange");
577 
578  return {const_iterator(_get_data() + start),
579  const_iterator(_get_data() + start + n)};
580  }
581 
585  constexpr size_type
586  size() const noexcept
587  {
588  return N;
589  }
590 
594  constexpr size_type
595  max_size() const noexcept
596  {
597  return N;
598  }
599 
603  constexpr bool
604  empty() const noexcept
605  {
606  return size() == 0;
607  }
608 
616  void
617  fill(const_reference value)
618  {
619  auto pop = _get_pool();
620 
621  flat_transaction::run(pop, [&] {
623  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
624  std::fill(_get_data(), _get_data() + size(), value);
625  });
626  }
627 
635  template <std::size_t Size = N>
636  typename std::enable_if<Size != 0>::type
637  swap(array &other)
638  {
639  /*
640  * _get_pool should be called before self assignment check to
641  * maintain the same behaviour for all arguments.
642  */
643  auto pop = _get_pool();
644 
645  if (this == &other)
646  return;
647 
648  flat_transaction::run(pop, [&] {
650  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
652  &other, 1, POBJ_XADD_ASSUME_INITIALIZED);
653 
654  std::swap_ranges(_get_data(), _get_data() + size(),
655  other._get_data());
656  });
657  }
658 
662  template <std::size_t Size = N>
663  typename std::enable_if<Size == 0>::type
664  swap(array &other)
665  {
666  static_assert(!std::is_const<T>::value,
667  "cannot swap zero-sized array of type 'const T'");
668  }
669 
670 private:
674  template <std::size_t Size = N>
675  typename std::enable_if<Size != 0, T *>::type
676  _get_data()
677  {
678  return this->_data;
679  }
680 
684  template <std::size_t Size = N>
685  typename std::enable_if<Size != 0, const T *>::type
686  _get_data() const
687  {
688  return this->_data;
689  }
690 
695  template <std::size_t Size = N>
696  typename std::enable_if<Size == 0, T *>::type
697  _get_data()
698  {
699  return reinterpret_cast<T *>(&this->_data);
700  }
701 
705  template <std::size_t Size = N>
706  typename std::enable_if<Size == 0, const T *>::type
707  _get_data() const
708  {
709  return reinterpret_cast<const T *>(&this->_data);
710  }
711 
717  pool_base
718  _get_pool() const
719  {
720  return pmem::obj::pool_by_vptr(this);
721  }
722 };
723 
728 template <typename T, std::size_t N>
729 inline bool
730 operator==(const array<T, N> &lhs, const array<T, N> &rhs)
731 {
732  return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
733 }
734 
739 template <typename T, std::size_t N>
740 inline bool
741 operator!=(const array<T, N> &lhs, const array<T, N> &rhs)
742 {
743  return !(lhs == rhs);
744 }
745 
750 template <typename T, std::size_t N>
751 inline bool
752 operator<(const array<T, N> &lhs, const array<T, N> &rhs)
753 {
754  return std::lexicographical_compare(lhs.cbegin(), lhs.cend(),
755  rhs.cbegin(), rhs.cend());
756 }
757 
762 template <typename T, std::size_t N>
763 inline bool
764 operator>(const array<T, N> &lhs, const array<T, N> &rhs)
765 {
766  return rhs < lhs;
767 }
768 
773 template <typename T, std::size_t N>
774 inline bool
775 operator>=(const array<T, N> &lhs, const array<T, N> &rhs)
776 {
777  return !(lhs < rhs);
778 }
779 
784 template <typename T, std::size_t N>
785 inline bool
786 operator<=(const array<T, N> &lhs, const array<T, N> &rhs)
787 {
788  return !(lhs > rhs);
789 }
790 
795 template <typename T, std::size_t N>
796 typename pmem::obj::array<T, N>::const_iterator
798 {
799  return a.cbegin();
800 }
801 
806 template <typename T, std::size_t N>
807 typename pmem::obj::array<T, N>::const_iterator
809 {
810  return a.cend();
811 }
812 
817 template <typename T, std::size_t N>
818 typename pmem::obj::array<T, N>::const_reverse_iterator
820 {
821  return a.crbegin();
822 }
823 
828 template <typename T, std::size_t N>
829 typename pmem::obj::array<T, N>::const_reverse_iterator
831 {
832  return a.crend();
833 }
834 
839 template <typename T, std::size_t N>
842 {
843  return a.begin();
844 }
845 
850 template <typename T, std::size_t N>
851 typename pmem::obj::array<T, N>::const_iterator
853 {
854  return a.begin();
855 }
856 
861 template <typename T, std::size_t N>
864 {
865  return a.end();
866 }
867 
872 template <typename T, std::size_t N>
873 typename pmem::obj::array<T, N>::const_iterator
875 {
876  return a.end();
877 }
878 
883 template <typename T, std::size_t N>
884 typename pmem::obj::array<T, N>::reverse_iterator
886 {
887  return a.rbegin();
888 }
889 
894 template <typename T, std::size_t N>
895 typename pmem::obj::array<T, N>::const_reverse_iterator
897 {
898  return a.rbegin();
899 }
900 
905 template <typename T, std::size_t N>
906 typename pmem::obj::array<T, N>::reverse_iterator
908 {
909  return a.rend();
910 }
911 
916 template <typename T, std::size_t N>
917 typename pmem::obj::array<T, N>::const_reverse_iterator
919 {
920  return a.rend();
921 }
922 
927 template <typename T, size_t N>
928 inline void
930 {
931  lhs.swap(rhs);
932 }
933 
938 template <size_t I, typename T, size_t N>
939 T &
941 {
942  static_assert(I < N,
943  "Index out of bounds in std::get<> (pmem::obj::array)");
944  return a.at(I);
945 }
946 
951 template <size_t I, typename T, size_t N>
952 T &&
954 {
955  static_assert(I < N,
956  "Index out of bounds in std::get<> (pmem::obj::array)");
957  return std::move(a.at(I));
958 }
959 
964 template <size_t I, typename T, size_t N>
965 const T &
966 get(const pmem::obj::array<T, N> &a) noexcept
967 {
968  static_assert(I < N,
969  "Index out of bounds in std::get<> (pmem::obj::array)");
970  return a.at(I);
971 }
972 
977 template <size_t I, typename T, size_t N>
978 const T &&
979 get(const pmem::obj::array<T, N> &&a) noexcept
980 {
981  static_assert(I < N,
982  "Index out of bounds in std::get<> (pmem::obj::array)");
983  return std::move(a.at(I));
984 }
985 
986 } /* namespace obj */
987 
988 } /* namespace pmem */
989 
990 #endif /* LIBPMEMOBJ_CPP_ARRAY_HPP */
static void run(obj::pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:810
Provides interface to access sequence of objects.
Definition: slice.hpp:61
Commonly used functionality.
Iterators for contiguous persistent containers.
void conditional_add_to_tx(const T *that, std::size_t count=1, uint64_t flags=0)
Conditionally add 'count' objects to a transaction.
Definition: common.hpp:176
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
Persistent memory namespace.
Definition: allocation_flag.hpp:15
Persistent smart pointer.
Convenience extensions for the resides on pmem property template.
Interface to access sequence of objects.
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:331
Non-const iterator which adds elements to a transaction in a bulk.
Definition: contiguous_iterator.hpp:192
Persistent container with std::array compatible interface.
Definition: array.hpp:57
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: array.hpp:367
reference at(size_type n)
Access element at specific index and add it to a transaction.
Definition: array.hpp:204
slice< range_snapshotting_iterator > range(size_type start, size_type n, size_type snapshot_size)
Returns slice.
Definition: array.hpp:524
constexpr size_type max_size() const noexcept
Returns the maximum size of the array.
Definition: array.hpp:595
pmem::obj::array< T, N >::reverse_iterator rbegin(pmem::obj::array< T, N > &a)
Non-member rbegin.
Definition: array.hpp:885
void fill(const_reference value)
Fills array with specified value inside internal transaction.
Definition: array.hpp:617
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: array.hpp:573
pmem::obj::array< T, N >::const_iterator end(const pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:874
const T & get(const pmem::obj::array< T, N > &a) noexcept
Non-member get function.
Definition: array.hpp:966
const_reference front() const
Access the first element.
Definition: array.hpp:452
iterator begin()
Returns an iterator to the beginning.
Definition: array.hpp:307
iterator end()
Returns an iterator to the end.
Definition: array.hpp:319
const_reference at(size_type n) const
Access element at specific index.
Definition: array.hpp:221
pmem::obj::array< T, N >::iterator begin(pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:841
array(array &&)=default
Defaulted move constructor.
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:415
const_iterator end() const noexcept
Returns a const iterator to the end.
Definition: array.hpp:346
pmem::obj::array< T, N >::iterator end(pmem::obj::array< T, N > &a)
Non-member end.
Definition: array.hpp:863
pmem::obj::array< T, N >::const_reverse_iterator crend(const pmem::obj::array< T, N > &a)
Non-member crend.
Definition: array.hpp:830
array & operator=(array &&other)
Move assignment operator - perform move assignment from other pmem::obj::array.
Definition: array.hpp:173
bool operator!=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member not-equal operator.
Definition: array.hpp:741
const_reverse_iterator rend() const noexcept
Returns a const reverse iterator to the end.
Definition: array.hpp:406
const T * data() const noexcept
Returns const raw pointer to the underlying data.
Definition: array.hpp:286
pmem::obj::array< T, N >::const_iterator cbegin(const pmem::obj::array< T, N > &a)
Non-member cbegin.
Definition: array.hpp:797
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:786
pmem::obj::array< T, N >::reverse_iterator rend(pmem::obj::array< T, N > &a)
Non-member rend.
Definition: array.hpp:907
void swap(pmem::obj::array< T, N > &lhs, pmem::obj::array< T, N > &rhs)
Non-member swap function.
Definition: array.hpp:929
pmem::obj::array< T, N >::const_iterator begin(const pmem::obj::array< T, N > &a)
Non-member begin.
Definition: array.hpp:852
array(const array &)=default
Defaulted copy constructor.
reference operator[](size_type n)
Access element at specific index and add it to a transaction.
Definition: array.hpp:250
pmem::obj::array< T, N >::const_reverse_iterator rbegin(const pmem::obj::array< T, N > &a)
Non-member rbegin.
Definition: array.hpp:896
const_reverse_iterator rbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:388
T & get(pmem::obj::array< T, N > &a)
Non-member get function.
Definition: array.hpp:940
bool operator==(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member equal operator.
Definition: array.hpp:730
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:275
array & operator=(const array &other)
Copy assignment operator - perform assignment from other pmem::obj::array.
Definition: array.hpp:142
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:397
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:764
slice< pointer > range(size_type start, size_type n)
Returns slice and snapshots requested range.
Definition: array.hpp:496
const_reference const_at(size_type n) const
Access element at specific index.
Definition: array.hpp:235
const_reference back() const
Access the last element.
Definition: array.hpp:470
std::enable_if< Size !=0 >::type swap(array &other)
Swaps content with other array's content inside internal transaction.
Definition: array.hpp:637
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:752
const_reference cback() const
Access the last element.
Definition: array.hpp:479
reference back()
Access the last element and add this element to a transaction.
Definition: array.hpp:441
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: array.hpp:355
const_reference cfront() const
Access the first element.
Definition: array.hpp:461
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:337
const T && get(const pmem::obj::array< T, N > &&a) noexcept
Non-member get function.
Definition: array.hpp:979
const_iterator begin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:328
reference front()
Access the first element and add this element to a transaction.
Definition: array.hpp:427
constexpr bool empty() const noexcept
Checks whether array is empty.
Definition: array.hpp:604
const T * cdata() const noexcept
Returns const raw pointer to the underlying data.
Definition: array.hpp:295
array()=default
Defaulted constructor.
pmem::obj::array< T, N >::const_reverse_iterator crbegin(const pmem::obj::array< T, N > &a)
Non-member crbegin.
Definition: array.hpp:819
constexpr size_type size() const noexcept
Returns size of the array.
Definition: array.hpp:586
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:775
const_reference operator[](size_type n) const
Access element at specific index.
Definition: array.hpp:262
pmem::obj::array< T, N >::const_reverse_iterator rend(const pmem::obj::array< T, N > &a)
Non-member rend.
Definition: array.hpp:918
pmem::obj::array< T, N >::const_iterator cend(const pmem::obj::array< T, N > &a)
Non-member cend.
Definition: array.hpp:808
T && get(pmem::obj::array< T, N > &&a)
Non-member get function.
Definition: array.hpp:953
std::enable_if< Size==0 >::type swap(array &other)
Swap for zero-sized array.
Definition: array.hpp:664
slice< const_iterator > range(size_type start, size_type n) const
Returns const slice.
Definition: array.hpp:552
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: array.hpp:379
C++ pmemobj transactions.
Libpmemobj C++ utils.