mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 08:02:02 +00:00
Field: fixed memory leak [#CLICKHOUSE-2756].
This commit is contained in:
parent
6226132be0
commit
7fa73c5462
@ -79,6 +79,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Позволяет получить идентификатор для типа или наоборот.
|
/// Позволяет получить идентификатор для типа или наоборот.
|
||||||
template <typename T> struct TypeToEnum;
|
template <typename T> struct TypeToEnum;
|
||||||
template <Types::Which which> struct EnumToType;
|
template <Types::Which which> struct EnumToType;
|
||||||
@ -99,7 +100,7 @@ public:
|
|||||||
|
|
||||||
Field(Field && rhs)
|
Field(Field && rhs)
|
||||||
{
|
{
|
||||||
move(std::move(rhs));
|
create(std::move(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -108,6 +109,12 @@ public:
|
|||||||
create(rhs);
|
create(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Field(T && rhs)
|
||||||
|
{
|
||||||
|
create(std::move(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
/// Создать строку inplace.
|
/// Создать строку inplace.
|
||||||
Field(const char * data, size_t size)
|
Field(const char * data, size_t size)
|
||||||
{
|
{
|
||||||
@ -119,6 +126,7 @@ public:
|
|||||||
create(data, size);
|
create(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NOTE In case when field already has string type, more direct assign is possible.
|
||||||
void assignString(const char * data, size_t size)
|
void assignString(const char * data, size_t size)
|
||||||
{
|
{
|
||||||
destroy();
|
destroy();
|
||||||
@ -135,8 +143,13 @@ public:
|
|||||||
{
|
{
|
||||||
if (this != &rhs)
|
if (this != &rhs)
|
||||||
{
|
{
|
||||||
destroy();
|
if (which != rhs.which)
|
||||||
create(rhs);
|
{
|
||||||
|
destroy();
|
||||||
|
create(rhs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assign(rhs); /// This assigns string or vector without deallocation of existing buffer.
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -145,7 +158,13 @@ public:
|
|||||||
{
|
{
|
||||||
if (this != &rhs)
|
if (this != &rhs)
|
||||||
{
|
{
|
||||||
move(std::move(rhs));
|
if (which != rhs.which)
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
create(std::move(rhs));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assign(std::move(rhs));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -153,8 +172,28 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
Field & operator= (const T & rhs)
|
Field & operator= (const T & rhs)
|
||||||
{
|
{
|
||||||
destroy();
|
if (which != TypeToEnum<T>::value)
|
||||||
create(rhs);
|
{
|
||||||
|
destroy();
|
||||||
|
create(rhs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assign(rhs);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Field & operator= (T && rhs)
|
||||||
|
{
|
||||||
|
if (which != TypeToEnum<T>::value)
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
create(std::move(rhs));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assign(std::move(rhs));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +328,7 @@ private:
|
|||||||
Types::Which which;
|
Types::Which which;
|
||||||
|
|
||||||
|
|
||||||
|
/// Assuming there was no allocated state or it was deallocated (see destroy).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void create(const T & x)
|
void create(const T & x)
|
||||||
{
|
{
|
||||||
@ -297,25 +337,70 @@ private:
|
|||||||
new (ptr) T(x);
|
new (ptr) T(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create(const Null & x)
|
template <typename T>
|
||||||
|
void create(T && x)
|
||||||
{
|
{
|
||||||
which = Types::Null;
|
which = TypeToEnum<T>::value;
|
||||||
|
T * __attribute__((__may_alias__)) ptr = reinterpret_cast<T*>(storage);
|
||||||
|
new (ptr) T(std::move(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assuming same types.
|
||||||
|
template <typename T>
|
||||||
|
void assign(const T & x)
|
||||||
|
{
|
||||||
|
T * __attribute__((__may_alias__)) ptr = reinterpret_cast<T*>(storage);
|
||||||
|
*ptr = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void assign(T && x)
|
||||||
|
{
|
||||||
|
T * __attribute__((__may_alias__)) ptr = reinterpret_cast<T*>(storage);
|
||||||
|
*ptr = std::move(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename F, typename Field> /// Field template parameter may be const or non-const Field.
|
||||||
|
static void dispatch(F && f, Field & field)
|
||||||
|
{
|
||||||
|
switch (field.which)
|
||||||
|
{
|
||||||
|
case Types::Null: f(field.get<Null>()); return;
|
||||||
|
case Types::UInt64: f(field.get<UInt64>()); return;
|
||||||
|
case Types::Int64: f(field.get<Int64>()); return;
|
||||||
|
case Types::Float64: f(field.get<Float64>()); return;
|
||||||
|
case Types::String: f(field.get<String>()); return;
|
||||||
|
case Types::Array: f(field.get<Array>()); return;
|
||||||
|
case Types::Tuple: f(field.get<Tuple>()); return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void create(const Field & x)
|
void create(const Field & x)
|
||||||
{
|
{
|
||||||
switch (x.which)
|
dispatch([this] (auto & value) { create(value); }, x);
|
||||||
{
|
|
||||||
case Types::Null: create(Null()); break;
|
|
||||||
case Types::UInt64: create(x.get<UInt64>()); break;
|
|
||||||
case Types::Int64: create(x.get<Int64>()); break;
|
|
||||||
case Types::Float64: create(x.get<Float64>()); break;
|
|
||||||
case Types::String: create(x.get<String>()); break;
|
|
||||||
case Types::Array: create(x.get<Array>()); break;
|
|
||||||
case Types::Tuple: create(x.get<Tuple>()); break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create(Field && x)
|
||||||
|
{
|
||||||
|
dispatch([this] (auto & value) { create(std::move(value)); }, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign(const Field & x)
|
||||||
|
{
|
||||||
|
dispatch([this] (auto & value) { assign(value); }, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign(Field && x)
|
||||||
|
{
|
||||||
|
dispatch([this] (auto & value) { assign(std::move(value)); }, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void create(const char * data, size_t size)
|
void create(const char * data, size_t size)
|
||||||
{
|
{
|
||||||
which = Types::String;
|
which = Types::String;
|
||||||
@ -347,6 +432,8 @@ private:
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
which = Types::Null; /// for exception safety in subsequent calls to destroy and create, when create fails.
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -355,31 +442,6 @@ private:
|
|||||||
T * __attribute__((__may_alias__)) ptr = reinterpret_cast<T*>(storage);
|
T * __attribute__((__may_alias__)) ptr = reinterpret_cast<T*>(storage);
|
||||||
ptr->~T();
|
ptr->~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void moveValue(Field && x)
|
|
||||||
{
|
|
||||||
T * __attribute__((__may_alias__)) ptr_this = reinterpret_cast<T*>(storage);
|
|
||||||
T * __attribute__((__may_alias__)) ptr_x = reinterpret_cast<T*>(x.storage);
|
|
||||||
|
|
||||||
new (ptr_this) T(std::move(*ptr_x));
|
|
||||||
}
|
|
||||||
|
|
||||||
void move(Field && x)
|
|
||||||
{
|
|
||||||
which = x.which;
|
|
||||||
|
|
||||||
switch (x.which)
|
|
||||||
{
|
|
||||||
case Types::Null: create(Null()); break;
|
|
||||||
case Types::UInt64: create(x.get<UInt64>()); break;
|
|
||||||
case Types::Int64: create(x.get<Int64>()); break;
|
|
||||||
case Types::Float64: create(x.get<Float64>()); break;
|
|
||||||
case Types::String: moveValue<String>(std::move(x)); break;
|
|
||||||
case Types::Array: moveValue<Array>(std::move(x)); break;
|
|
||||||
case Types::Tuple: moveValue<Tuple>(std::move(x)); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef DBMS_MIN_FIELD_SIZE
|
#undef DBMS_MIN_FIELD_SIZE
|
||||||
@ -393,7 +455,7 @@ template <> struct Field::TypeToEnum<String> { static const Types::Which
|
|||||||
template <> struct Field::TypeToEnum<Array> { static const Types::Which value = Types::Array; };
|
template <> struct Field::TypeToEnum<Array> { static const Types::Which value = Types::Array; };
|
||||||
template <> struct Field::TypeToEnum<Tuple> { static const Types::Which value = Types::Tuple; };
|
template <> struct Field::TypeToEnum<Tuple> { static const Types::Which value = Types::Tuple; };
|
||||||
|
|
||||||
template <> struct Field::EnumToType<Field::Types::Null> { using Type = Null ; };
|
template <> struct Field::EnumToType<Field::Types::Null> { using Type = Null ; };
|
||||||
template <> struct Field::EnumToType<Field::Types::UInt64> { using Type = UInt64 ; };
|
template <> struct Field::EnumToType<Field::Types::UInt64> { using Type = UInt64 ; };
|
||||||
template <> struct Field::EnumToType<Field::Types::Int64> { using Type = Int64 ; };
|
template <> struct Field::EnumToType<Field::Types::Int64> { using Type = Int64 ; };
|
||||||
template <> struct Field::EnumToType<Field::Types::Float64> { using Type = Float64 ; };
|
template <> struct Field::EnumToType<Field::Types::Float64> { using Type = Float64 ; };
|
||||||
|
Loading…
Reference in New Issue
Block a user