PMDK C++ bindings  1.10
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-2019, 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/base.h>
22 
23 namespace pmem
24 {
25 
26 namespace obj
27 {
28 
44 template <typename T, std::size_t N>
45 struct array {
46 
47  template <typename Y, std::size_t M>
48  struct standard_array_traits {
49  using type = Y[N];
50  };
51 
52  /* zero-sized array support */
53  template <typename Y>
54  struct standard_array_traits<Y, 0> {
55  struct _alignment_struct {
56  Y _data[1];
57  };
58 
59  struct alignas(_alignment_struct) type {
60  char _data[sizeof(_alignment_struct)];
61  };
62  };
63 
64  /* Member types */
65  using value_type = T;
66  using pointer = value_type *;
67  using const_pointer = const value_type *;
68  using reference = value_type &;
69  using const_reference = const value_type &;
71  using const_iterator = const_pointer;
72  using size_type = std::size_t;
73  using difference_type = std::ptrdiff_t;
74  using reverse_iterator = std::reverse_iterator<iterator>;
75  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
78 
79  /* Underlying array */
80  typename standard_array_traits<T, N>::type _data;
81 
85  array() = default;
86 
90  array(const array &) = default;
91 
98  array(array &&) = default;
99 
110  array &
111  operator=(const array &other)
112  {
113  /*
114  * _get_pool should be called before self assignment check to
115  * maintain the same behaviour for all arguments.
116  */
117  auto pop = _get_pool();
118 
119  if (this == &other)
120  return *this;
121 
122  transaction::run(pop, [&] {
123  detail::conditional_add_to_tx(
124  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
125  std::copy(other.cbegin(), other.cend(), _get_data());
126  });
127 
128  return *this;
129  }
130 
141  array &
142  operator=(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  transaction::run(pop, [&] {
154  detail::conditional_add_to_tx(
155  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
156  detail::conditional_add_to_tx(
157  &other, 1, POBJ_XADD_ASSUME_INITIALIZED);
158  std::move(other._get_data(), other._get_data() + size(),
159  _get_data());
160  });
161 
162  return *this;
163  }
164 
172  reference
173  at(size_type n)
174  {
175  if (n >= N)
176  throw std::out_of_range("array::at");
177 
178  detail::conditional_add_to_tx(_get_data() + n, 1,
179  POBJ_XADD_ASSUME_INITIALIZED);
180 
181  return _get_data()[n];
182  }
183 
189  const_reference
190  at(size_type n) const
191  {
192  if (n >= N)
193  throw std::out_of_range("array::at");
194 
195  return _get_data()[n];
196  }
197 
203  const_reference
204  const_at(size_type n) const
205  {
206  if (n >= N)
207  throw std::out_of_range("array::const_at");
208 
209  return _get_data()[n];
210  }
211 
219  reference operator[](size_type n)
220  {
221  detail::conditional_add_to_tx(_get_data() + n, 1,
222  POBJ_XADD_ASSUME_INITIALIZED);
223 
224  return _get_data()[n];
225  }
226 
231  const_reference operator[](size_type n) const
232  {
233  return _get_data()[n];
234  }
235 
243  T *
245  {
246  detail::conditional_add_to_tx(this, 1,
247  POBJ_XADD_ASSUME_INITIALIZED);
248  return _get_data();
249  }
250 
254  const T *
255  data() const noexcept
256  {
257  return _get_data();
258  }
259 
263  const T *
264  cdata() const noexcept
265  {
266  return _get_data();
267  }
268 
275  iterator
277  {
278  return iterator(_get_data());
279  }
280 
287  iterator
288  end()
289  {
290  return iterator(_get_data() + size());
291  }
292 
296  const_iterator
297  begin() const noexcept
298  {
299  return const_iterator(_get_data());
300  }
301 
305  const_iterator
306  cbegin() const noexcept
307  {
308  return const_iterator(_get_data());
309  }
310 
314  const_iterator
315  end() const noexcept
316  {
317  return const_iterator(_get_data() + size());
318  }
319 
323  const_iterator
324  cend() const noexcept
325  {
326  return const_iterator(_get_data() + size());
327  }
328 
335  reverse_iterator
337  {
338  return reverse_iterator(iterator(_get_data() + size()));
339  }
340 
347  reverse_iterator
349  {
350  return reverse_iterator(iterator(_get_data()));
351  }
352 
356  const_reverse_iterator
357  rbegin() const noexcept
358  {
359  return const_reverse_iterator(cend());
360  }
361 
365  const_reverse_iterator
366  crbegin() const noexcept
367  {
368  return const_reverse_iterator(cend());
369  }
370 
374  const_reverse_iterator
375  rend() const noexcept
376  {
377  return const_reverse_iterator(cbegin());
378  }
379 
383  const_reverse_iterator
384  crend() const noexcept
385  {
386  return const_reverse_iterator(cbegin());
387  }
388 
395  reference
397  {
398  detail::conditional_add_to_tx(_get_data(), 1,
399  POBJ_XADD_ASSUME_INITIALIZED);
400  return _get_data()[0];
401  }
402 
409  reference
411  {
412  detail::conditional_add_to_tx(&_get_data()[size() - 1], 1,
413  POBJ_XADD_ASSUME_INITIALIZED);
414  return _get_data()[size() - 1];
415  }
416 
420  const_reference
421  front() const
422  {
423  return _get_data()[0];
424  }
425 
429  const_reference
430  cfront() const
431  {
432  return _get_data()[0];
433  }
434 
438  const_reference
439  back() const
440  {
441  return _get_data()[size() - 1];
442  }
443 
447  const_reference
448  cback() const
449  {
450  return _get_data()[size() - 1];
451  }
452 
465  range(size_type start, size_type n)
466  {
467  if (start + n > N)
468  throw std::out_of_range("array::range");
469 
470  detail::conditional_add_to_tx(_get_data() + start, n,
471  POBJ_XADD_ASSUME_INITIALIZED);
472 
473  return {_get_data() + start, _get_data() + start + n};
474  }
475 
493  range(size_type start, size_type n, size_type snapshot_size)
494  {
495  if (start + n > N)
496  throw std::out_of_range("array::range");
497 
498  if (snapshot_size > n)
499  snapshot_size = n;
500 
501  return {range_snapshotting_iterator(_get_data() + start,
502  _get_data() + start, n,
503  snapshot_size),
505  _get_data() + start, n,
506  snapshot_size)};
507  }
508 
521  range(size_type start, size_type n) const
522  {
523  if (start + n > N)
524  throw std::out_of_range("array::range");
525 
526  return {const_iterator(_get_data() + start),
527  const_iterator(_get_data() + start + n)};
528  }
529 
542  crange(size_type start, size_type n) const
543  {
544  if (start + n > N)
545  throw std::out_of_range("array::crange");
546 
547  return {const_iterator(_get_data() + start),
548  const_iterator(_get_data() + start + n)};
549  }
550 
554  constexpr size_type
555  size() const noexcept
556  {
557  return N;
558  }
559 
563  constexpr size_type
564  max_size() const noexcept
565  {
566  return N;
567  }
568 
572  constexpr bool
573  empty() const noexcept
574  {
575  return size() == 0;
576  }
577 
585  void
586  fill(const_reference value)
587  {
588  auto pop = _get_pool();
589 
590  transaction::run(pop, [&] {
591  detail::conditional_add_to_tx(
592  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
593  std::fill(_get_data(), _get_data() + size(), value);
594  });
595  }
596 
604  template <std::size_t Size = N>
605  typename std::enable_if<Size != 0>::type
606  swap(array &other)
607  {
608  /*
609  * _get_pool should be called before self assignment check to
610  * maintain the same behaviour for all arguments.
611  */
612  auto pop = _get_pool();
613 
614  if (this == &other)
615  return;
616 
617  transaction::run(pop, [&] {
618  detail::conditional_add_to_tx(
619  this, 1, POBJ_XADD_ASSUME_INITIALIZED);
620  detail::conditional_add_to_tx(
621  &other, 1, POBJ_XADD_ASSUME_INITIALIZED);
622 
623  std::swap_ranges(_get_data(), _get_data() + size(),
624  other._get_data());
625  });
626  }
627 
631  template <std::size_t Size = N>
632  typename std::enable_if<Size == 0>::type
633  swap(array &other)
634  {
635  static_assert(!std::is_const<T>::value,
636  "cannot swap zero-sized array of type 'const T'");
637  }
638 
639 private:
643  template <std::size_t Size = N>
644  typename std::enable_if<Size != 0, T *>::type
646  {
647  return this->_data;
648  }
649 
653  template <std::size_t Size = N>
654  typename std::enable_if<Size != 0, const T *>::type
655  _get_data() const
656  {
657  return this->_data;
658  }
659 
664  template <std::size_t Size = N>
665  typename std::enable_if<Size == 0, T *>::type
667  {
668  return reinterpret_cast<T *>(&this->_data);
669  }
670 
674  template <std::size_t Size = N>
675  typename std::enable_if<Size == 0, const T *>::type
676  _get_data() const
677  {
678  return reinterpret_cast<const T *>(&this->_data);
679  }
680 
686  pool_base
687  _get_pool() const
688  {
689  auto pop = pmemobj_pool_by_ptr(this);
690  if (pop == nullptr)
691  throw pmem::pool_error(
692  "Object outside of pmemobj pool.");
693 
694  return pool_base(pop);
695  }
696 };
697 
701 template <typename T, std::size_t N>
702 inline bool
703 operator==(const array<T, N> &lhs, const array<T, N> &rhs)
704 {
705  return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
706 }
707 
711 template <typename T, std::size_t N>
712 inline bool
713 operator!=(const array<T, N> &lhs, const array<T, N> &rhs)
714 {
715  return !(lhs == rhs);
716 }
717 
721 template <typename T, std::size_t N>
722 inline bool
723 operator<(const array<T, N> &lhs, const array<T, N> &rhs)
724 {
725  return std::lexicographical_compare(lhs.cbegin(), lhs.cend(),
726  rhs.cbegin(), rhs.cend());
727 }
728 
732 template <typename T, std::size_t N>
733 inline bool
734 operator>(const array<T, N> &lhs, const array<T, N> &rhs)
735 {
736  return rhs < lhs;
737 }
738 
742 template <typename T, std::size_t N>
743 inline bool
744 operator>=(const array<T, N> &lhs, const array<T, N> &rhs)
745 {
746  return !(lhs < rhs);
747 }
748 
752 template <typename T, std::size_t N>
753 inline bool
754 operator<=(const array<T, N> &lhs, const array<T, N> &rhs)
755 {
756  return !(lhs > rhs);
757 }
758 
762 template <typename T, std::size_t N>
763 typename pmem::obj::array<T, N>::const_iterator
765 {
766  return a.cbegin();
767 }
768 
772 template <typename T, std::size_t N>
773 typename pmem::obj::array<T, N>::const_iterator
775 {
776  return a.cend();
777 }
778 
782 template <typename T, std::size_t N>
783 typename pmem::obj::array<T, N>::const_reverse_iterator
785 {
786  return a.crbegin();
787 }
788 
792 template <typename T, std::size_t N>
793 typename pmem::obj::array<T, N>::const_reverse_iterator
795 {
796  return a.crend();
797 }
798 
802 template <typename T, std::size_t N>
805 {
806  return a.begin();
807 }
808 
812 template <typename T, std::size_t N>
813 typename pmem::obj::array<T, N>::const_iterator
815 {
816  return a.begin();
817 }
818 
822 template <typename T, std::size_t N>
825 {
826  return a.end();
827 }
828 
832 template <typename T, std::size_t N>
833 typename pmem::obj::array<T, N>::const_iterator
835 {
836  return a.end();
837 }
838 
842 template <typename T, std::size_t N>
843 typename pmem::obj::array<T, N>::reverse_iterator
845 {
846  return a.rbegin();
847 }
848 
852 template <typename T, std::size_t N>
853 typename pmem::obj::array<T, N>::const_reverse_iterator
855 {
856  return a.rbegin();
857 }
858 
862 template <typename T, std::size_t N>
863 typename pmem::obj::array<T, N>::reverse_iterator
865 {
866  return a.rend();
867 }
868 
872 template <typename T, std::size_t N>
873 typename pmem::obj::array<T, N>::const_reverse_iterator
875 {
876  return a.rend();
877 }
878 
882 template <typename T, size_t N>
883 inline void
885 {
886  lhs.swap(rhs);
887 }
888 
892 template <size_t I, typename T, size_t N>
893 T &
895 {
896  static_assert(I < N,
897  "Index out of bounds in std::get<> (pmem::obj::array)");
898  return a.at(I);
899 }
900 
904 template <size_t I, typename T, size_t N>
905 T &&
907 {
908  static_assert(I < N,
909  "Index out of bounds in std::get<> (pmem::obj::array)");
910  return std::move(a.at(I));
911 }
912 
916 template <size_t I, typename T, size_t N>
917 const T &
918 get(const pmem::obj::array<T, N> &a) noexcept
919 {
920  static_assert(I < N,
921  "Index out of bounds in std::get<> (pmem::obj::array)");
922  return a.at(I);
923 }
924 
928 template <size_t I, typename T, size_t N>
929 const T &&
930 get(const pmem::obj::array<T, N> &&a) noexcept
931 {
932  static_assert(I < N,
933  "Index out of bounds in std::get<> (pmem::obj::array)");
934  return std::move(a.at(I));
935 }
936 
937 } /* namespace obj */
938 
939 } /* namespace pmem */
940 
941 #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:357
pmem::obj::array::operator[]
const_reference operator[](size_type n) const
Access element at specific index.
Definition: array.hpp:231
pmem::obj::array::max_size
constexpr size_type max_size() const noexcept
Returns the maximum size of the array.
Definition: array.hpp:564
pmem::obj::array::back
const_reference back() const
Access the last element.
Definition: array.hpp:439
pmem::obj::array::range
slice< const_iterator > range(size_type start, size_type n) const
Returns const slice.
Definition: array.hpp:521
pmem::obj::array::operator[]
reference operator[](size_type n)
Access element at specific index and add it to a transaction.
Definition: array.hpp:219
pmem::obj::array::array
array(array &&)=default
Defaulted move constructor.
pmem::pool_error
Custom pool error class.
Definition: pexceptions.hpp:45
pmem::obj::array::back
reference back()
Access the last element and add this element to a transaction.
Definition: array.hpp:410
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:493
pmem::obj::array::cdata
const T * cdata() const noexcept
Returns const raw pointer to the underlying data.
Definition: array.hpp:264
common.hpp
Commonly used functionality.
pmem::obj::array::cbegin
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:306
pmem::obj::operator>
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:734
pmem::obj::array::crbegin
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:366
pmem::obj::array::begin
const_iterator begin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:297
pmem::obj::array::_get_data
std::enable_if< Size==0, T * >::type _get_data()
Support for zero sized array.
Definition: array.hpp:666
pmem::obj::operator>=
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:744
pmem::obj::array::fill
void fill(const_reference value)
Fills array with specified value inside internal transaction.
Definition: array.hpp:586
pmem::obj::array::_get_pool
pool_base _get_pool() const
Check whether object is on pmem and return pool_base instance.
Definition: array.hpp:687
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:406
pmem::obj::array::_get_data
std::enable_if< Size !=0, T * >::type _get_data()
Support for non-zero sized array.
Definition: array.hpp:645
pmem::obj::array::cend
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: array.hpp:324
pmem::obj::array::operator=
array & operator=(const array &other)
Copy assignment operator - perform assignment from other pmem::obj::array.
Definition: array.hpp:111
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:393
pmem::obj::array::at
const_reference at(size_type n) const
Access element at specific index.
Definition: array.hpp:190
pmem::obj::array::cfront
const_reference cfront() const
Access the first element.
Definition: array.hpp:430
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:522
pmem::obj::array::data
const T * data() const noexcept
Returns const raw pointer to the underlying data.
Definition: array.hpp:255
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:606
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:276
pmem::obj::array::data
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:244
pmem::obj::array::operator=
array & operator=(array &&other)
Move assignment operator - perform move assignment from other pmem::obj::array.
Definition: array.hpp:142
pmem::obj::array::front
const_reference front() const
Access the first element.
Definition: array.hpp:421
pmem::obj::operator<
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less than operator.
Definition: array.hpp:723
pmem::obj::array::empty
constexpr bool empty() const noexcept
Checks whether array is empty.
Definition: array.hpp:573
pmem::obj::array::rbegin
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: array.hpp:336
pmem::obj::array::at
reference at(size_type n)
Access element at specific index and add it to a transaction.
Definition: array.hpp:173
pmem::obj::get
T & get(pmem::obj::array< T, N > &a)
Non-member get function.
Definition: array.hpp:894
pmem::obj::array::crend
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:384
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:204
pmem::obj::array::cback
const_reference cback() const
Access the last element.
Definition: array.hpp:448
pmem::obj::operator<=
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member less or equal operator.
Definition: array.hpp:754
pmem::obj::array::end
const_iterator end() const noexcept
Returns a const iterator to the end.
Definition: array.hpp:315
pmem::obj::array
pmem::obj::array - persistent container with std::array compatible interface.
Definition: array.hpp:45
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:465
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:655
pmem::obj::array::crange
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: array.hpp:542
pmem::obj::array::_get_data
std::enable_if< Size==0, const T * >::type _get_data() const
Support for zero sized array.
Definition: array.hpp:676
pmem::obj::array::rend
const_reverse_iterator rend() const noexcept
Returns a const reverse iterator to the end.
Definition: array.hpp:375
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:348
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:396
pmem::obj::array::end
iterator end()
Returns an iterator to the end.
Definition: array.hpp:288
pmem::obj::array::swap
std::enable_if< Size==0 >::type swap(array &other)
Swap for zero-sized array.
Definition: array.hpp:633
pmem::obj::array::size
constexpr size_type size() const noexcept
Returns size of the array.
Definition: array.hpp:555