Skip to content

Commit

Permalink
kj::ArrayPtr<T>::copyFrom method (#2035)
Browse files Browse the repository at this point in the history
Type-safe alternative to memcpy. As with the fill case
compilers are pretty good at optimizing it too:

https://godbolt.org/z/dfMxeT1M5
  • Loading branch information
mikea committed May 13, 2024
1 parent e32ad07 commit 8dd8823
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
13 changes: 13 additions & 0 deletions c++/src/kj/common-test.c++
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,19 @@ KJ_TEST("ArrayPtr::as<Std>") {
KJ_EXPECT(stdPtr.size() == 5);
}

KJ_TEST("ArrayPtr::copyFrom") {
int arr1[] = {12, 34, 56, 34, 12};
int arr2[] = {98, 67, 9, 22, 107};
int arr3[] = {98, 67, 9, 22, 107};

KJ_EXPECT(arrayPtr(arr1) != arrayPtr(arr2));
KJ_EXPECT(arrayPtr(arr2) == arrayPtr(arr3));

arrayPtr(arr1).copyFrom(arr2);
KJ_EXPECT(arrayPtr(arr1) == arrayPtr(arr2));
KJ_EXPECT(arrayPtr(arr2) == arrayPtr(arr3));
}

// Verifies the expected values of kj::isDisallowedInCoroutine<T>

struct DisallowedInCoroutineStruct {
Expand Down
19 changes: 19 additions & 0 deletions c++/src/kj/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -1954,9 +1954,28 @@ class ArrayPtr: public DisallowConstCopyIfNotConst<T> {
// libc++ std::fill doesn't have memset specialization either.
}

inline void copyFrom(kj::ArrayPtr<const T> other) {
// Copy data from the other array pointer.
// Arrays have to be of the same size and memory area MUST NOT overlap.
KJ_IREQUIRE(size_ == other.size(), "copy requires arrays of the same size");
KJ_IREQUIRE(!intersects(other), "copy memory area must not overlap");
T* __restrict__ dst = begin();
const T* __restrict__ src = other.begin();
for (size_t s = size_, i = 0; i < s; i++) { dst[i] = src[i]; }
}

private:
T* ptr;
size_t size_;

inline bool intersects(kj::ArrayPtr<const T> other) const {
// Checks if memory area intersects with another pointer.

// Memory _does not_ intersect if one of the arrays is completely on one side of the other:
// begin() >= other.end() || other.begin() >= end()
// Negating the expression gets the result:
return begin() < other.end() && other.begin() < end();
}
};

template <>
Expand Down

0 comments on commit 8dd8823

Please sign in to comment.