Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for non-seastar managed strings #833

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 36 additions & 8 deletions include/seastar/core/sstring.hh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class basic_sstring {
struct external_type {
char_type* str;
Size size;
bool is_ref;//all non-managed non-copy string references should set this flag to true
Copy link
Contributor

@nyh nyh Dec 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regardless of whether this patch is needed at all (see my other comment) please note you shouldn't just add something to "external type" - it will make it longer, and longer than "internal_type", and waste space. What you can do is to replace the old "pad" with a single-byte flag. HOWEVER, this byte - in internal - is already used to for the internal size. So maybe you should pick a specific value (e.g., 255) which will say this is a ref. Should probably have a function (is_ref()) to abstract this check.

int8_t pad;
} external;
struct internal_type {
Expand Down Expand Up @@ -106,6 +107,7 @@ public:
struct initialized_later {};

basic_sstring() noexcept {
u.external.is_ref = false;
Copy link
Contributor

@nyh nyh Dec 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, "u" is a union, you need to set either external or internal, you can't set both... In this constructor, the string is internal, so you musn't set external. The only byte common to both union members is the last one (size or pad). In fact, the sstring code would have been better and clearer if this byte was outside the union.

u.internal.size = 0;
if (NulTerminate) {
u.internal.str[0] = '\0';
Expand All @@ -115,13 +117,19 @@ public:
if (x.is_internal()) {
u.internal = x.u.internal;
} else {
u.external.is_ref = x.u.external.is_ref;
u.internal.size = -1;
u.external.str = reinterpret_cast<char_type*>(std::malloc(x.u.external.size + padding()));
if (!u.external.str) {
internal::throw_bad_alloc();
if(x.u.external.is_ref) {
u.external.str = x.u.external.str;
u.external.size = x.u.external.size;
} else {
u.external.str = reinterpret_cast<char_type*>(std::malloc(x.u.external.size + padding()));
if (!u.external.str) {
internal::throw_bad_alloc();
}
std::copy(x.u.external.str, x.u.external.str + x.u.external.size + padding(), u.external.str);
u.external.size = x.u.external.size;
}
std::copy(x.u.external.str, x.u.external.str + x.u.external.size + padding(), u.external.str);
u.external.size = x.u.external.size;
}
}
basic_sstring(basic_sstring&& x) noexcept {
Expand All @@ -145,6 +153,7 @@ public:
}
u.internal.size = size;
} else {
u.external.is_ref = false;
u.internal.size = -1;
u.external.str = reinterpret_cast<char_type*>(std::malloc(size + padding()));
if (!u.external.str) {
Expand All @@ -156,7 +165,14 @@ public:
}
}
}
basic_sstring(const char_type* x, size_t size) {
basic_sstring(const char_type* x, size_t size, bool is_ref = false) {
u.external.is_ref = is_ref;
if(is_ref) {
u.internal.size = -1;
u.external.str = (char*)x;
u.external.size = size;
return;
}
if (size_type(size) != size) {
internal::throw_sstring_overflow();
}
Expand All @@ -181,6 +197,7 @@ public:
}

basic_sstring(size_t size, char_type x) : basic_sstring(initialized_later(), size) {
u.external.is_ref = false;
memset(begin(), x, size);
}

Expand All @@ -199,11 +216,18 @@ public:
: basic_sstring(v.data(), v.size()) {
}
~basic_sstring() noexcept {
if (is_external()) {
if (is_external() && !u.external.is_ref) {
std::free(u.external.str);
}
}
basic_sstring& operator=(const basic_sstring& x) {
if (x.is_external() && x.u.external.is_ref) {
u.external.is_ref = x.u.external.is_ref;
u.internal.size = -1;
u.external.str = x.u.external.str;
u.external.size = x.u.external.size;
return *this;
}
basic_sstring tmp(x);
swap(tmp);
return *this;
Expand Down Expand Up @@ -303,6 +327,7 @@ public:
* @param c if n greater than current size character to fill newly allocated space with.
*/
void resize(size_t n, const char_type c = '\0') {
if(u.external.is_ref) return;
if (n > size()) {
*this += basic_sstring(n - size(), c);
} else if (n < size()) {
Expand Down Expand Up @@ -448,7 +473,7 @@ public:
// Deprecated March 2020.
[[deprecated("Use = {}")]]
void reset() noexcept {
if (is_external()) {
if (is_external() && !u.external.is_ref) {
std::free(u.external.str);
}
u.internal.size = 0;
Expand All @@ -462,6 +487,9 @@ public:
auto size = u.external.size;
u.external.str = nullptr;
u.external.size = 0;
if(u.external.is_ref) {
return temporary_buffer<char_type>(size);
}
return temporary_buffer<char_type>(ptr, size, make_free_deleter(ptr));
} else {
auto buf = temporary_buffer<char_type>(u.internal.size);
Expand Down