PMDK C++ bindings  1.11.1
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-2020, Intel Corporation */
3 
9 #ifndef LIBPMEMOBJ_CPP_ARRAY_HPP
10 #define LIBPMEMOBJ_CPP_ARRAY_HPP
11 
12 #include <algorithm>
13 #include <functional>
14 
18 #include <libpmemobj++/pext.hpp>
19 #include <libpmemobj++/slice.hpp>
21 #include <libpmemobj++/utils.hpp>
22 #include <libpmemobj/base.h>
23 
24 namespace pmem
25 {
26 
27 namespace obj
28 {
29 
45 template <typename T, std::size_t N>
46 struct array {
47 
48  template <typename Y, std::size_t M>
49  struct standard_array_traits {
50  using type = Y[N];
51  };
52 
53  /* zero-sized array support */
54  template <typename Y>
55  struct standard_array_traits<Y, 0> {
56  struct _alignment_struct {
57  Y _data[1];
58  };
59 
60  struct alignas(_alignment_struct) type {
61  char _data[sizeof(_alignment_struct)];
62  };
63  };
64 
65  /* Member types */
66  using value_type = T;
67  using pointer = value_type *;
68  using const_pointer = const value_type *;
69  using reference = value_type &;
70  using const_reference = const value_type &;
72  using const_iterator = const_pointer;
73  using size_type = std::size_t;
74  using difference_type = std::ptrdiff_t;
75  using reverse_iterator = std::reverse_iterator<iterator>;
76  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
79 
80  /* Underlying array */
81  typename standard_array_traits<T, N>::type _data;
82 
86  array() = default;
87 
91  array(const array &) = default;
92 
99  array(array &&) = default;
100 
111  array &
112  operator=(const array &other)
113  {
114  /*
115  * _get_pool should be called before self assignment check to
116  * maintain the same behaviour for all arguments.
117  */
118  auto pop = _get_pool();
119 
120  if (this == &other)
121  return *this;
122 
123  transaction::run(pop, [&] {
124  detail::conditional_add_to_tx(
125  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
126  std::copy(other.cbegin(), other.cend(), _get_data());
127  });
128 
129  return *this;
130  }
131 
142  array &
143  operator=(array &&other)
144  {
145  /*
146  * _get_pool should be called before self assignment check to
147  * maintain the same behaviour for all arguments.
148  */
149  auto pop = _get_pool();
150 
151  if (this == &other)
152  return *this;
153 
154  transaction::run(pop, [&] {
155  detail::conditional_add_to_tx(
156  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
157  detail::conditional_add_to_tx(
158  &other, 1, POBJ_XADD_ASSUME_INITIALIZED);
159  std::move(other._get_data(), other._get_data() + size(),
160  _get_data());
161  });
162 
163  return *this;
164  }
165 
173  reference
174  at(size_type n)
175  {
176  if (n >= N)
177  throw std::out_of_range("array::at");
178 
179  detail::conditional_add_to_tx(_get_data() + n, 1,
180  POBJ_XADD_ASSUME_INITIALIZED);
181 
182  return _get_data()[n];
183  }
184 
190  const_reference
191  at(size_type n) const
192  {
193  if (n >= N)
194  throw std::out_of_range("array::at");
195 
196  return _get_data()[n];
197  }
198 
204  const_reference
205  const_at(size_type n) const
206  {
207  if (n >= N)
208  throw std::out_of_range("array::const_at");
209 
210  return _get_data()[n];
211  }
212 
220  reference operator[](size_type n)
221  {
222  detail::conditional_add_to_tx(_get_data() + n, 1,
223  POBJ_XADD_ASSUME_INITIALIZED);
224 
225  return _get_data()[n];
226  }
227 
232  const_reference operator[](size_type n) const
233  {
234  return _get_data()[n];
235  }
236 
244  T *
246  {
247  detail::conditional_add_to_tx(this, 1,
248  POBJ_XADD_ASSUME_INITIALIZED);
249  return _get_data();
250  }
251 
255  const T *
256  data() const noexcept
257  {
258  return _get_data();
259  }
260 
264  const T *
265  cdata() const noexcept
266  {
267  return _get_data();
268  }
269 
276  iterator
278  {
279  return iterator(_get_data());
280  }
281 
288  iterator
289  end()
290  {
291  return iterator(_get_data() + size());
292  }
293 
297  const_iterator
298  begin() const noexcept
299  {
300  return const_iterator(_get_data());
301  }
302 
306  const_iterator
307  cbegin() const noexcept
308  {
309  return const_iterator(_get_data());
310  }
311 
315  const_iterator
316  end() const noexcept
317  {
318  return const_iterator(_get_data() + size());
319  }
320 
324  const_iterator
325  cend() const noexcept
326  {
327  return const_iterator(_get_data() + size());
328  }
329 
336  reverse_iterator
338  {
339  return reverse_iterator(iterator(_get_data() + size()));
340  }
341 
348  reverse_iterator
350  {
351  return reverse_iterator(iterator(_get_data()));
352  }
353 
357  const_reverse_iterator
358  rbegin() const noexcept
359  {
360  return const_reverse_iterator(cend());
361  }
362 
366  const_reverse_iterator
367  crbegin() const noexcept
368  {
369  return const_reverse_iterator(cend());
370  }
371 
375  const_reverse_iterator
376  rend() const noexcept
377  {
378  return const_reverse_iterator(cbegin());
379  }
380 
384  const_reverse_iterator
385  crend() const noexcept
386  {
387  return const_reverse_iterator(cbegin());
388  }
389 
396  reference
398  {
399  detail::conditional_add_to_tx(_get_data(), 1,
400  POBJ_XADD_ASSUME_INITIALIZED);
401  return _get_data()[0];
402  }
403 
410  reference
412  {
413  detail::conditional_add_to_tx(&_get_data()[size() - 1], 1,
414  POBJ_XADD_ASSUME_INITIALIZED);
415  return _get_data()[size() - 1];
416  }
417 
421  const_reference
422  front() const
423  {
424  return _get_data()[0];
425  }
426 
430  const_reference
431  cfront() const
432  {
433  return _get_data()[0];
434  }
435 
439  const_reference
440  back() const
441  {
442  return _get_data()[size() - 1];
443  }
444 
448  const_reference
449  cback() const
450  {
451  return _get_data()[size() - 1];
452  }
453 
466  range(size_type start, size_type n)
467  {
468  if (start + n > N)
469  throw std::out_of_range("array::range");
470 
471  detail::conditional_add_to_tx(_get_data() + start, n,
472  POBJ_XADD_ASSUME_INITIALIZED);
473 
474  return {_get_data() + start, _get_data() + start + n};
475  }
476 
494  range(size_type start, size_type n, size_type snapshot_size)
495  {
496  if (start + n > N)
497  throw std::out_of_range("array::range");
498 
499  if (snapshot_size > n)
500  snapshot_size = n;
501 
502  return {range_snapshotting_iterator(_get_data() + start,
503  _get_data() + start, n,
504  snapshot_size),
506  _get_data() + start, n,
507  snapshot_size)};
508  }
509 
522  range(size_type start, size_type n) const
523  {
524  if (start + n > N)
525  throw std::out_of_range("array::range");
526 
527  return {const_iterator(_get_data() + start),
528  const_iterator(_get_data() + start + n)};
529  }
530 
543  crange(size_type start, size_type n) const
544  {
545  if (start + n > N)
546  throw std::out_of_range("array::crange");
547 
548  return {const_iterator(_get_data() + start),
549  const_iterator(_get_data() + start + n)};
550  }
551 
555  constexpr size_type
556  size() const noexcept
557  {
558  return N;
559  }
560 
564  constexpr size_type
565  max_size() const noexcept
566  {
567  return N;
568  }
569 
573  constexpr bool
574  empty() const noexcept
575  {
576  return size() == 0;
577  }
578 
586  void
587  fill(const_reference value)
588  {
589  auto pop = _get_pool();
590 
591  transaction::run(pop, [&] {
592  detail::conditional_add_to_tx(
593  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
594  std::fill(_get_data(), _get_data() + size(), value);
595  });
596  }
597 
605  template <std::size_t Size = N>
606  typename std::enable_if<Size != 0>::type
607  swap(array &other)
608  {
609  /*
610  * _get_pool should be called before self assignment check to
611  * maintain the same behaviour for all arguments.
612  */
613  auto pop = _get_pool();
614 
615  if (this == &other)
616  return;
617 
618  transaction::run(pop, [&] {
619  detail::conditional_add_to_tx(
620  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
621  detail::conditional_add_to_tx(
622  &other, 1, POBJ_XADD_ASSUME_INITIALIZED);
623 
624  std::swap_ranges(_get_data(), _get_data() + size(),
625  other._get_data());
626  });
627  }
628 
632  template <std::size_t Size = N>
633  typename std::enable_if<Size == 0>::type
634  swap(array &other)
635  {
636  static_assert(!std::is_const<T>::value,
637  "cannot swap zero-sized array of type 'const T'");
638  }
639 
640 private:
644  template <std::size_t Size = N>
645  typename std::enable_if<Size != 0, T *>::type
647  {
648  return this->_data;
649  }
650 
654  template <std::size_t Size = N>
655  typename std::enable_if<Size != 0, const T *>::type
656  _get_data() const
657  {
658  return this->_data;
659  }
660 
665  template <std::size_t Size = N>
666  typename std::enable_if<Size == 0, T *>::type
668  {
669  return reinterpret_cast<T *>(&this->_data);
670  }
671 
675  template <std::size_t Size = N>
676  typename std::enable_if<Size == 0, const T *>::type
677  _get_data() const
678  {
679  return reinterpret_cast<const T *>(&this->_data);
680  }
681 
687  pool_base
688  _get_pool() const
689  {
690  return pmem::obj::pool_by_vptr(this);
691  }
692 };
693 
697 template <typename T, std::size_t N>
698 inline bool
699 operator==(const array<T, N> &lhs, const array<T, N> &rhs)
700 {
701  return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
702 }
703 
707 template <typename T, std::size_t N>
708 inline bool
709 operator!=(const array<T, N> &lhs, const array<T, N> &rhs)
710 {
711  return !(lhs == rhs);
712 }
713 
717 template <typename T, std::size_t N>
718 inline bool
719 operator<(const array<T, N> &lhs, const array<T, N> &rhs)
720 {
721  return std::lexicographical_compare(lhs.cbegin(), lhs.cend(),
722  rhs.cbegin(), rhs.cend());
723 }
724 
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 rhs < lhs;
733 }
734 
738 template <typename T, std::size_t N>
739 inline bool
740 operator>=(const array<T, N> &lhs, const array<T, N> &rhs)
741 {
742  return !(lhs < rhs);
743 }
744 
748 template <typename T, std::size_t N>
749 inline bool
750 operator<=(const array<T, N> &lhs, const array<T, N> &rhs)
751 {
752  return !(lhs > rhs);
753 }
754 
758 template <typename T, std::size_t N>
759 typename pmem::obj::array<T, N>::const_iterator
761 {
762  return a.cbegin();
763 }
764 
768 template <typename T, std::size_t N>
769 typename pmem::obj::array<T, N>::const_iterator
771 {
772  return a.cend();
773 }
774 
778 template <typename T, std::size_t N>
779 typename pmem::obj::array<T, N>::const_reverse_iterator
781 {
782  return a.crbegin();
783 }
784 
788 template <typename T, std::size_t N>
789 typename pmem::obj::array<T, N>::const_reverse_iterator
791 {
792  return a.crend();
793 }
794 
798 template <typename T, std::size_t N>
801 {
802  return a.begin();
803 }
804 
808 template <typename T, std::size_t N>
809 typename pmem::obj::array<T, N>::const_iterator
811 {
812  return a.begin();
813 }
814 
818 template <typename T, std::size_t N>
821 {
822  return a.end();
823 }
824 
828 template <typename T, std::size_t N>
829 typename pmem::obj::array<T, N>::const_iterator
831 {
832  return a.end();
833 }
834 
838 template <typename T, std::size_t N>
839 typename pmem::obj::array<T, N>::reverse_iterator
841 {
842  return a.rbegin();
843 }
844 
848 template <typename T, std::size_t N>
849 typename pmem::obj::array<T, N>::const_reverse_iterator
851 {
852  return a.rbegin();
853 }
854 
858 template <typename T, std::size_t N>
859 typename pmem::obj::array<T, N>::reverse_iterator
861 {
862  return a.rend();
863 }
864 
868 template <typename T, std::size_t N>
869 typename pmem::obj::array<T, N>::const_reverse_iterator
871 {
872  return a.rend();
873 }
874 
878 template <typename T, size_t N>
879 inline void
881 {
882  lhs.swap(rhs);
883 }
884 
888 template <size_t I, typename T, size_t N>
889 T &
891 {
892  static_assert(I < N,
893  "Index out of bounds in std::get<> (pmem::obj::array)");
894  return a.at(I);
895 }
896 
900 template <size_t I, typename T, size_t N>
901 T &&
903 {
904  static_assert(I < N,
905  "Index out of bounds in std::get<> (pmem::obj::array)");
906  return std::move(a.at(I));
907 }
908 
912 template <size_t I, typename T, size_t N>
913 const T &
914 get(const pmem::obj::array<T, N> &a) noexcept
915 {
916  static_assert(I < N,
917  "Index out of bounds in std::get<> (pmem::obj::array)");
918  return a.at(I);
919 }
920 
924 template <size_t I, typename T, size_t N>
925 const T &&
926 get(const pmem::obj::array<T, N> &&a) noexcept
927 {
928  static_assert(I < N,
929  "Index out of bounds in std::get<> (pmem::obj::array)");
930  return std::move(a.at(I));
931 }
932 
933 } /* namespace obj */
934 
935 } /* namespace pmem */
936 
937 #endif /* LIBPMEMOBJ_CPP_ARRAY_HPP */
pmem::obj::array::rbegin
const_reverse_iterator rbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:358
pmem::obj::array::operator[]
const_reference operator[](size_type n) const
Access element at specific index.
Definition: array.hpp:232
pmem::obj::array::max_size
constexpr size_type max_size() const noexcept
Returns the maximum size of the array.
Definition: array.hpp:565
pmem::obj::array::back
const_reference back() const
Access the last element.
Definition: array.hpp:440
pmem::obj::array::range
slice< const_iterator > range(size_type start, size_type n) const
Returns const slice.
Definition: array.hpp:522
pmem::obj::array::operator[]
reference operator[](size_type n)
Access element at specific index and add it to a transaction.
Definition: array.hpp:220
pmem::obj::array::array
array(array &&)=default
Defaulted move constructor.
pmem::obj::array::back
reference back()
Access the last element and add this element to a transaction.
Definition: array.hpp:411
utils.hpp
Libpmemobj C++ utils.
pmem
Persistent memory namespace.
Definition: allocation_flag.hpp:15
pmem::obj::array::range
slice< range_snapshotting_iterator > range(size_type start, size_type n, size_type snapshot_size)
Returns slice.
Definition: array.hpp:494
pmem::obj::array::cdata
const T * cdata() const noexcept
Returns const raw pointer to the underlying data.
Definition: array.hpp:265
common.hpp
Commonly used functionality.
pmem::obj::array::cbegin
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:307
pmem::obj::operator>
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:730
pmem::obj::array::crbegin
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:367
pmem::obj::array::begin
const_iterator begin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:298
pmem::obj::array::_get_data
std::enable_if< Size==0, T * >::type _get_data()
Support for zero sized array.
Definition: array.hpp:667
pmem::obj::operator>=
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:740
pmem::obj::array::fill
void fill(const_reference value)
Fills array with specified value inside internal transaction.
Definition: array.hpp:587
pmem::obj::array::_get_pool
pool_base _get_pool() const
Check whether object is on pmem and return pool_base instance.
Definition: array.hpp:688
pmem::obj::operator==
bool operator==(standard_alloc_policy< T > const &, standard_alloc_policy< T2 > const &)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:420
pmem::obj::array::_get_data
std::enable_if< Size !=0, T * >::type _get_data()
Support for non-zero sized array.
Definition: array.hpp:646
pmem::obj::array::cend
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: array.hpp:325
pmem::obj::array::operator=
array & operator=(const array &other)
Copy assignment operator - perform assignment from other pmem::obj::array.
Definition: array.hpp:112
slice.hpp
Interface to access sequence of objects.
pmem::obj::transaction::run
static void run(pool_base &pool, std::function< void()> tx, Locks &... locks)
Execute a closure-like transaction and lock locks.
Definition: transaction.hpp:406
pmem::obj::array::at
const_reference at(size_type n) const
Access element at specific index.
Definition: array.hpp:191
pmem::obj::array::cfront
const_reference cfront() const
Access the first element.
Definition: array.hpp:431
pmem::detail::basic_contiguous_iterator
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:331
pmem::obj::operator!=
bool operator!=(const allocator< T, P, Tr > &lhs, const OtherAllocator &rhs)
Determines if memory from another allocator can be deallocated from this one.
Definition: allocator.hpp:536
pmem::obj::array::data
const T * data() const noexcept
Returns const raw pointer to the underlying data.
Definition: array.hpp:256
pmem::obj::array::swap
std::enable_if< Size !=0 >::type swap(array &other)
Swaps content with other array's content inside internal transaction.
Definition: array.hpp:607
contiguous_iterator.hpp
Iterators for contiguous persistent containers.
transaction.hpp
C++ pmemobj transactions.
pmem::obj::array::begin
iterator begin()
Returns an iterator to the beginning.
Definition: array.hpp:277
pmem::obj::array::data
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:245
pmem::obj::array::operator=
array & operator=(array &&other)
Move assignment operator - perform move assignment from other pmem::obj::array.
Definition: array.hpp:143
pmem::obj::array::front
const_reference front() const
Access the first element.
Definition: array.hpp:422
pmem::obj::operator<
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:719
pmem::obj::array::empty
constexpr bool empty() const noexcept
Checks whether array is empty.
Definition: array.hpp:574
pmem::obj::array::rbegin
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: array.hpp:337
pmem::obj::array::at
reference at(size_type n)
Access element at specific index and add it to a transaction.
Definition: array.hpp:174
pmem::obj::get
T & get(pmem::obj::array< T, N > &a)
Non-member get function.
Definition: array.hpp:890
pmem::obj::array::crend
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:385
pmem::obj::slice
pmem::obj::slice - provides interface to access sequence of objects.
Definition: slice.hpp:27
pmem::obj::array::const_at
const_reference const_at(size_type n) const
Access element at specific index.
Definition: array.hpp:205
pmem::obj::array::cback
const_reference cback() const
Access the last element.
Definition: array.hpp:449
pmem::obj::operator<=
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:750
pmem::obj::array::end
const_iterator end() const noexcept
Returns a const iterator to the end.
Definition: array.hpp:316
pmem::obj::array
pmem::obj::array - persistent container with std::array compatible interface.
Definition: array.hpp:46
pext.hpp
Convenience extensions for the resides on pmem property template.
pmem::obj::array::array
array()=default
Defaulted constructor.
pmem::obj::array::range
slice< pointer > range(size_type start, size_type n)
Returns slice and snapshots requested range.
Definition: array.hpp:466
pmem::detail::range_snapshotting_iterator
Non-const iterator which adds elements to a transaction in a bulk.
Definition: contiguous_iterator.hpp:192
pmem::obj::array::_get_data
std::enable_if< Size !=0, const T * >::type _get_data() const
Support for non-zero sized array.
Definition: array.hpp:656
pmem::obj::array::crange
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: array.hpp:543
pmem::obj::pool_by_vptr
pool_base pool_by_vptr(const T *that)
Retrieve pool handle for the given pointer.
Definition: utils.hpp:32
pmem::obj::array::_get_data
std::enable_if< Size==0, const T * >::type _get_data() const
Support for zero sized array.
Definition: array.hpp:677
pmem::obj::array::rend
const_reverse_iterator rend() const noexcept
Returns a const reverse iterator to the end.
Definition: array.hpp:376
pmem::obj::pool_base
The non-template pool base class.
Definition: pool.hpp:46
pmem::obj::array::rend
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: array.hpp:349
pmem::obj::array::array
array(const array &)=default
Defaulted copy constructor.
persistent_ptr.hpp
Persistent smart pointer.
pmem::obj::array::front
reference front()
Access the first element and add this element to a transaction.
Definition: array.hpp:397
pmem::obj::array::end
iterator end()
Returns an iterator to the end.
Definition: array.hpp:289
pmem::obj::array::swap
std::enable_if< Size==0 >::type swap(array &other)
Swap for zero-sized array.
Definition: array.hpp:634
pmem::obj::array::size
constexpr size_type size() const noexcept
Returns size of the array.
Definition: array.hpp:556