summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2017-01-06 10:15:44 -0300
committerJuan Linietsky <reduzio@gmail.com>2017-01-06 10:15:44 -0300
commit53ce643e520de193c085c0c23046dcbd2e5308a5 (patch)
treed8336629c4ce789eb441fc3bd428e317d8ad8e9c /core
parent99ceddd11ef652a3b8e6bf5d09dcc519d957ce14 (diff)
-Changed memory functions, Memory::alloc_static*, simplified them, made them aligned to 16
-Changed Vector<> template to fit this.
Diffstat (limited to 'core')
-rw-r--r--core/os/memory.cpp205
-rw-r--r--core/os/memory.h135
-rw-r--r--core/os/memory_pool_dynamic_static.cpp2
-rw-r--r--core/os/memory_pool_dynamic_static.h2
-rw-r--r--core/os/memory_pool_static.cpp49
-rw-r--r--core/os/memory_pool_static.h69
-rw-r--r--core/os/os.cpp8
-rw-r--r--core/pool_allocator.cpp4
-rw-r--r--core/safe_refcount.cpp61
-rw-r--r--core/safe_refcount.h312
-rw-r--r--core/typedefs.h4
-rw-r--r--core/vector.h71
12 files changed, 329 insertions, 593 deletions
diff --git a/core/os/memory.cpp b/core/os/memory.cpp
index 4922a18335..cf42c3681a 100644
--- a/core/os/memory.cpp
+++ b/core/os/memory.cpp
@@ -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,49 +101,147 @@ 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::free_static(void *p_ptr) {
+void * Memory::alloc_static(size_t p_bytes,bool p_pad_align) {
- ERR_FAIL_COND( !MemoryPoolStatic::get_singleton());
- MemoryPoolStatic::get_singleton()->free(p_ptr);
-}
+#ifdef DEBUG_ENABLED
+ bool prepad=true;
+#else
+ bool prepad=p_pad_align;
+#endif
+
+ void * mem = malloc( p_bytes + (prepad?PAD_ALIGN:0));
+
+ alloc_count++;
-size_t Memory::get_static_mem_available() {
+ ERR_FAIL_COND_V(!mem,NULL);
- ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
- return MemoryPoolStatic::get_singleton()->get_available_mem();
+ 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;
+ }
}
-size_t Memory::get_static_mem_max_usage() {
+void * Memory::realloc_static(void *p_memory,size_t p_bytes,bool p_pad_align) {
+
+ 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);
- ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
- return MemoryPoolStatic::get_singleton()->get_max_usage();
+ return mem;
+ }
}
-size_t Memory::get_static_mem_usage() {
+void Memory::free_static(void *p_ptr,bool p_pad_align) {
- ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
- return MemoryPoolStatic::get_singleton()->get_total_usage();
+ ERR_FAIL_COND(p_ptr==NULL);
+
+ 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);
+ }
}
-void Memory::dump_static_mem_to_file(const char* p_file) {
+size_t Memory::get_mem_available() {
+
+ return 0xFFFFFFFFFFFFF;
+
+}
- 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) {
MemoryPoolDynamic::ID id = MemoryPoolDynamic::get_singleton()->alloc(p_bytes,p_descr);
diff --git a/core/os/memory.h b/core/os/memory.h
index b3b806f7c6..6a939e3d6f 100644
--- a/core/os/memory.h
+++ b/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;
- }
-
- 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 );
+ void unref();
+ Error _resize(size_t p_size);
- } 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;
+
+ uint64_t elem_count = *(ptr-1);
- for (unsigned int i=0;i<*elems;i++) {
+ for (uint64_t i=0;i<elem_count;i++) {
p_class[i].~T();
};
- Memory::free_static(elems);
+ Memory::free_static(ptr,true);
}
diff --git a/core/os/memory_pool_dynamic_static.cpp b/core/os/memory_pool_dynamic_static.cpp
index 9db4916cbd..b7a1bbc19f 100644
--- a/core/os/memory_pool_dynamic_static.cpp
+++ b/core/os/memory_pool_dynamic_static.cpp
@@ -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 {
diff --git a/core/os/memory_pool_dynamic_static.h b/core/os/memory_pool_dynamic_static.h
index 85c969174a..a72d39355c 100644
--- a/core/os/memory_pool_dynamic_static.h
+++ b/core/os/memory_pool_dynamic_static.h
@@ -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 */
diff --git a/core/os/memory_pool_static.cpp b/core/os/memory_pool_static.cpp
deleted file mode 100644
index bd2ca1436f..0000000000
--- a/core/os/memory_pool_static.cpp
+++ /dev/null
@@ -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;
-}
-
-
diff --git a/core/os/memory_pool_static.h b/core/os/memory_pool_static.h
deleted file mode 100644
index 634d3eda60..0000000000
--- a/core/os/memory_pool_static.h
+++ /dev/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
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 75773a9076..7333d667db 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -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() {
diff --git a/core/pool_allocator.cpp b/core/pool_allocator.cpp
index 00351890c7..e425218060 100644
--- a/core/pool_allocator.cpp
+++ b/core/pool_allocator.cpp
@@ -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 );
diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp
index de6b688b8a..f0d4fbd610 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -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;
+ }
}
-long atomic_decrement( register long * pw ) {
- return InterlockedDecrement( pw );
+uint32_t atomic_decrement( register uint32_t * pw ) {
+
+ return __sync_sub_and_fetch(pw,1);
+
}
+#else
+ //no threads supported?
+#error Must provide atomic functions for this platform or compiler!
+
+#endif
+
#endif
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index 5bb2a4564b..08bea9d244 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -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
diff --git a/core/typedefs.h b/core/typedefs.h
index b24f259cc6..176c77570d 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -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>
diff --git a/core/vector.h b/core/vector.h
index 8113099a61..3227561000 100644
--- a/core/vector.h
+++ b/core/vector.h
@@ -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 ) {
+ uint32_t *refc = _get_refcount();
+
+ if (*refc > 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 current_size = *_get_size();
+
+ uint32_t* mem_new = (uint32_t*)Memory::alloc_static(_get_alloc_size(current_size),true);
- T*_data=(T*)(_size+1);
+
+ *(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;
+ }
}