Core: trivially_relocatable

This commit is contained in:
Mirek Fidler 2024-08-23 08:35:19 +02:00
parent abb5c9ae17
commit 3638778b2e
20 changed files with 140 additions and 136 deletions

View file

@ -12,8 +12,8 @@ protected:
void ReAlloc(int newalloc);
void Add0();
void DeepCopy0(const BiVector& src);
T *AddHead0() { AssertMoveable<T>(); Add0(); return &vector[start = Ix(alloc - 1)/*(start + alloc - 1) % alloc*/]; }
T *AddTail0() { AssertMoveable<T>(); Add0(); return &vector[EI()]; }
T *AddHead0() { Add0(); return &vector[start = Ix(alloc - 1)/*(start + alloc - 1) % alloc*/]; }
T *AddTail0() { Add0(); return &vector[EI()]; }
void Zero() { start = items = alloc = 0; vector = NULL; }
void Free();
void Pick(BiVector&& x) { vector = pick(x.vector); start = x.start; items = x.items;
@ -21,6 +21,8 @@ protected:
void Copy(T *dst, int start, int count) const;
public:
static_assert(is_trivially_relocatable<T> || is_upp_guest<T>);
int GetCount() const { return items; }
bool IsEmpty() const { return items == 0; }
void Clear();

View file

@ -54,4 +54,6 @@ inline bool IsInf(const Complex& x) { return IsInf(x.real()) || IsInf(x.i
inline bool IsFin(const Complex& x) { return IsFin(x.real()) && IsFin(x.imag()); }
VALUE_COMPARE(Complex)
NTL_MOVEABLE(Complex)
template <> inline constexpr bool is_trivially_relocatable<Complex> = true;

View file

@ -1,7 +1,7 @@
#ifndef CORE_H
#define CORE_H
#define UPP_VERSION 0x20220300
#define UPP_VERSION 0x20240900
#ifndef flagMT
#define flagMT // MT is now always on
@ -410,12 +410,6 @@ String AsString(const i16x8& x);
String AsString(const i8x16& x);
#endif
#ifdef PLATFORM_WIN32
NTL_MOVEABLE(POINT)
NTL_MOVEABLE(SIZE)
NTL_MOVEABLE(RECT)
#endif
}
#if (defined(TESTLEAKS) || defined(HEAPDBG)) && defined(COMPILER_GCC) && defined(UPP_HEAP)

View file

@ -65,7 +65,7 @@ Value ParseJSON(const char *s)
String AsJSON(Time tm)
{
return IsNull(tm) ? "null" : "\"\\/Date(" + AsString(1000 * (tm - Time(1970, 1, 1))) + ")\\/\"";
return IsNull(tm) ? String("null") : "\"\\/Date(" + AsString(1000 * (tm - Time(1970, 1, 1))) + ")\\/\"";
}
String AsJSON(Date dt)

View file

@ -444,7 +444,7 @@ String LanguageInfo::FormatDouble(double value, int digits, int FD_flags, int fi
return Null;
return NlsFormatRaw(UPP::FormatDouble(value, digits, FD_flags),
FD_flags & FD_NOTHSEPS ? String() : thousand_separator,
FD_flags & FD_COMMA ? "," : decimal_point);
FD_flags & FD_COMMA ? String(",") : decimal_point);
}
String LanguageInfo::FormatDate(Date date) const

View file

@ -233,13 +233,13 @@ String FileExtToMIME(const String& ext)
if(*h == '.')
h = h.Mid(1);
int q = sEXT().Find(h);
return q >= 0 ? sMIME()[q] : "application/octet-stream";
return q >= 0 ? sMIME()[q] : String("application/octet-stream");
}
String MIMEToFileExt(const String& mime)
{
int q = sMIME().Find(ToLower(mime));
return q >= 0 ? sEXT()[q] : "bin";
return q >= 0 ? sEXT()[q] : String("bin");
}
}

View file

@ -330,14 +330,12 @@ void memcpy128(void *p, const void *q, size_t count)
template <class T>
void memcpy_t(void *t, const T *s, size_t count)
{
#ifdef CPU_X86
if((sizeof(T) & 15) == 0)
memcpy128(t, s, count * (sizeof(T) >> 4));
else
if((sizeof(T) & 7) == 0)
memcpy64(t, s, count * (sizeof(T) >> 3));
else
#endif
if((sizeof(T) & 3) == 0)
memcpy32(t, s, count * (sizeof(T) >> 2));
else

View file

@ -343,7 +343,7 @@ public:
~String0() { Free(); }
};
class String : public Moveable<String, AString<String0> > {
class String : Moveable<String>, public AString<String0> {
void Swap(String& b) { String0::Swap(b); }
#ifdef _DEBUG
@ -799,7 +799,7 @@ public:
// WString0& operator=(const WString0& s) { Free(); Set0(s); return *this; }
};
class WString : public Moveable<WString, AString<WString0> >
class WString : Moveable<WString>, public AString<WString0>
{
void Swap(WString& b) { WString0::Swap(b); }

View file

@ -130,74 +130,108 @@ inline void Fill(unsigned char *t, const unsigned char *lim, const unsigned char
inline void Copy(unsigned char *dst, const unsigned char *src, const unsigned char *lim)
{ memcpy8(dst, src, size_t((byte *)lim - (byte *)src)); }
#ifdef NO_MOVEABLE_CHECK
template <class T>
inline void DeepCopyConstructFill(T *t, const T *end, const T& x) {
while(t != end)
new(t++) T(clone(x));
}
template <class T>
inline void AssertMoveable(T *) {}
inline void Construct(T *t, const T *lim) {
while(t < lim)
new(t++) T;
}
#define MoveableTemplate(T)
template <class T, class B = EmptyClass>
class Moveable : public B
template <class T>
inline void Destruct(T *t)
{
};
t->~T();
}
template <class T>
struct Moveable_ {
};
#define NTL_MOVEABLE(T)
#else
inline void Destroy(T *t, const T *end)
{
while(t != end)
Destruct(t++);
}
template <class T>
inline void AssertMoveablePtr(T, T) {}
template <class T>
inline void AssertMoveable0(T *t) { AssertMoveablePtr(&**t, *t); }
// COMPILATION ERROR HERE MEANS TYPE T WAS NOT MARKED AS Moveable
struct TriviallyRelocatable {};
template <class T, class B = EmptyClass>
struct Moveable : public B {
friend void AssertMoveable0(T *) {}
};
struct Moveable : TriviallyRelocatable<T> {};
template <class T> // backward compatiblity
struct Moveable_ : Moveable<T> {};
template <class T>
struct Moveable_ {
friend void AssertMoveable0(T *) {}
};
inline constexpr bool is_trivially_relocatable = std::is_trivially_copyable_v<T> ||
std::is_base_of_v<TriviallyRelocatable<T>, T>;
template <class T>
inline void AssertMoveable(T *t = 0) { if(t) AssertMoveable0(t); }
inline constexpr bool is_upp_guest = false;
#if defined(COMPILER_MSC) || defined(COMPILER_GCC) && (__GNUC__ < 4 || __GNUC_MINOR__ < 1)
#define NTL_MOVEABLE(T) inline void AssertMoveable0(T *) {}
#else
#define NTL_MOVEABLE(T) template<> inline void AssertMoveable<T>(T *) {}
#endif
template <class T>
inline typename std::enable_if_t<is_trivially_relocatable<T>> Move(T *dst, T *src)
{
memcpy(dst, src, sizeof(T));
}
#endif
template <class T>
inline typename std::enable_if_t<!is_trivially_relocatable<T>> Move(T *dst, T *src)
{
new(dst) T(pick(*src));
Destruct(src);
}
NTL_MOVEABLE(bool)
NTL_MOVEABLE(char)
NTL_MOVEABLE(signed char)
NTL_MOVEABLE(unsigned char)
NTL_MOVEABLE(short)
NTL_MOVEABLE(unsigned short)
NTL_MOVEABLE(int)
NTL_MOVEABLE(unsigned int)
NTL_MOVEABLE(long)
NTL_MOVEABLE(unsigned long)
NTL_MOVEABLE(int64)
NTL_MOVEABLE(uint64)
NTL_MOVEABLE(float)
NTL_MOVEABLE(double)
NTL_MOVEABLE(void *)
NTL_MOVEABLE(const void *)
template <class T>
inline void InMove(T *dst, T *src, int n)
{
if(is_trivially_relocatable<T>)
memmove(dst, src, n * sizeof(T));
else {
if(n <= 0)
return;
dst += n - 1;
T *s = src + n - 1;
for(;;) {
Move(dst, s);
if(s == src) break;
dst--;
s--;
}
}
}
#if defined(_NATIVE_WCHAR_T_DEFINED) || defined(COMPILER_GCC)
NTL_MOVEABLE(wchar_t)
#endif
template <class T>
inline void ReMove(T *dst, T *src, int n)
{
if(is_trivially_relocatable<T>)
memmove(dst, src, n * sizeof(T));
else {
T *lim = src + n;
while(src != lim)
Move(dst++, src++);
}
}
template <class T>
inline void Relocate(T *dst, T *src, int n)
{
if(is_trivially_relocatable<T>)
memcpy_t(dst, src, n);
else {
T *lim = src + n;
while(src != lim)
Move(dst++, src++);
}
}
template <class T, class S>
inline void DeepCopyConstruct(T *t, const S *s, const S *end) {
while(s != end)
new (t++) T(clone(*s++));
}
template <class T, class B = EmptyClass>
class WithClone : public B {
@ -216,8 +250,7 @@ public:
};
template <class T, class B = EmptyClass>
class MoveableAndDeepCopyOption : public B {
friend void AssertMoveable0(T *) {}
class MoveableAndDeepCopyOption : public Moveable<T> {
#ifdef DEPRECATED
friend T& operator<<=(T& dest, const T& src)
{ if(&dest != &src) { (&dest)->~T(); ::new(&dest) T(src, 1); } return dest; }
@ -421,9 +454,6 @@ public:
STL_ITERATOR_COMPATIBILITY
};
unsigned Pow2Bound(unsigned i);
unsigned PrimeBound(unsigned i);
hash_t memhash(const void *ptr, size_t size);
template <class T>
@ -480,12 +510,6 @@ public:
template <class T> CombineHash& operator<<(const T& x) { Do(x); return *this; }
};
template <int size>
struct Data_S_ : Moveable< Data_S_<size> >
{
byte filler[size];
};
template <class C>
bool IsEqualMap(const C& a, const C& b)
{

View file

@ -155,6 +155,21 @@ public:
Tuple(const Args... args) : Base(args...) {};
};
template <typename A, typename B>
inline constexpr bool is_trivially_relocatable<Tuple<A, B>> = is_trivially_relocatable<A> &&
is_trivially_relocatable<B>;
template <typename A, typename B, typename C>
inline constexpr bool is_trivially_relocatable<Tuple<A, B, C>> = is_trivially_relocatable<A> &&
is_trivially_relocatable<B> &&
is_trivially_relocatable<C>;
template <typename A, typename B, typename C, typename D>
inline constexpr bool is_trivially_relocatable<Tuple<A, B, C, D>> = is_trivially_relocatable<A> &&
is_trivially_relocatable<B> &&
is_trivially_relocatable<C> &&
is_trivially_relocatable<D>;
template <typename... Args>
Tuple<Args...> MakeTuple(const Args... args) {
return Tuple<Args...>(args...);

View file

@ -77,7 +77,7 @@ class AssignValueTypeNo : public ValueType<T, type, B> {};
template <class T>
dword GetValueTypeNo() { return ValueTypeNo((T*)NULL); }
class Value : Moveable_<Value> {
class Value : Moveable<Value> {
public:
class Void {
protected:
@ -292,7 +292,7 @@ public:
friend void Swap(Value& a, Value& b) { Swap(a.data, b.data); }
typedef ConstIteratorOf<Vector<Value>> const_iterator;
typedef const Value *const_iterator;
const_iterator begin() const { return GetVA().begin(); }
const_iterator end() const { return GetVA().end(); }

View file

@ -9,33 +9,6 @@ void BREAK_WHEN_PICKED(T& x)
}
#endif
template <class T>
inline void DeepCopyConstructFill(T *t, const T *end, const T& x) {
while(t != end)
new(t++) T(clone(x));
}
template <class T>
inline void Construct(T *t, const T *lim) {
while(t < lim)
new(t++) T;
}
template <class T>
inline void Destroy(T *t, const T *end)
{
while(t != end) {
t->~T();
t++;
}
}
template <class T, class S>
inline void DeepCopyConstruct(T *t, const S *s, const S *end) {
while(s != end)
new (t++) T(clone(*s++));
}
template <class T>
class Buffer : Moveable< Buffer<T> > {
T *ptr;
@ -165,6 +138,8 @@ template <class U> class Index;
template <class T>
class Vector : public MoveableAndDeepCopyOption< Vector<T> > {
static_assert(is_trivially_relocatable<T> || is_upp_guest<T>);
T *vector;
int items;
int alloc;
@ -283,7 +258,6 @@ public:
~Vector() {
Free();
return; // Constraints:
AssertMoveable((T *)0); // T must be moveable
}
// Pick assignment & copy. Picked source can only do Clear(), ~Vector(), operator=, operator <<=

View file

@ -122,7 +122,7 @@ bool Vector<T>::ReAlloc(int newalloc)
alloc = newalloc == INT_MAX ? INT_MAX // maximum alloc reached
: (int)((sz - sz0) / sizeof(T) + newalloc); // adjust alloc to real memory size
if(vector && newvector)
memcpy_t((T *)newvector, vector, items);
Relocate((T *)newvector, vector, items);
vector = (T *)newvector;
return alloced;
}
@ -306,7 +306,7 @@ void Vector<T>::Remove(int q, int count) {
ASSERT(q >= 0 && q <= items - count && count >= 0);
if(count == 0) return;
Destroy(vector + q, vector + q + count);
memmove((void *)(vector + q), (void *)(vector + q + count), (items - q - count) * sizeof(T));
ReMove(vector + q, vector + q + count, items - q - count);
items -= count;
}
@ -319,18 +319,17 @@ void Vector<T>::Remove(const int *sorted_list, int n)
for(;;) {
ASSERT(pos < items);
if(pos == *sorted_list) {
(vector + pos)->~T();
Destruct(vector + pos);
pos++;
sorted_list++;
if(--n == 0) break;
ASSERT(*sorted_list >= pos);
}
else
*((Data_S_<sizeof(T)>*)vector + npos++)
= *((Data_S_<sizeof(T)>*)vector + pos++);
Move(vector + npos++, vector + pos++);
}
while(pos < items)
*((Data_S_<sizeof(T)>*)vector + npos++) = *((Data_S_<sizeof(T)>*)vector + pos++);
Move(vector + npos++, vector + pos++);
items = npos;
}
@ -347,15 +346,15 @@ void Vector<T>::RemoveIf(Condition c)
int i = 0;
for(; i < items; i++) // run to the first element without moving
if(c(i)) {
(vector + i)->~T();
Destruct(vector + i);
break;
}
int ti = i++;
for(; i < items; i++)
if(c(i))
(vector + i)->~T();
Destruct(vector + i);
else
*((Data_S_<sizeof(T)>*)vector + ti++) = *((Data_S_<sizeof(T)>*)vector + i);
Move(vector + ti++, vector + i);
items = ti;
}
@ -368,14 +367,14 @@ void Vector<T>::RawInsert(int q, int count)
if(items + count > alloc) {
T *newvector = RawAlloc(alloc = max(alloc + count, int(alloc + ((unsigned)alloc >> 1))));
if(vector) {
memcpy_t(newvector, vector, q);
memcpy_t(newvector + q + count, vector + q, items - q);
Relocate(newvector, vector, q);
Relocate(newvector + q + count, vector + q, items - q);
RawFree(vector);
}
vector = newvector;
}
else
memmove((void *)(vector + q + count), (void *)(vector + q), (items - q) * sizeof(T));
InMove(vector + q + count, vector + q, items - q);
items += count;
}
@ -442,7 +441,7 @@ void Vector<T>::Insert(int i, Vector<T>&& v) {
ASSERT(!vector || v.vector != vector);
if(v.items) {
RawInsert(i, v.items);
memcpy_t(vector + i, v.vector, v.items);
Relocate(vector + i, v.vector, v.items);
}
RawFree(v.vector);
v.Zero();
@ -455,7 +454,7 @@ void Vector<T>::InsertSplit(int i, Vector<T>& v, int from)
int n = v.GetCount() - from;
if(n) {
RawInsert(i, n);
memcpy_t(vector + i, v.vector + from, n);
Relocate(vector + i, v.vector + from, n);
v.items = from;
}
}
@ -737,10 +736,10 @@ void BiVector<T>::ReAlloc(int newalloc) {
if(items) {
int end = start + items;
if(end <= alloc)
memcpy_t(newvector, vector + start, end - start);
Relocate(newvector, vector + start, end - start);
else {
memcpy_t(newvector, vector + start, alloc - start);
memcpy_t(newvector + alloc - start, vector, end - alloc);
Relocate(newvector, vector + start, alloc - start);
Relocate(newvector + alloc - start, vector, end - alloc);
}
MemoryFree(vector);
}

View file

@ -174,7 +174,7 @@ public:
XmlParser(Stream& in);
};
class XmlNode : Moveable< XmlNode, DeepCopyOption<XmlNode> > {
class XmlNode : Moveable<XmlNode>, DeepCopyOption<XmlNode> {
int type;
String text;
Array<XmlNode> node;

View file

@ -3,8 +3,6 @@ struct KeyInfo {
dword key[4];
};
NTL_MOVEABLE(KeyInfo)
void RegisterKeyBinding(const char *group, const char *id, KeyInfo& (*info)());
KeyInfo& AK_NULL();

View file

@ -148,7 +148,7 @@ private:
byte cap;
bool invert;
};
struct Attr : Moveable<Attr, SimpleAttr> {
struct Attr : Moveable<Attr>, SimpleAttr {
int mtx_serial; // used to detect changes to speedup preclip
WithDeepCopy<Vector<ColorStop>> color_stop;

View file

@ -73,7 +73,7 @@ inline Size operator/(Size sz, Zoom m)
return Size(sz.cx / m, sz.cy / m);
}
struct PageY : Moveable<PageY, RelOps<PageY> > {
struct PageY : Moveable<PageY>, RelOps<PageY> {
int page;
int y;

View file

@ -90,7 +90,7 @@ struct Pdb : Debugger, ParentCtrl {
bool reference = false; // this is reference
};
struct Val : Moveable<Val, TypeInfo> {
struct Val : Moveable<Val>, TypeInfo {
bool array = false;
bool rvalue = false; // data is loaded from debugee (if false, data pointed to by address)
bool udt = false; // user defined type (e.g. struct..)

View file

@ -5,7 +5,7 @@ struct FileLine : Moveable<FileLine> {
int line;
};
struct LngEntry : Moveable<LngEntry, DeepCopyOption<LngEntry> > {
struct LngEntry : Moveable<LngEntry>, DeepCopyOption<LngEntry> {
bool added;
VectorMap<int, String> text;
Vector<FileLine> fileline;

View file

@ -41,8 +41,6 @@ static void png_user_warning_fn(png_structp png_ptr, png_const_charp warning_msg
LLOG("png warning: " << warning_msg);
}
NTL_MOVEABLE(png_color)
static Size GetDotSize(Size pixel_size, png_uint_32 x_ppm, png_uint_32 y_ppm, int unit_type)
{
if(unit_type != 1 || !x_ppm || !y_ppm)