PMDK C++ bindings  1.2.0
This is the C++ bindings documentation for PMDK's libpmemobj.
array.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
38 #ifndef LIBPMEMOBJ_CPP_ARRAY_HPP
39 #define LIBPMEMOBJ_CPP_ARRAY_HPP
40 
41 #include <algorithm>
42 #include <functional>
43 
48 #include <libpmemobj++/pext.hpp>
49 #include <libpmemobj.h>
50 
51 namespace pmem
52 {
53 
54 namespace obj
55 {
56 
57 namespace experimental
58 {
59 
73 template <typename T, std::size_t N>
74 struct array {
75 
76  template <typename Y, std::size_t M>
77  struct standard_array_traits {
78  using type = Y[N];
79  };
80 
81  /* zero-sized array support */
82  template <typename Y>
83  struct standard_array_traits<Y, 0> {
84  struct _alignment_struct {
85  Y _data[1];
86  };
87 
88  struct alignas(_alignment_struct) type {
89  char _data[sizeof(_alignment_struct)];
90  };
91  };
92 
93  /* Member types */
94  using value_type = T;
95  using pointer = value_type *;
96  using const_pointer = const value_type *;
97  using reference = value_type &;
98  using const_reference = const value_type &;
101  using size_type = std::size_t;
102  using difference_type = std::ptrdiff_t;
103  using reverse_iterator = std::reverse_iterator<iterator>;
104  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
105 
106  /* Underlying array */
107  typename standard_array_traits<T, N>::type _data;
108 
112  array() = default;
113 
117  array(const array &) = default;
118 
122  array(array &&) = default;
123 
130  array &
131  operator=(const array &other)
132  {
133  detail::conditional_add_to_tx(this);
134 
135  std::copy(other.cbegin(), other.cend(), _get_data());
136  return *this;
137  }
138 
145  array &
146  operator=(array &&other)
147  {
148  detail::conditional_add_to_tx(this);
149 
150  std::copy(other.cbegin(), other.cend(), _get_data());
151  return *this;
152  }
153 
161  reference
162  at(size_type n)
163  {
164  if (n >= N)
165  throw std::out_of_range("array::at");
166 
167  detail::conditional_add_to_tx(_get_data() + n);
168 
169  return _get_data()[n];
170  }
171 
177  const_reference
178  at(size_type n) const
179  {
180  if (n >= N)
181  throw std::out_of_range("array::at");
182 
183  return _get_data()[n];
184  }
185 
193  reference operator[](size_type n)
194  {
195  detail::conditional_add_to_tx(_get_data() + n);
196 
197  return _get_data()[n];
198  }
199 
204  const_reference operator[](size_type n) const
205  {
206  return _get_data()[n];
207  }
208 
216  T *
218  {
219  detail::conditional_add_to_tx(this);
220  return _get_data();
221  }
222 
226  const T *
227  data() const noexcept
228  {
229  return _get_data();
230  }
231 
238  iterator
240  {
241  return iterator(_get_data());
242  }
243 
250  iterator
251  end()
252  {
253  return iterator(_get_data() + size());
254  }
255 
259  const_iterator
260  begin() const noexcept
261  {
262  return const_iterator(_get_data());
263  }
264 
268  const_iterator
269  cbegin() const noexcept
270  {
271  return const_iterator(_get_data());
272  }
273 
277  const_iterator
278  end() const noexcept
279  {
280  return const_iterator(_get_data() + size());
281  }
282 
286  const_iterator
287  cend() const noexcept
288  {
289  return const_iterator(_get_data() + size());
290  }
291 
298  reverse_iterator
300  {
301  return reverse_iterator(iterator(_get_data() + size()));
302  }
303 
310  reverse_iterator
312  {
313  return reverse_iterator(iterator(_get_data()));
314  }
315 
319  const_reverse_iterator
320  rbegin() const noexcept
321  {
322  return const_reverse_iterator(cend());
323  }
324 
328  const_reverse_iterator
329  crbegin() const noexcept
330  {
331  return const_reverse_iterator(cend());
332  }
333 
337  const_reverse_iterator
338  rend() const noexcept
339  {
340  return const_reverse_iterator(cbegin());
341  }
342 
346  const_reverse_iterator
347  crend() const noexcept
348  {
349  return const_reverse_iterator(cbegin());
350  }
351 
358  reference
360  {
361  detail::conditional_add_to_tx(_get_data());
362  return _get_data()[0];
363  }
364 
371  reference
373  {
374  detail::conditional_add_to_tx(&_get_data()[size() - 1]);
375  return _get_data()[size() - 1];
376  }
377 
381  const_reference
382  front() const
383  {
384  return _get_data()[0];
385  }
386 
390  const_reference
391  back() const
392  {
393  return _get_data()[size() - 1];
394  }
395 
413  range(size_type start, size_type n,
414  size_type snapshot_size = std::numeric_limits<size_type>::max())
415  {
416  if (start + n > N)
417  throw std::out_of_range("array::range");
418 
419  if (snapshot_size > n)
420  snapshot_size = n;
421 
422  return {range_snapshotting_iterator<T>(_get_data() + start,
423  _get_data(), N,
424  snapshot_size),
426  _get_data(), N,
427  snapshot_size)};
428  }
429 
442  range(size_type start, size_type n) const
443  {
444  if (start + n > N)
445  throw std::out_of_range("array::range");
446 
447  return {const_iterator(_get_data() + start),
448  const_iterator(_get_data() + start + n)};
449  }
450 
463  crange(size_type start, size_type n) const
464  {
465  if (start + n > N)
466  throw std::out_of_range("array::crange");
467 
468  return {const_iterator(_get_data() + start),
469  const_iterator(_get_data() + start + n)};
470  }
471 
475  constexpr size_type
476  size() const noexcept
477  {
478  return N;
479  }
480 
484  constexpr size_type
485  max_size() const noexcept
486  {
487  return N;
488  }
489 
493  constexpr bool
494  empty() const noexcept
495  {
496  return size() == 0;
497  }
498 
506  void
507  fill(const_reference value)
508  {
509  detail::conditional_add_to_tx(this);
510  std::fill(_get_data(), _get_data() + size(), value);
511  }
512 
520  template <std::size_t Size = N>
521  typename std::enable_if<Size != 0>::type
522  swap(array &other)
523  {
524  detail::conditional_add_to_tx(this);
525  detail::conditional_add_to_tx(&other);
526 
527  std::swap_ranges(_get_data(), _get_data() + size(),
528  other._get_data());
529  }
530 
534  template <std::size_t Size = N>
535  typename std::enable_if<Size == 0>::type
536  swap(array &other)
537  {
538  static_assert(!std::is_const<T>::value,
539  "cannot swap zero-sized array of type 'const T'");
540  }
541 
542 private:
546  template <std::size_t Size = N>
547  typename std::enable_if<Size != 0, T *>::type
549  {
550  return this->_data;
551  }
552 
556  template <std::size_t Size = N>
557  typename std::enable_if<Size != 0, const T *>::type
558  _get_data() const
559  {
560  return this->_data;
561  }
562 
567  template <std::size_t Size = N>
568  typename std::enable_if<Size == 0, T *>::type
570  {
571  return reinterpret_cast<T *>(&this->_data);
572  }
573 
577  template <std::size_t Size = N>
578  typename std::enable_if<Size == 0, const T *>::type
579  _get_data() const
580  {
581  return reinterpret_cast<const T *>(&this->_data);
582  }
583 };
584 
588 template <typename T, std::size_t N>
589 inline bool
590 operator==(const array<T, N> &lhs, const array<T, N> &rhs)
591 {
592  return std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());
593 }
594 
598 template <typename T, std::size_t N>
599 inline bool
600 operator!=(const array<T, N> &lhs, const array<T, N> &rhs)
601 {
602  return !(lhs == rhs);
603 }
604 
608 template <typename T, std::size_t N>
609 inline bool
610 operator<(const array<T, N> &lhs, const array<T, N> &rhs)
611 {
612  return std::lexicographical_compare(lhs.cbegin(), lhs.cend(),
613  rhs.cbegin(), rhs.cend());
614 }
615 
619 template <typename T, std::size_t N>
620 inline bool
621 operator>(const array<T, N> &lhs, const array<T, N> &rhs)
622 {
623  return rhs < lhs;
624 }
625 
629 template <typename T, std::size_t N>
630 inline bool
631 operator>=(const array<T, N> &lhs, const array<T, N> &rhs)
632 {
633  return !(lhs < rhs);
634 }
635 
639 template <typename T, std::size_t N>
640 inline bool
641 operator<=(const array<T, N> &lhs, const array<T, N> &rhs)
642 {
643  return !(lhs > rhs);
644 }
645 
649 template <typename T, std::size_t N>
652 {
653  return a.cbegin();
654 }
655 
659 template <typename T, std::size_t N>
662 {
663  return a.cend();
664 }
665 
669 template <typename T, std::size_t N>
670 typename pmem::obj::experimental::array<T, N>::const_reverse_iterator
672 {
673  return a.crbegin();
674 }
675 
679 template <typename T, std::size_t N>
680 typename pmem::obj::experimental::array<T, N>::const_reverse_iterator
682 {
683  return a.crend();
684 }
685 
689 template <typename T, std::size_t N>
692 {
693  return a.begin();
694 }
695 
699 template <typename T, std::size_t N>
702 {
703  return a.end();
704 }
705 
709 template <typename T, std::size_t N>
710 typename pmem::obj::experimental::array<T, N>::reverse_iterator
712 {
713  return a.rbegin();
714 }
715 
719 template <typename T, std::size_t N>
720 typename pmem::obj::experimental::array<T, N>::reverse_iterator
722 {
723  return a.rend();
724 }
725 
729 template <typename T, size_t N>
730 inline void
733 {
734  lhs.swap(rhs);
735 }
736 
740 template <size_t I, typename T, size_t N>
741 T &
743 {
744  static_assert(I < N,
745  "Index out of bounds in std::get<> (pmem::obj::array)");
746  return a.at(I);
747 }
748 
752 template <size_t I, typename T, size_t N>
753 T &&
755 {
756  static_assert(I < N,
757  "Index out of bounds in std::get<> (pmem::obj::array)");
758  return std::move(a.at(I));
759 }
760 
764 template <size_t I, typename T, size_t N>
765 const T &
767 {
768  static_assert(I < N,
769  "Index out of bounds in std::get<> (pmem::obj::array)");
770  return a.at(I);
771 }
772 
776 template <size_t I, typename T, size_t N>
777 const T &&
779 {
780  static_assert(I < N,
781  "Index out of bounds in std::get<> (pmem::obj::array)");
782  return std::move(a.at(I));
783 }
784 
785 } /* namespace experimental */
786 
787 } /* namespace obj */
788 
789 } /* namespace pmem */
790 
791 #endif /* LIBPMEMOBJ_CPP_ARRAY_HPP */
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:400
slice< const_iterator > range(size_type start, size_type n) const
Returns const slice.
Definition: array.hpp:442
Non-const iterator which adds elements to a transaction in a bulk.
Definition: contiguous_iterator.hpp:294
constexpr bool empty() const noexcept
Checks whether array is empty.
Definition: array.hpp:494
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater or equal operator.
Definition: array.hpp:631
std::enable_if< Size !=0 >::type swap(array &other)
Swaps content with other array&#39;s content.
Definition: array.hpp:522
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:329
Default non-const iterator which adds element to a transaction on every access.
Definition: contiguous_iterator.hpp:420
const_iterator cbegin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:269
slice< const_iterator > crange(size_type start, size_type n) const
Returns const slice.
Definition: array.hpp:463
void fill(const_reference value)
Adds entire array to a transaction and fills array with specified value.
Definition: array.hpp:507
iterator end()
Returns an iterator to the end.
Definition: array.hpp:251
const_iterator begin() const noexcept
Returns const iterator to the beginning.
Definition: array.hpp:260
array & operator=(const array &other)
Copy assignment operator - adds &#39;this&#39; to a transaction.
Definition: array.hpp:131
iterator begin()
Returns an iterator to the beginning.
Definition: array.hpp:239
std::enable_if< Size !=0, T * >::type _get_data()
Support for non-zero sized array.
Definition: array.hpp:548
reverse_iterator rend()
Returns a reverse iterator to the end.
Definition: array.hpp:311
reference back()
Access the last element and add this element to a transaction.
Definition: array.hpp:372
Convenience extensions for the resides on pmem property template.
const_reference back() const
Access the last element.
Definition: array.hpp:391
Commonly used functionality.
Iterators for pmem::obj::array.
pmem::obj::experimental::array - EXPERIMENTAL persistent container with std::array compatible interfa...
Definition: array.hpp:74
std::enable_if< Size !=0, const T * >::type _get_data() const
Support for non-zero sized array.
Definition: array.hpp:558
reference operator[](size_type n)
Access element at specific index and add it to a transaction.
Definition: array.hpp:193
T * data()
Returns raw pointer to the underlying data and adds entire array to a transaction.
Definition: array.hpp:217
constexpr size_type max_size() const noexcept
Returns the maximum size of the array.
Definition: array.hpp:485
array()=default
Defaulted constructor.
const_reverse_iterator rbegin() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:320
std::enable_if< Size==0, T * >::type _get_data()
Support for zero sized array.
Definition: array.hpp:569
pmem::obj::experimental::slice - provides interface to access sequence of objects.
Definition: slice.hpp:58
reverse_iterator rbegin()
Returns a reverse iterator to the beginning.
Definition: array.hpp:299
const_reverse_iterator rend() const noexcept
Returns a const reverse iterator to the end.
Definition: array.hpp:338
const_reference operator[](size_type n) const
Access element at specific index.
Definition: array.hpp:204
const_reference front() const
Access the first element.
Definition: array.hpp:382
const_iterator end() const noexcept
Returns a const iterator to the end.
Definition: array.hpp:278
const T * data() const noexcept
Returns const raw pointer to the underlying data.
Definition: array.hpp:227
const_iterator cend() const noexcept
Returns a const iterator to the end.
Definition: array.hpp:287
std::enable_if< Size==0, const T * >::type _get_data() const
Support for zero sized array.
Definition: array.hpp:579
slice< range_snapshotting_iterator< T > > range(size_type start, size_type n, size_type snapshot_size=std::numeric_limits< size_type >::max())
Returns slice.
Definition: array.hpp:413
std::enable_if< Size==0 >::type swap(array &other)
Swap for zero-sized array.
Definition: array.hpp:536
Const iterator.
Definition: contiguous_iterator.hpp:208
Persistent smart pointer.
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Non-member greater than operator.
Definition: array.hpp:621
Iterface to access sequence of objects.
reference at(size_type n)
Access element at specific index and add it to a transaction.
Definition: array.hpp:162
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:516
const_reverse_iterator crend() const noexcept
Returns a const reverse iterator to the beginning.
Definition: array.hpp:347
Definition: allocator.hpp:48
constexpr size_type size() const noexcept
Returns size of the array.
Definition: array.hpp:476
array & operator=(array &&other)
Move assignment operator - adds &#39;this&#39; to a transaction.
Definition: array.hpp:146
reference front()
Access the first element and add this element to a transaction.
Definition: array.hpp:359
const_reference at(size_type n) const
Access element at specific index.
Definition: array.hpp:178