mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 04:06:14 +00:00
-Changed memory functions, Memory::alloc_static*, simplified them, made them aligned to 16
-Changed Vector<> template to fit this.
This commit is contained in:
parent
99ceddd11e
commit
53ce643e52
@ -30,9 +30,68 @@
|
||||
#include "error_macros.h"
|
||||
#include "copymem.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
MID::MID(MemoryPoolDynamic::ID p_id) {
|
||||
|
||||
data = (Data*)memalloc(sizeof(Data));
|
||||
data->refcount.init();
|
||||
data->id=p_id;
|
||||
}
|
||||
|
||||
void MID::unref() {
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
if (data->refcount.unref()) {
|
||||
|
||||
if (data->id!=MemoryPoolDynamic::INVALID_ID)
|
||||
MemoryPoolDynamic::get_singleton()->free(data->id);
|
||||
memfree(data);
|
||||
}
|
||||
|
||||
data=NULL;
|
||||
}
|
||||
Error MID::_resize(size_t p_size) {
|
||||
|
||||
if (p_size==0 && (!data || data->id==MemoryPoolDynamic::INVALID_ID))
|
||||
return OK;
|
||||
if (p_size && !data) {
|
||||
// create data because we'll need it
|
||||
data = (Data*)memalloc(sizeof(Data));
|
||||
ERR_FAIL_COND_V( !data,ERR_OUT_OF_MEMORY );
|
||||
data->refcount.init();
|
||||
data->id=MemoryPoolDynamic::INVALID_ID;
|
||||
}
|
||||
|
||||
if (p_size==0 && data && data->id==MemoryPoolDynamic::INVALID_ID) {
|
||||
|
||||
MemoryPoolDynamic::get_singleton()->free(data->id);
|
||||
data->id=MemoryPoolDynamic::INVALID_ID;
|
||||
}
|
||||
|
||||
if (p_size>0) {
|
||||
|
||||
if (data->id==MemoryPoolDynamic::INVALID_ID) {
|
||||
|
||||
data->id=MemoryPoolDynamic::get_singleton()->alloc(p_size,"Unnamed MID");
|
||||
ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
|
||||
|
||||
} else {
|
||||
|
||||
MemoryPoolDynamic::get_singleton()->realloc(data->id,p_size);
|
||||
ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void * operator new(size_t p_size,const char *p_description) {
|
||||
|
||||
return Memory::alloc_static( p_size, p_description );
|
||||
return Memory::alloc_static( p_size, false );
|
||||
}
|
||||
|
||||
void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size)) {
|
||||
@ -42,48 +101,146 @@ void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size)) {
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void * Memory::alloc_static(size_t p_bytes,const char *p_alloc_from) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
size_t Memory::mem_usage=0;
|
||||
size_t Memory::max_usage=0;
|
||||
#endif
|
||||
|
||||
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), NULL );
|
||||
return MemoryPoolStatic::get_singleton()->alloc(p_bytes,p_alloc_from);
|
||||
}
|
||||
void * Memory::realloc_static(void *p_memory,size_t p_bytes) {
|
||||
size_t Memory::alloc_count=0;
|
||||
|
||||
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), NULL );
|
||||
return MemoryPoolStatic::get_singleton()->realloc(p_memory,p_bytes);
|
||||
|
||||
void * Memory::alloc_static(size_t p_bytes,bool p_pad_align) {
|
||||
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad=true;
|
||||
#else
|
||||
bool prepad=p_pad_align;
|
||||
#endif
|
||||
|
||||
void * mem = malloc( p_bytes + (prepad?PAD_ALIGN:0));
|
||||
|
||||
alloc_count++;
|
||||
|
||||
ERR_FAIL_COND_V(!mem,NULL);
|
||||
|
||||
if (prepad) {
|
||||
uint64_t *s = (uint64_t*)mem;
|
||||
*s=p_bytes;
|
||||
|
||||
uint8_t *s8 = (uint8_t*)mem;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
mem_usage+=p_bytes;
|
||||
if (mem_usage>max_usage) {
|
||||
max_usage=mem_usage;
|
||||
}
|
||||
#endif
|
||||
return s8 + PAD_ALIGN;
|
||||
} else {
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
void Memory::free_static(void *p_ptr) {
|
||||
void * Memory::realloc_static(void *p_memory,size_t p_bytes,bool p_pad_align) {
|
||||
|
||||
ERR_FAIL_COND( !MemoryPoolStatic::get_singleton());
|
||||
MemoryPoolStatic::get_singleton()->free(p_ptr);
|
||||
if (p_memory==NULL) {
|
||||
return alloc_static(p_bytes,p_pad_align);
|
||||
}
|
||||
|
||||
uint8_t *mem = (uint8_t*)p_memory;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad=true;
|
||||
#else
|
||||
bool prepad=p_pad_align;
|
||||
#endif
|
||||
|
||||
if (prepad) {
|
||||
mem-=PAD_ALIGN;
|
||||
uint64_t *s = (uint64_t*)mem;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
mem_usage-=*s;
|
||||
mem_usage+=p_bytes;
|
||||
#endif
|
||||
|
||||
if (p_bytes==0) {
|
||||
free(mem);
|
||||
return NULL;
|
||||
} else {
|
||||
*s=p_bytes;
|
||||
|
||||
mem = (uint8_t*)realloc(mem,p_bytes+PAD_ALIGN);
|
||||
ERR_FAIL_COND_V(!mem,NULL);
|
||||
|
||||
s = (uint64_t*)mem;
|
||||
|
||||
*s=p_bytes;
|
||||
|
||||
return mem+PAD_ALIGN;
|
||||
}
|
||||
} else {
|
||||
|
||||
mem = (uint8_t*)realloc(mem,p_bytes);
|
||||
|
||||
ERR_FAIL_COND_V(mem==NULL && p_bytes>0,NULL);
|
||||
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
|
||||
void Memory::free_static(void *p_ptr,bool p_pad_align) {
|
||||
|
||||
size_t Memory::get_static_mem_available() {
|
||||
ERR_FAIL_COND(p_ptr==NULL);
|
||||
|
||||
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
|
||||
return MemoryPoolStatic::get_singleton()->get_available_mem();
|
||||
uint8_t *mem = (uint8_t*)p_ptr;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool prepad=true;
|
||||
#else
|
||||
bool prepad=p_pad_align;
|
||||
#endif
|
||||
|
||||
alloc_count--;
|
||||
|
||||
if (prepad) {
|
||||
mem-=PAD_ALIGN;
|
||||
uint64_t *s = (uint64_t*)mem;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
mem_usage-=*s;
|
||||
#endif
|
||||
|
||||
free(mem);
|
||||
} else {
|
||||
|
||||
free(mem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t Memory::get_static_mem_max_usage() {
|
||||
size_t Memory::get_mem_available() {
|
||||
|
||||
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
|
||||
return MemoryPoolStatic::get_singleton()->get_max_usage();
|
||||
}
|
||||
|
||||
size_t Memory::get_static_mem_usage() {
|
||||
|
||||
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
|
||||
return MemoryPoolStatic::get_singleton()->get_total_usage();
|
||||
return 0xFFFFFFFFFFFFF;
|
||||
|
||||
}
|
||||
|
||||
void Memory::dump_static_mem_to_file(const char* p_file) {
|
||||
|
||||
MemoryPoolStatic::get_singleton()->dump_mem_to_file(p_file);
|
||||
size_t Memory::get_mem_usage(){
|
||||
#ifdef DEBUG_ENABLED
|
||||
return mem_usage;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
size_t Memory::get_mem_max_usage(){
|
||||
#ifdef DEBUG_ENABLED
|
||||
return max_usage;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
MID Memory::alloc_dynamic(size_t p_bytes, const char *p_descr) {
|
||||
|
||||
|
135
core/os/memory.h
135
core/os/memory.h
@ -32,13 +32,18 @@
|
||||
#include <stddef.h>
|
||||
#include "safe_refcount.h"
|
||||
#include "os/memory_pool_dynamic.h"
|
||||
#include "os/memory_pool_static.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef PAD_ALIGN
|
||||
#define PAD_ALIGN 16 //must always be greater than this at much
|
||||
#endif
|
||||
|
||||
|
||||
class MID {
|
||||
|
||||
struct Data {
|
||||
@ -49,19 +54,7 @@ class MID {
|
||||
|
||||
mutable Data *data;
|
||||
|
||||
void unref() {
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
if (data->refcount.unref()) {
|
||||
|
||||
if (data->id!=MemoryPoolDynamic::INVALID_ID)
|
||||
MemoryPoolDynamic::get_singleton()->free(data->id);
|
||||
MemoryPoolStatic::get_singleton()->free(data);
|
||||
}
|
||||
|
||||
data=NULL;
|
||||
}
|
||||
|
||||
void ref(Data *p_data) {
|
||||
|
||||
@ -95,49 +88,13 @@ friend class MID_Lock;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Error _resize(size_t p_size) {
|
||||
|
||||
if (p_size==0 && (!data || data->id==MemoryPoolDynamic::INVALID_ID))
|
||||
return OK;
|
||||
if (p_size && !data) {
|
||||
// create data because we'll need it
|
||||
data = (Data*)MemoryPoolStatic::get_singleton()->alloc(sizeof(Data),"MID::Data");
|
||||
ERR_FAIL_COND_V( !data,ERR_OUT_OF_MEMORY );
|
||||
data->refcount.init();
|
||||
data->id=MemoryPoolDynamic::INVALID_ID;
|
||||
}
|
||||
void unref();
|
||||
Error _resize(size_t p_size);
|
||||
|
||||
if (p_size==0 && data && data->id==MemoryPoolDynamic::INVALID_ID) {
|
||||
|
||||
MemoryPoolDynamic::get_singleton()->free(data->id);
|
||||
data->id=MemoryPoolDynamic::INVALID_ID;
|
||||
}
|
||||
|
||||
if (p_size>0) {
|
||||
|
||||
if (data->id==MemoryPoolDynamic::INVALID_ID) {
|
||||
|
||||
data->id=MemoryPoolDynamic::get_singleton()->alloc(p_size,"Unnamed MID");
|
||||
ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
|
||||
|
||||
} else {
|
||||
|
||||
MemoryPoolDynamic::get_singleton()->realloc(data->id,p_size);
|
||||
ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
friend class Memory;
|
||||
|
||||
MID(MemoryPoolDynamic::ID p_id) {
|
||||
|
||||
data = (Data*)MemoryPoolStatic::get_singleton()->alloc(sizeof(Data),"MID::Data");
|
||||
data->refcount.init();
|
||||
data->id=p_id;
|
||||
}
|
||||
MID(MemoryPoolDynamic::ID p_id);
|
||||
public:
|
||||
|
||||
bool is_valid() const { return data; }
|
||||
@ -173,15 +130,23 @@ public:
|
||||
class Memory{
|
||||
|
||||
Memory();
|
||||
#ifdef DEBUG_ENABLED
|
||||
static size_t mem_usage;
|
||||
static size_t max_usage;
|
||||
#endif
|
||||
|
||||
static size_t alloc_count;
|
||||
|
||||
public:
|
||||
|
||||
static void * alloc_static(size_t p_bytes,const char *p_descr="");
|
||||
static void * realloc_static(void *p_memory,size_t p_bytes);
|
||||
static void free_static(void *p_ptr);
|
||||
static size_t get_static_mem_available();
|
||||
static size_t get_static_mem_usage();
|
||||
static size_t get_static_mem_max_usage();
|
||||
static void dump_static_mem_to_file(const char* p_file);
|
||||
static void * alloc_static(size_t p_bytes,bool p_pad_align=false);
|
||||
static void * realloc_static(void *p_memory,size_t p_bytes,bool p_pad_align=false);
|
||||
static void free_static(void *p_ptr,bool p_pad_align=false);
|
||||
|
||||
static size_t get_mem_available();
|
||||
static size_t get_mem_usage();
|
||||
static size_t get_mem_max_usage();
|
||||
|
||||
|
||||
static MID alloc_dynamic(size_t p_bytes, const char *p_descr="");
|
||||
static Error realloc_dynamic(MID p_mid,size_t p_bytes);
|
||||
@ -191,15 +156,10 @@ public:
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct MemAalign {
|
||||
static _FORCE_INLINE_ int get_align() { return DEFAULT_ALIGNMENT; }
|
||||
};
|
||||
|
||||
class DefaultAllocator {
|
||||
public:
|
||||
_FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory, ""); }
|
||||
_FORCE_INLINE_ static void free(void *p_ptr) { return Memory::free_static(p_ptr); }
|
||||
_FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory, false); }
|
||||
_FORCE_INLINE_ static void free(void *p_ptr) { return Memory::free_static(p_ptr,false); }
|
||||
|
||||
};
|
||||
|
||||
@ -209,19 +169,10 @@ void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size)); ///< ope
|
||||
|
||||
void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
#define memalloc(m_size) Memory::alloc_static(m_size, __FILE__ ":" __STR(__LINE__) ", memalloc.")
|
||||
#define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size)
|
||||
#define memfree(m_size) Memory::free_static(m_size)
|
||||
|
||||
#else
|
||||
|
||||
#define memalloc(m_size) Memory::alloc_static(m_size)
|
||||
#define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size)
|
||||
#define memfree(m_size) Memory::free_static(m_size)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
#define dynalloc(m_size) Memory::alloc_dynamic(m_size, __FILE__ ":" __STR(__LINE__) ", type: DYNAMIC")
|
||||
@ -245,16 +196,8 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
|
||||
return p_obj;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
#define memnew(m_class) _post_initialize(new(__FILE__ ":" __STR(__LINE__) ", memnew type: " __STR(m_class)) m_class)
|
||||
|
||||
#else
|
||||
|
||||
#define memnew(m_class) _post_initialize(new("") m_class)
|
||||
|
||||
#endif
|
||||
|
||||
_ALWAYS_INLINE_ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description) {
|
||||
// void *failptr=0;
|
||||
// ERR_FAIL_COND_V( check < p_size , failptr); /** bug, or strange compiler, most likely */
|
||||
@ -275,7 +218,7 @@ void memdelete(T *p_class) {
|
||||
if (!predelete_handler(p_class))
|
||||
return; // doesn't want to be deleted
|
||||
p_class->~T();
|
||||
Memory::free_static(p_class);
|
||||
Memory::free_static(p_class,false);
|
||||
}
|
||||
|
||||
template<class T,class A>
|
||||
@ -288,15 +231,9 @@ void memdelete_allocator(T *p_class) {
|
||||
}
|
||||
|
||||
#define memdelete_notnull(m_v) { if (m_v) memdelete(m_v); }
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
#define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count,__FILE__ ":" __STR(__LINE__) ", memnew_arr type: " _STR(m_class))
|
||||
|
||||
#else
|
||||
|
||||
#define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count)
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
|
||||
@ -307,11 +244,11 @@ T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
|
||||
same strategy used by std::vector, and the DVector class, so it should be safe.*/
|
||||
|
||||
size_t len = sizeof(T) * p_elements;
|
||||
unsigned int *mem = (unsigned int*)Memory::alloc_static( len + MAX(sizeof(size_t), DEFAULT_ALIGNMENT), p_descr );
|
||||
uint64_t *mem = (uint64_t*)Memory::alloc_static( len , true );
|
||||
T *failptr=0; //get rid of a warning
|
||||
ERR_FAIL_COND_V( !mem, failptr );
|
||||
*mem=p_elements;
|
||||
mem = (unsigned int *)( ((uint8_t*)mem) + MAX(sizeof(size_t), DEFAULT_ALIGNMENT));
|
||||
*(mem-1)=p_elements;
|
||||
|
||||
T* elems = (T*)mem;
|
||||
|
||||
/* call operator new */
|
||||
@ -330,20 +267,22 @@ T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
|
||||
template<typename T>
|
||||
size_t memarr_len(const T *p_class) {
|
||||
|
||||
uint8_t* ptr = ((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT);
|
||||
return *(size_t*)ptr;
|
||||
uint64_t* ptr = (uint64_t*)p_class;
|
||||
return *(ptr-1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void memdelete_arr(T *p_class) {
|
||||
|
||||
unsigned int * elems = (unsigned int*)(((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT));
|
||||
uint64_t* ptr = (uint64_t*)p_class;
|
||||
|
||||
for (unsigned int i=0;i<*elems;i++) {
|
||||
uint64_t elem_count = *(ptr-1);
|
||||
|
||||
for (uint64_t i=0;i<elem_count;i++) {
|
||||
|
||||
p_class[i].~T();
|
||||
};
|
||||
Memory::free_static(elems);
|
||||
Memory::free_static(ptr,true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -221,7 +221,7 @@ Error MemoryPoolDynamicStatic::unlock(ID p_id) {
|
||||
|
||||
size_t MemoryPoolDynamicStatic::get_available_mem() const {
|
||||
|
||||
return Memory::get_static_mem_available();
|
||||
return Memory::get_mem_available();
|
||||
}
|
||||
|
||||
size_t MemoryPoolDynamicStatic::get_total_usage() const {
|
||||
|
@ -5,7 +5,7 @@
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
|
@ -1,49 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* memory_pool_static.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "memory_pool_static.h"
|
||||
|
||||
MemoryPoolStatic *MemoryPoolStatic::singleton=0;
|
||||
|
||||
MemoryPoolStatic *MemoryPoolStatic::get_singleton() {
|
||||
|
||||
return singleton;
|
||||
}
|
||||
|
||||
|
||||
MemoryPoolStatic::MemoryPoolStatic() {
|
||||
|
||||
singleton=this;
|
||||
}
|
||||
|
||||
|
||||
MemoryPoolStatic::~MemoryPoolStatic() {
|
||||
singleton=NULL;
|
||||
}
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* memory_pool_static.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef MEMORY_POOL_STATIC_H
|
||||
#define MEMORY_POOL_STATIC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "core/typedefs.h"
|
||||
|
||||
/**
|
||||
@author Juan Linietsky <red@lunatea>
|
||||
*/
|
||||
class MemoryPoolStatic {
|
||||
private:
|
||||
|
||||
static MemoryPoolStatic *singleton;
|
||||
|
||||
public:
|
||||
|
||||
static MemoryPoolStatic *get_singleton();
|
||||
|
||||
virtual void* alloc(size_t p_bytes,const char *p_description)=0; ///< Pointer in p_description shold be to a const char const like "hello"
|
||||
virtual void* realloc(void * p_memory,size_t p_bytes)=0; ///< Pointer in p_description shold be to a const char const like "hello"
|
||||
virtual void free(void *p_ptr)=0; ///< Pointer in p_description shold be to a const char const
|
||||
|
||||
virtual size_t get_available_mem() const=0;
|
||||
virtual size_t get_total_usage()=0;
|
||||
virtual size_t get_max_usage()=0;
|
||||
|
||||
/* Most likely available only if memory debugger was compiled in */
|
||||
virtual int get_alloc_count()=0;
|
||||
virtual void * get_alloc_ptr(int p_alloc_idx)=0;
|
||||
virtual const char* get_alloc_description(int p_alloc_idx)=0;
|
||||
virtual size_t get_alloc_size(int p_alloc_idx)=0;
|
||||
|
||||
virtual void dump_mem_to_file(const char* p_file)=0;
|
||||
|
||||
MemoryPoolStatic();
|
||||
virtual ~MemoryPoolStatic();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -187,7 +187,7 @@ const char *OS::get_last_error() const {
|
||||
|
||||
void OS::dump_memory_to_file(const char* p_file) {
|
||||
|
||||
Memory::dump_static_mem_to_file(p_file);
|
||||
// Memory::dump_static_mem_to_file(p_file);
|
||||
}
|
||||
|
||||
static FileAccess *_OSPRF=NULL;
|
||||
@ -367,7 +367,7 @@ Error OS::dialog_input_text(String p_title, String p_description, String p_parti
|
||||
|
||||
int OS::get_static_memory_usage() const {
|
||||
|
||||
return Memory::get_static_mem_usage();
|
||||
return Memory::get_mem_usage();
|
||||
}
|
||||
int OS::get_dynamic_memory_usage() const{
|
||||
|
||||
@ -376,7 +376,7 @@ int OS::get_dynamic_memory_usage() const{
|
||||
|
||||
int OS::get_static_memory_peak_usage() const {
|
||||
|
||||
return Memory::get_static_mem_max_usage();
|
||||
return Memory::get_mem_max_usage();
|
||||
}
|
||||
|
||||
Error OS::set_cwd(const String& p_cwd) {
|
||||
@ -392,7 +392,7 @@ bool OS::has_touchscreen_ui_hint() const {
|
||||
|
||||
int OS::get_free_static_memory() const {
|
||||
|
||||
return Memory::get_static_mem_available();
|
||||
return Memory::get_mem_available();
|
||||
}
|
||||
|
||||
void OS::yield() {
|
||||
|
@ -604,7 +604,7 @@ void PoolAllocator::create_pool(void * p_mem,int p_size,int p_max_entries) {
|
||||
|
||||
PoolAllocator::PoolAllocator(int p_size,bool p_needs_locking,int p_max_entries) {
|
||||
|
||||
mem_ptr=Memory::alloc_static( p_size,"PoolAllocator()");
|
||||
mem_ptr=memalloc( p_size);
|
||||
ERR_FAIL_COND(!mem_ptr);
|
||||
align=1;
|
||||
create_pool(mem_ptr,p_size,p_max_entries);
|
||||
@ -648,7 +648,7 @@ PoolAllocator::PoolAllocator(int p_align,int p_size,bool p_needs_locking,int p_m
|
||||
PoolAllocator::~PoolAllocator() {
|
||||
|
||||
if (mem_ptr)
|
||||
Memory::free_static( mem_ptr );
|
||||
memfree( mem_ptr );
|
||||
|
||||
memdelete_arr( entry_array );
|
||||
memdelete_arr( entry_indices );
|
||||
|
@ -29,27 +29,76 @@
|
||||
#include "safe_refcount.h"
|
||||
|
||||
|
||||
// Atomic functions, these are used for multithread safe reference counters!
|
||||
|
||||
#ifdef NO_THREADS
|
||||
|
||||
|
||||
uint32_t atomic_conditional_increment( register uint32_t * pw ) {
|
||||
|
||||
if (*pw==0)
|
||||
return 0;
|
||||
|
||||
(*pw)++;
|
||||
|
||||
return *pw;
|
||||
}
|
||||
|
||||
uint32_t atomic_decrement( register uint32_t * pw ) {
|
||||
|
||||
(*pw)--;
|
||||
|
||||
return *pw;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
// don't pollute my namespace!
|
||||
#include <windows.h>
|
||||
long atomic_conditional_increment( register long * pw ) {
|
||||
uint32_t atomic_conditional_increment( register uint32_t * pw ) {
|
||||
|
||||
/* try to increment until it actually works */
|
||||
// taken from boost
|
||||
|
||||
while (true) {
|
||||
long tmp = static_cast< long const volatile& >( *pw );
|
||||
uint32_t tmp = static_cast< uint32_t const volatile& >( *pw );
|
||||
if( tmp == 0 )
|
||||
return 0; // if zero, can't add to it anymore
|
||||
if( InterlockedCompareExchange( pw, tmp + 1, tmp ) == tmp )
|
||||
return 0; // if zero, can't add to it anymore
|
||||
if( InterlockedCompareExchange( (LONG volatile*)pw, tmp + 1, tmp ) == tmp )
|
||||
return tmp+1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t atomic_decrement( register uint32_t * pw ) {
|
||||
return InterlockedDecrement( (LONG volatile*)pw );
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
uint32_t atomic_conditional_increment( register uint32_t * pw ) {
|
||||
|
||||
while (true) {
|
||||
uint32_t tmp = static_cast< uint32_t const volatile& >( *pw );
|
||||
if( tmp == 0 )
|
||||
return 0; // if zero, can't add to it anymore
|
||||
if( __sync_val_compare_and_swap( pw, tmp, tmp + 1 ) == tmp )
|
||||
return tmp+1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t atomic_decrement( register uint32_t * pw ) {
|
||||
|
||||
return __sync_sub_and_fetch(pw,1);
|
||||
|
||||
}
|
||||
|
||||
long atomic_decrement( register long * pw ) {
|
||||
return InterlockedDecrement( pw );
|
||||
}
|
||||
#else
|
||||
//no threads supported?
|
||||
#error Must provide atomic functions for this platform or compiler!
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -33,309 +33,17 @@
|
||||
/* x86/x86_64 GCC */
|
||||
|
||||
#include "platform_config.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
|
||||
#ifdef NO_THREADS
|
||||
|
||||
struct SafeRefCount {
|
||||
|
||||
int count;
|
||||
|
||||
public:
|
||||
|
||||
// destroy() is called when weak_count_ drops to zero.
|
||||
|
||||
bool ref() { //true on success
|
||||
|
||||
if (count==0)
|
||||
return false;
|
||||
count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int refval() { //true on success
|
||||
|
||||
if (count==0)
|
||||
return 0;
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
bool unref() { // true if must be disposed of
|
||||
|
||||
if (count>0)
|
||||
count--;
|
||||
|
||||
return count==0;
|
||||
}
|
||||
|
||||
long get() const { // nothrow
|
||||
|
||||
return static_cast<int const volatile &>( count );
|
||||
}
|
||||
|
||||
void init(int p_value=1) {
|
||||
|
||||
count=p_value;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#if defined( PLATFORM_REFCOUNT )
|
||||
|
||||
#include "platform_refcount.h"
|
||||
|
||||
|
||||
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
|
||||
|
||||
#define REFCOUNT_T volatile int
|
||||
#define REFCOUNT_GET_T int const volatile&
|
||||
|
||||
static inline int atomic_conditional_increment( volatile int * pw ) {
|
||||
// int rv = *pw;
|
||||
// if( rv != 0 ) ++*pw;
|
||||
// return rv;
|
||||
|
||||
int rv, tmp;
|
||||
|
||||
__asm__
|
||||
(
|
||||
"movl %0, %%eax\n\t"
|
||||
"0:\n\t"
|
||||
"test %%eax, %%eax\n\t"
|
||||
"je 1f\n\t"
|
||||
"movl %%eax, %2\n\t"
|
||||
"incl %2\n\t"
|
||||
"lock\n\t"
|
||||
"cmpxchgl %2, %0\n\t"
|
||||
"jne 0b\n\t"
|
||||
"1:":
|
||||
"=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
|
||||
"m"( *pw ): // input (%3)
|
||||
"cc" // clobbers
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline int atomic_decrement( volatile int *pw) {
|
||||
|
||||
// return --(*pw);
|
||||
|
||||
unsigned char rv;
|
||||
|
||||
__asm__
|
||||
(
|
||||
"lock\n\t"
|
||||
"decl %0\n\t"
|
||||
"setne %1":
|
||||
"=m" (*pw), "=qm" (rv):
|
||||
"m" (*pw):
|
||||
"memory"
|
||||
);
|
||||
return static_cast<int>(rv);
|
||||
}
|
||||
|
||||
/* PowerPC32/64 GCC */
|
||||
|
||||
#elif ( defined( __GNUC__ ) ) && ( defined( __powerpc__ ) || defined( __ppc__ ) )
|
||||
|
||||
#define REFCOUNT_T int
|
||||
#define REFCOUNT_GET_T int const volatile&
|
||||
|
||||
inline int atomic_conditional_increment( int * pw )
|
||||
{
|
||||
// if( *pw != 0 ) ++*pw;
|
||||
// return *pw;
|
||||
|
||||
int rv;
|
||||
|
||||
__asm__
|
||||
(
|
||||
"0:\n\t"
|
||||
"lwarx %1, 0, %2\n\t"
|
||||
"cmpwi %1, 0\n\t"
|
||||
"beq 1f\n\t"
|
||||
"addi %1, %1, 1\n\t"
|
||||
"1:\n\t"
|
||||
"stwcx. %1, 0, %2\n\t"
|
||||
"bne- 0b":
|
||||
|
||||
"=m"( *pw ), "=&b"( rv ):
|
||||
"r"( pw ), "m"( *pw ):
|
||||
"cc"
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
inline int atomic_decrement( int * pw )
|
||||
{
|
||||
// return --*pw;
|
||||
|
||||
int rv;
|
||||
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"sync\n\t"
|
||||
"0:\n\t"
|
||||
"lwarx %1, 0, %2\n\t"
|
||||
"addi %1, %1, -1\n\t"
|
||||
"stwcx. %1, 0, %2\n\t"
|
||||
"bne- 0b\n\t"
|
||||
"isync":
|
||||
|
||||
"=m"( *pw ), "=&b"( rv ):
|
||||
"r"( pw ), "m"( *pw ):
|
||||
"memory", "cc"
|
||||
);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* CW ARM */
|
||||
|
||||
#elif defined( __GNUC__ ) && ( defined( __arm__ ) )
|
||||
|
||||
#define REFCOUNT_T int
|
||||
#define REFCOUNT_GET_T int const volatile&
|
||||
|
||||
inline int atomic_conditional_increment(volatile int* v)
|
||||
{
|
||||
int t;
|
||||
int tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldrex %0, [%2] \n"
|
||||
" cmp %0, #0 \n"
|
||||
" beq 2f \n"
|
||||
" add %0, %0, #1 \n"
|
||||
"2: \n"
|
||||
" strex %1, %0, [%2] \n"
|
||||
" cmp %1, #0 \n"
|
||||
" bne 1b \n"
|
||||
|
||||
: "=&r" (t), "=&r" (tmp)
|
||||
: "r" (v)
|
||||
: "cc", "memory");
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
inline int atomic_decrement(volatile int* v)
|
||||
{
|
||||
int t;
|
||||
int tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldrex %0, [%2] \n"
|
||||
" add %0, %0, #-1 \n"
|
||||
" strex %1, %0, [%2] \n"
|
||||
" cmp %1, #0 \n"
|
||||
" bne 1b \n"
|
||||
|
||||
: "=&r" (t), "=&r" (tmp)
|
||||
: "r" (v)
|
||||
: "cc", "memory");
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* CW PPC */
|
||||
|
||||
#elif ( defined( __MWERKS__ ) ) && defined( __POWERPC__ )
|
||||
|
||||
inline long atomic_conditional_increment( register long * pw )
|
||||
{
|
||||
register int a;
|
||||
|
||||
asm
|
||||
{
|
||||
loop:
|
||||
|
||||
lwarx a, 0, pw
|
||||
cmpwi a, 0
|
||||
beq store
|
||||
|
||||
addi a, a, 1
|
||||
|
||||
store:
|
||||
|
||||
stwcx. a, 0, pw
|
||||
bne- loop
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
inline long atomic_decrement( register long * pw )
|
||||
{
|
||||
register int a;
|
||||
|
||||
asm {
|
||||
|
||||
sync
|
||||
|
||||
loop:
|
||||
|
||||
lwarx a, 0, pw
|
||||
addi a, a, -1
|
||||
stwcx. a, 0, pw
|
||||
bne- loop
|
||||
|
||||
isync
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Any Windows (MSVC) */
|
||||
|
||||
#elif defined( _MSC_VER )
|
||||
|
||||
// made functions to not pollute namespace..
|
||||
|
||||
#define REFCOUNT_T long
|
||||
#define REFCOUNT_GET_T long const volatile&
|
||||
|
||||
long atomic_conditional_increment( register long * pw );
|
||||
long atomic_decrement( register long * pw );
|
||||
|
||||
#if 0
|
||||
#elif defined( __GNUC__ ) && defined( ARMV6_ENABLED)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#error This platform cannot use safe refcount, compile with NO_THREADS or implement it.
|
||||
|
||||
#endif
|
||||
uint32_t atomic_conditional_increment( register uint32_t * counter );
|
||||
uint32_t atomic_decrement( register uint32_t * pw );
|
||||
|
||||
|
||||
|
||||
struct SafeRefCount {
|
||||
|
||||
REFCOUNT_T count;
|
||||
uint32_t count;
|
||||
|
||||
public:
|
||||
|
||||
@ -346,7 +54,7 @@ public:
|
||||
return atomic_conditional_increment( &count ) != 0;
|
||||
}
|
||||
|
||||
int refval() { //true on success
|
||||
uint32_t refval() { //true on success
|
||||
|
||||
return atomic_conditional_increment( &count );
|
||||
}
|
||||
@ -360,20 +68,18 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
long get() const { // nothrow
|
||||
uint32_t get() const { // nothrow
|
||||
|
||||
return static_cast<REFCOUNT_GET_T>( count );
|
||||
return count;
|
||||
}
|
||||
|
||||
void init(int p_value=1) {
|
||||
void init(uint32_t p_value=1) {
|
||||
|
||||
count=p_value;
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // no thread safe
|
||||
|
||||
#endif
|
||||
|
@ -77,10 +77,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_ALIGNMENT
|
||||
#define DEFAULT_ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
|
||||
//custom, gcc-safe offsetof, because gcc complains a lot.
|
||||
template<class T>
|
||||
|
@ -46,19 +46,20 @@ class Vector {
|
||||
|
||||
// internal helpers
|
||||
|
||||
_FORCE_INLINE_ SafeRefCount* _get_refcount() const {
|
||||
_FORCE_INLINE_ uint32_t* _get_refcount() const {
|
||||
|
||||
if (!_ptr)
|
||||
return NULL;
|
||||
|
||||
return reinterpret_cast<SafeRefCount*>((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount));
|
||||
return reinterpret_cast<uint32_t*>(_ptr)-2;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ int* _get_size() const {
|
||||
_FORCE_INLINE_ uint32_t* _get_size() const {
|
||||
|
||||
if (!_ptr)
|
||||
return NULL;
|
||||
return reinterpret_cast<int*>((uint8_t*)_ptr-sizeof(int));
|
||||
return NULL;
|
||||
|
||||
return reinterpret_cast<uint32_t*>(_ptr)-1;
|
||||
|
||||
}
|
||||
_FORCE_INLINE_ T* _get_data() const {
|
||||
@ -71,7 +72,7 @@ class Vector {
|
||||
|
||||
_FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
|
||||
//return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
|
||||
return nearest_power_of_2(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
|
||||
return nearest_power_of_2(p_elements*sizeof(T));
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
|
||||
@ -79,8 +80,8 @@ class Vector {
|
||||
size_t o;
|
||||
size_t p;
|
||||
if (_mul_overflow(p_elements, sizeof(T), &o)) return false;
|
||||
if (_add_overflow(o, sizeof(SafeRefCount)+sizeof(int), &p)) return false;
|
||||
*out = nearest_power_of_2(p);
|
||||
*out = nearest_power_of_2(o);
|
||||
if (_add_overflow(o, 32, &p)) return false; //no longer allocated here
|
||||
return true;
|
||||
#else
|
||||
// Speed is more important than correctness here, do the operations unchecked
|
||||
@ -104,7 +105,7 @@ public:
|
||||
_FORCE_INLINE_ void clear() { resize(0); }
|
||||
|
||||
_FORCE_INLINE_ int size() const {
|
||||
int* size = _get_size();
|
||||
uint32_t* size = (uint32_t*)_get_size();
|
||||
if (size)
|
||||
return *size;
|
||||
else
|
||||
@ -190,22 +191,22 @@ void Vector<T>::_unref(void *p_data) {
|
||||
if (!p_data)
|
||||
return;
|
||||
|
||||
SafeRefCount *src = reinterpret_cast<SafeRefCount*>((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount));
|
||||
uint32_t *refc = _get_refcount();
|
||||
|
||||
if (!src->unref())
|
||||
if (atomic_decrement(refc)>0)
|
||||
return; // still in use
|
||||
// clean up
|
||||
|
||||
int *count = (int*)(src+1);
|
||||
uint32_t *count = _get_size();
|
||||
T *data = (T*)(count+1);
|
||||
|
||||
for (int i=0;i<*count;i++) {
|
||||
for (uint32_t i=0;i<*count;i++) {
|
||||
// call destructors
|
||||
data[i].~T();
|
||||
}
|
||||
|
||||
// free mem
|
||||
memfree((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount));
|
||||
Memory::free_static((uint8_t*)p_data,true);
|
||||
|
||||
}
|
||||
|
||||
@ -215,18 +216,22 @@ void Vector<T>::_copy_on_write() {
|
||||
if (!_ptr)
|
||||
return;
|
||||
|
||||
if (_get_refcount()->get() > 1 ) {
|
||||
/* in use by more than me */
|
||||
void* mem_new = memalloc(_get_alloc_size(*_get_size()));
|
||||
SafeRefCount *src_new=(SafeRefCount *)mem_new;
|
||||
src_new->init();
|
||||
int * _size = (int*)(src_new+1);
|
||||
*_size=*_get_size();
|
||||
uint32_t *refc = _get_refcount();
|
||||
|
||||
T*_data=(T*)(_size+1);
|
||||
if (*refc > 1) {
|
||||
/* in use by more than me */
|
||||
uint32_t current_size = *_get_size();
|
||||
|
||||
uint32_t* mem_new = (uint32_t*)Memory::alloc_static(_get_alloc_size(current_size),true);
|
||||
|
||||
|
||||
*(mem_new-2)=1; //refcount
|
||||
*(mem_new-1)=current_size; //size
|
||||
|
||||
T*_data=(T*)(mem_new);
|
||||
|
||||
// initialize new elements
|
||||
for (int i=0;i<*_size;i++) {
|
||||
for (uint32_t i=0;i<current_size;i++) {
|
||||
|
||||
memnew_placement(&_data[i], T( _get_data()[i] ) );
|
||||
}
|
||||
@ -280,16 +285,17 @@ Error Vector<T>::resize(int p_size) {
|
||||
|
||||
if (size()==0) {
|
||||
// alloc from scratch
|
||||
void* ptr=memalloc(alloc_size);
|
||||
uint32_t *ptr=(uint32_t*)Memory::alloc_static(alloc_size,true);
|
||||
ERR_FAIL_COND_V( !ptr ,ERR_OUT_OF_MEMORY);
|
||||
_ptr=(T*)((uint8_t*)ptr+sizeof(int)+sizeof(SafeRefCount));
|
||||
_get_refcount()->init(); // init refcount
|
||||
*_get_size()=0; // init size (currently, none)
|
||||
*(ptr-1)=0; //size, currently none
|
||||
*(ptr-2)=1; //refcount
|
||||
|
||||
_ptr=(T*)ptr;
|
||||
|
||||
} else {
|
||||
void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size);
|
||||
void *_ptrnew = (T*)Memory::realloc_static(_ptr, alloc_size,true);
|
||||
ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
|
||||
_ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
|
||||
_ptr=(T*)(_ptrnew);
|
||||
}
|
||||
|
||||
// construct the newly created elements
|
||||
@ -305,16 +311,16 @@ Error Vector<T>::resize(int p_size) {
|
||||
} else if (p_size<size()) {
|
||||
|
||||
// deinitialize no longer needed elements
|
||||
for (int i=p_size;i<*_get_size();i++) {
|
||||
for (uint32_t i=p_size;i<*_get_size();i++) {
|
||||
|
||||
T* t = &_get_data()[i];
|
||||
t->~T();
|
||||
}
|
||||
|
||||
void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size);
|
||||
void *_ptrnew = (T*)Memory::realloc_static(_ptr, alloc_size,true);
|
||||
ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
|
||||
|
||||
_ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
|
||||
_ptr=(T*)(_ptrnew);
|
||||
|
||||
*_get_size()=p_size;
|
||||
|
||||
@ -382,8 +388,9 @@ void Vector<T>::_copy_from(const Vector& p_from) {
|
||||
if (!p_from._ptr)
|
||||
return; //nothing to do
|
||||
|
||||
if (p_from._get_refcount()->ref()) // could reference
|
||||
if (atomic_conditional_increment(p_from._get_refcount())>0) { // could reference
|
||||
_ptr=p_from._ptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
|
||||
}
|
||||
|
||||
|
||||
char *ilogmem = (char*)Memory::alloc_static(iloglen+1);
|
||||
char *ilogmem = (char*)memalloc(iloglen+1);
|
||||
ilogmem[iloglen]=0;
|
||||
glGetShaderInfoLog(v.vert_id, iloglen, &iloglen, ilogmem);
|
||||
|
||||
@ -378,7 +378,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
|
||||
|
||||
err_string+=ilogmem;
|
||||
_display_error_with_code(err_string,strings);
|
||||
Memory::free_static(ilogmem);
|
||||
memfree(ilogmem);
|
||||
glDeleteShader(v.vert_id);
|
||||
glDeleteProgram( v.id );
|
||||
v.id=0;
|
||||
@ -473,7 +473,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
|
||||
iloglen = 4096; //buggy driver (Adreno 220+....)
|
||||
}
|
||||
|
||||
char *ilogmem = (char*)Memory::alloc_static(iloglen+1);
|
||||
char *ilogmem = (char*)memalloc(iloglen+1);
|
||||
ilogmem[iloglen]=0;
|
||||
glGetShaderInfoLog(v.frag_id, iloglen, &iloglen, ilogmem);
|
||||
|
||||
@ -482,7 +482,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
|
||||
err_string+=ilogmem;
|
||||
_display_error_with_code(err_string,strings);
|
||||
ERR_PRINT(err_string.ascii().get_data());
|
||||
Memory::free_static(ilogmem);
|
||||
memfree(ilogmem);
|
||||
glDeleteShader(v.frag_id);
|
||||
glDeleteShader(v.vert_id);
|
||||
glDeleteProgram( v.id );
|
||||
|
@ -1,434 +1,2 @@
|
||||
/*************************************************************************/
|
||||
/* memory_pool_static_malloc.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "memory_pool_static_malloc.h"
|
||||
#include "error_macros.h"
|
||||
#include "os/memory.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "os/copymem.h"
|
||||
#include "os/os.h"
|
||||
|
||||
/**
|
||||
* NOTE NOTE NOTE NOTE
|
||||
* in debug mode, this prepends the memory size to the allocated block
|
||||
* so BE CAREFUL!
|
||||
*/
|
||||
|
||||
void* MemoryPoolStaticMalloc::alloc(size_t p_bytes,const char *p_description) {
|
||||
|
||||
#if DEFAULT_ALIGNMENT == 1
|
||||
|
||||
return _alloc(p_bytes, p_description);
|
||||
|
||||
#else
|
||||
|
||||
size_t total;
|
||||
#if defined(_add_overflow)
|
||||
if (_add_overflow(p_bytes, DEFAULT_ALIGNMENT, &total)) return NULL;
|
||||
#else
|
||||
total = p_bytes + DEFAULT_ALIGNMENT;
|
||||
#endif
|
||||
uint8_t* ptr = (uint8_t*)_alloc(total, p_description);
|
||||
ERR_FAIL_COND_V( !ptr, ptr );
|
||||
int ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
|
||||
ptr[ofs-1] = ofs;
|
||||
return (void*)(ptr + ofs);
|
||||
#endif
|
||||
};
|
||||
|
||||
void* MemoryPoolStaticMalloc::_alloc(size_t p_bytes,const char *p_description) {
|
||||
|
||||
ERR_FAIL_COND_V(p_bytes==0,0);
|
||||
|
||||
MutexLock lock(mutex);
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
size_t total;
|
||||
#if defined(_add_overflow)
|
||||
if (_add_overflow(p_bytes, sizeof(RingPtr), &total)) return NULL;
|
||||
#else
|
||||
total = p_bytes + sizeof(RingPtr);
|
||||
#endif
|
||||
void *mem=malloc(total); /// add for size and ringlist
|
||||
|
||||
if (!mem) {
|
||||
printf("**ERROR: out of memory while allocating %lu bytes by %s?\n", (unsigned long) p_bytes, p_description);
|
||||
printf("**ERROR: memory usage is %lu\n", (unsigned long) get_total_usage());
|
||||
};
|
||||
|
||||
ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
|
||||
|
||||
/* setup the ringlist element */
|
||||
|
||||
RingPtr *ringptr = (RingPtr*)mem;
|
||||
|
||||
/* setup the ringlist element data (description and size ) */
|
||||
|
||||
ringptr->size = p_bytes;
|
||||
ringptr->descr=p_description;
|
||||
|
||||
if (ringlist) { /* existing ringlist */
|
||||
|
||||
/* assign next */
|
||||
ringptr->next = ringlist->next;
|
||||
ringlist->next = ringptr;
|
||||
/* assign prev */
|
||||
ringptr->prev = ringlist;
|
||||
ringptr->next->prev = ringptr;
|
||||
} else { /* non existing ringlist */
|
||||
|
||||
ringptr->next=ringptr;
|
||||
ringptr->prev=ringptr;
|
||||
ringlist=ringptr;
|
||||
|
||||
}
|
||||
|
||||
total_mem+=p_bytes;
|
||||
|
||||
/* update statistics */
|
||||
if (total_mem > max_mem )
|
||||
max_mem = total_mem;
|
||||
|
||||
total_pointers++;
|
||||
|
||||
if (total_pointers > max_pointers)
|
||||
max_pointers=total_pointers;
|
||||
|
||||
return ringptr + 1; /* return memory after ringptr */
|
||||
|
||||
#else
|
||||
void *mem=malloc(p_bytes);
|
||||
|
||||
ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
|
||||
return mem;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void* MemoryPoolStaticMalloc::realloc(void *p_memory,size_t p_bytes) {
|
||||
|
||||
#if DEFAULT_ALIGNMENT == 1
|
||||
|
||||
return _realloc(p_memory,p_bytes);
|
||||
#else
|
||||
if (!p_memory)
|
||||
return alloc(p_bytes);
|
||||
|
||||
size_t total;
|
||||
#if defined(_add_overflow)
|
||||
if (_add_overflow(p_bytes, DEFAULT_ALIGNMENT, &total)) return NULL;
|
||||
#else
|
||||
total = p_bytes + DEFAULT_ALIGNMENT;
|
||||
#endif
|
||||
uint8_t* mem = (uint8_t*)p_memory;
|
||||
int ofs = *(mem-1);
|
||||
mem = mem - ofs;
|
||||
uint8_t* ptr = (uint8_t*)_realloc(mem, total);
|
||||
ERR_FAIL_COND_V(ptr == NULL, NULL);
|
||||
int new_ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
|
||||
if (new_ofs != ofs) {
|
||||
|
||||
//printf("realloc moving %i bytes\n", p_bytes);
|
||||
movemem((ptr + new_ofs), (ptr + ofs), p_bytes);
|
||||
ptr[new_ofs-1] = new_ofs;
|
||||
};
|
||||
return ptr + new_ofs;
|
||||
#endif
|
||||
};
|
||||
|
||||
void* MemoryPoolStaticMalloc::_realloc(void *p_memory,size_t p_bytes) {
|
||||
|
||||
if (p_memory==NULL) {
|
||||
|
||||
return alloc( p_bytes );
|
||||
}
|
||||
|
||||
if (p_bytes==0) {
|
||||
|
||||
this->free(p_memory);
|
||||
ERR_FAIL_COND_V( p_bytes < 0 , NULL );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MutexLock lock(mutex);
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
|
||||
RingPtr *ringptr = (RingPtr*)p_memory;
|
||||
ringptr--; /* go back an element to find the tingptr */
|
||||
|
||||
bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr);
|
||||
bool is_list = ( ringlist == ringptr );
|
||||
|
||||
RingPtr *new_ringptr=(RingPtr*)::realloc(ringptr, p_bytes+sizeof(RingPtr));
|
||||
|
||||
ERR_FAIL_COND_V( new_ringptr == 0, NULL ); /// reallocation failed
|
||||
|
||||
/* actualize mem used */
|
||||
total_mem -= new_ringptr->size;
|
||||
new_ringptr->size = p_bytes;
|
||||
total_mem += new_ringptr->size;
|
||||
|
||||
if (total_mem > max_mem ) //update statistics
|
||||
max_mem = total_mem;
|
||||
|
||||
if (new_ringptr == ringptr )
|
||||
return ringptr + 1; // block didn't move, don't do anything
|
||||
|
||||
if (single_element) {
|
||||
|
||||
new_ringptr->next=new_ringptr;
|
||||
new_ringptr->prev=new_ringptr;
|
||||
} else {
|
||||
|
||||
new_ringptr->next->prev=new_ringptr;
|
||||
new_ringptr->prev->next=new_ringptr;
|
||||
}
|
||||
|
||||
if (is_list)
|
||||
ringlist=new_ringptr;
|
||||
|
||||
|
||||
return new_ringptr + 1;
|
||||
|
||||
#else
|
||||
return ::realloc( p_memory, p_bytes );
|
||||
#endif
|
||||
}
|
||||
|
||||
void MemoryPoolStaticMalloc::free(void *p_ptr) {
|
||||
|
||||
ERR_FAIL_COND( !MemoryPoolStatic::get_singleton());
|
||||
|
||||
#if DEFAULT_ALIGNMENT == 1
|
||||
|
||||
_free(p_ptr);
|
||||
#else
|
||||
|
||||
uint8_t* mem = (uint8_t*)p_ptr;
|
||||
int ofs = *(mem-1);
|
||||
mem = mem - ofs;
|
||||
|
||||
_free(mem);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void MemoryPoolStaticMalloc::_free(void *p_ptr) {
|
||||
|
||||
MutexLock lock(mutex);
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
if (p_ptr==0) {
|
||||
printf("**ERROR: STATIC ALLOC: Attempted free of NULL pointer.\n");
|
||||
return;
|
||||
};
|
||||
|
||||
RingPtr *ringptr = (RingPtr*)p_ptr;
|
||||
|
||||
ringptr--; /* go back an element to find the ringptr */
|
||||
|
||||
|
||||
#if 0
|
||||
{ // check for existing memory on free.
|
||||
RingPtr *p = ringlist;
|
||||
|
||||
bool found=false;
|
||||
|
||||
if (ringlist) {
|
||||
do {
|
||||
if (p==ringptr) {
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
|
||||
p=p->next;
|
||||
} while (p!=ringlist);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
printf("**ERROR: STATIC ALLOC: Attempted free of unknown pointer at %p\n",(ringptr+1));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
/* proceed to erase */
|
||||
|
||||
bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr);
|
||||
bool is_list = ( ringlist == ringptr );
|
||||
|
||||
if (single_element) {
|
||||
/* just get rid of it */
|
||||
ringlist=0;
|
||||
|
||||
} else {
|
||||
/* auto-remove from ringlist */
|
||||
if (is_list)
|
||||
ringlist=ringptr->next;
|
||||
|
||||
ringptr->prev->next = ringptr->next;
|
||||
ringptr->next->prev = ringptr->prev;
|
||||
}
|
||||
|
||||
total_mem -= ringptr->size;
|
||||
total_pointers--;
|
||||
// catch more errors
|
||||
zeromem(ringptr,sizeof(RingPtr)+ringptr->size);
|
||||
::free(ringptr); //just free that pointer
|
||||
|
||||
#else
|
||||
ERR_FAIL_COND(p_ptr==0);
|
||||
|
||||
::free(p_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
size_t MemoryPoolStaticMalloc::get_available_mem() const {
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
size_t MemoryPoolStaticMalloc::get_total_usage() {
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
return total_mem;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
size_t MemoryPoolStaticMalloc::get_max_usage() {
|
||||
|
||||
return max_mem;
|
||||
}
|
||||
|
||||
/* Most likely available only if memory debugger was compiled in */
|
||||
int MemoryPoolStaticMalloc::get_alloc_count() {
|
||||
|
||||
return total_pointers;
|
||||
}
|
||||
void * MemoryPoolStaticMalloc::get_alloc_ptr(int p_alloc_idx) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
const char* MemoryPoolStaticMalloc::get_alloc_description(int p_alloc_idx) {
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
size_t MemoryPoolStaticMalloc::get_alloc_size(int p_alloc_idx) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MemoryPoolStaticMalloc::dump_mem_to_file(const char* p_file) {
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */
|
||||
RingPtr *p = ringlist;
|
||||
FILE *f = fopen(p_file,"wb");
|
||||
|
||||
do {
|
||||
fprintf(f,"%p-%i-%s\n", p+1, (int)p->size, (p->descr?p->descr:"") );
|
||||
p=p->next;
|
||||
} while (p!=ringlist);
|
||||
|
||||
fclose(f);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
MemoryPoolStaticMalloc::MemoryPoolStaticMalloc() {
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
total_mem=0;
|
||||
total_pointers=0;
|
||||
ringlist=0;
|
||||
max_mem=0;
|
||||
max_pointers=0;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
mutex=NULL;
|
||||
#ifndef NO_THREADS
|
||||
|
||||
mutex=Mutex::create(); // at this point, this should work
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
MemoryPoolStaticMalloc::~MemoryPoolStaticMalloc() {
|
||||
|
||||
Mutex *old_mutex=mutex;
|
||||
mutex=NULL;
|
||||
if (old_mutex)
|
||||
memdelete(old_mutex);
|
||||
|
||||
#ifdef DEBUG_MEMORY_ENABLED
|
||||
|
||||
if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
if (total_mem > 0 ) {
|
||||
printf("**ERROR: STATIC ALLOC: ** MEMORY LEAKS DETECTED **\n");
|
||||
printf("**ERROR: STATIC ALLOC: %i bytes of memory in use at exit.\n",(int)total_mem);
|
||||
|
||||
if (1){
|
||||
printf("**ERROR: STATIC ALLOC: Following is the list of leaked allocations: \n");
|
||||
|
||||
ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */
|
||||
RingPtr *p = ringlist;
|
||||
|
||||
do {
|
||||
printf("\t%p - %i bytes - %s\n", (RingPtr*)(p+1), (int)p->size, (p->descr?p->descr:"") );
|
||||
p=p->next;
|
||||
} while (p!=ringlist);
|
||||
|
||||
printf("**ERROR: STATIC ALLOC: End of Report.\n");
|
||||
};
|
||||
|
||||
printf("mem - max %i, pointers %i, leaks %i.\n",(int)max_mem,max_pointers,(int)total_mem);
|
||||
} else {
|
||||
|
||||
printf("INFO: mem - max %i, pointers %i, no leaks.\n",(int)max_mem,max_pointers);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,82 +0,0 @@
|
||||
/*************************************************************************/
|
||||
/* memory_pool_static_malloc.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* http://www.godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#ifndef MEMORY_POOL_STATIC_MALLOC_H
|
||||
#define MEMORY_POOL_STATIC_MALLOC_H
|
||||
|
||||
#include "os/memory_pool_static.h"
|
||||
#include "os/mutex.h"
|
||||
/**
|
||||
@author Juan Linietsky <red@lunatea>
|
||||
*/
|
||||
class MemoryPoolStaticMalloc : public MemoryPoolStatic {
|
||||
|
||||
struct RingPtr {
|
||||
|
||||
size_t size;
|
||||
const char *descr; /* description of memory */
|
||||
RingPtr *next;
|
||||
RingPtr *prev;
|
||||
};
|
||||
|
||||
RingPtr *ringlist;
|
||||
size_t total_mem;
|
||||
int total_pointers;
|
||||
|
||||
size_t max_mem;
|
||||
int max_pointers;
|
||||
|
||||
Mutex *mutex;
|
||||
|
||||
void* _alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello"
|
||||
void* _realloc(void *p_memory,size_t p_bytes); ///< Pointer in
|
||||
void _free(void *p_ptr); ///< Pointer in p_description shold be to a const char const
|
||||
|
||||
public:
|
||||
|
||||
virtual void* alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello"
|
||||
virtual void free(void *p_ptr); ///< Pointer in p_description shold be to a const char const
|
||||
virtual void* realloc(void *p_memory,size_t p_bytes); ///< Pointer in
|
||||
virtual size_t get_available_mem() const;
|
||||
virtual size_t get_total_usage();
|
||||
virtual size_t get_max_usage();
|
||||
|
||||
/* Most likely available only if memory debugger was compiled in */
|
||||
virtual int get_alloc_count();
|
||||
virtual void * get_alloc_ptr(int p_alloc_idx);
|
||||
virtual const char* get_alloc_description(int p_alloc_idx);
|
||||
virtual size_t get_alloc_size(int p_alloc_idx);
|
||||
|
||||
void dump_mem_to_file(const char* p_file);
|
||||
|
||||
MemoryPoolStaticMalloc();
|
||||
~MemoryPoolStaticMalloc();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -30,7 +30,7 @@
|
||||
|
||||
#ifdef UNIX_ENABLED
|
||||
|
||||
#include "memory_pool_static_malloc.h"
|
||||
|
||||
#include "os/memory_pool_dynamic_static.h"
|
||||
#include "thread_posix.h"
|
||||
#include "semaphore_posix.h"
|
||||
@ -116,7 +116,6 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MemoryPoolStaticMalloc *mempool_static=NULL;
|
||||
static MemoryPoolDynamicStatic *mempool_dynamic=NULL;
|
||||
|
||||
|
||||
@ -145,7 +144,6 @@ void OS_Unix::initialize_core() {
|
||||
PacketPeerUDPPosix::make_default();
|
||||
IP_Unix::make_default();
|
||||
#endif
|
||||
mempool_static = new MemoryPoolStaticMalloc;
|
||||
mempool_dynamic = memnew( MemoryPoolDynamicStatic );
|
||||
|
||||
ticks_start=0;
|
||||
@ -157,7 +155,6 @@ void OS_Unix::finalize_core() {
|
||||
|
||||
if (mempool_dynamic)
|
||||
memdelete( mempool_dynamic );
|
||||
delete mempool_static;
|
||||
|
||||
}
|
||||
|
||||
|
@ -121,9 +121,9 @@ float Performance::get_monitor(Monitor p_monitor) const {
|
||||
case TIME_FPS: return OS::get_singleton()->get_frames_per_second();
|
||||
case TIME_PROCESS: return _process_time;
|
||||
case TIME_FIXED_PROCESS: return _fixed_process_time;
|
||||
case MEMORY_STATIC: return Memory::get_static_mem_usage();
|
||||
case MEMORY_STATIC: return Memory::get_mem_usage();
|
||||
case MEMORY_DYNAMIC: return Memory::get_dynamic_mem_usage();
|
||||
case MEMORY_STATIC_MAX: return Memory::get_static_mem_max_usage();
|
||||
case MEMORY_STATIC_MAX: return Memory::get_mem_max_usage();
|
||||
case MEMORY_DYNAMIC_MAX: return Memory::get_dynamic_mem_available();
|
||||
case MEMORY_MESSAGE_BUFFER_MAX: return MessageQueue::get_singleton()->get_max_buffer_usage();
|
||||
case OBJECT_COUNT: return ObjectDB::get_object_count();
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "os_windows.h"
|
||||
|
||||
#include "drivers/gles3/rasterizer_gles3.h"
|
||||
#include "drivers/unix/memory_pool_static_malloc.h"
|
||||
#include "os/memory_pool_dynamic_static.h"
|
||||
#include "drivers/windows/thread_windows.h"
|
||||
#include "drivers/windows/semaphore_windows.h"
|
||||
@ -167,7 +166,6 @@ const char * OS_Windows::get_audio_driver_name(int p_driver) const {
|
||||
return AudioDriverManagerSW::get_driver(p_driver)->get_name();
|
||||
}
|
||||
|
||||
static MemoryPoolStatic *mempool_static=NULL;
|
||||
static MemoryPoolDynamic *mempool_dynamic=NULL;
|
||||
|
||||
void OS_Windows::initialize_core() {
|
||||
@ -196,7 +194,6 @@ void OS_Windows::initialize_core() {
|
||||
StreamPeerWinsock::make_default();
|
||||
PacketPeerUDPWinsock::make_default();
|
||||
|
||||
mempool_static = new MemoryPoolStaticMalloc;
|
||||
#if 1
|
||||
mempool_dynamic = memnew( MemoryPoolDynamicStatic );
|
||||
#else
|
||||
@ -1308,7 +1305,6 @@ void OS_Windows::finalize_core() {
|
||||
|
||||
if (mempool_dynamic)
|
||||
memdelete( mempool_dynamic );
|
||||
delete mempool_static;
|
||||
|
||||
|
||||
TCPServerWinsock::cleanup();
|
||||
|
Loading…
Reference in New Issue
Block a user