diff options
Diffstat (limited to 'src/libjin/Common')
-rw-r--r-- | src/libjin/Common/je_array.hpp | 4 | ||||
-rw-r--r-- | src/libjin/Common/je_common.h | 5 | ||||
-rw-r--r-- | src/libjin/Common/je_exception.cpp | 46 | ||||
-rw-r--r-- | src/libjin/Common/je_exception.h | 35 | ||||
-rw-r--r-- | src/libjin/Common/je_noncopyable.h | 4 | ||||
-rw-r--r-- | src/libjin/Common/je_object.h | 6 | ||||
-rw-r--r-- | src/libjin/Common/je_pool.hpp | 172 | ||||
-rw-r--r-- | src/libjin/Common/je_singleton.hpp | 6 | ||||
-rw-r--r-- | src/libjin/Common/je_stringmap.hpp | 4 | ||||
-rw-r--r-- | src/libjin/Common/je_subsystem.hpp | 4 | ||||
-rw-r--r-- | src/libjin/Common/je_temporary.h | 4 | ||||
-rw-r--r-- | src/libjin/Common/je_types.h | 4 | ||||
-rw-r--r-- | src/libjin/Common/je_utf8.h | 6 |
13 files changed, 269 insertions, 31 deletions
diff --git a/src/libjin/Common/je_array.hpp b/src/libjin/Common/je_array.hpp index 361f1f0..8a5cbf1 100644 --- a/src/libjin/Common/je_array.hpp +++ b/src/libjin/Common/je_array.hpp @@ -1,5 +1,5 @@ -#ifndef __JE_COMMON_ARRAY_H -#define __JE_COMMON_ARRAY_H +#ifndef __JE_COMMON_ARRAY_H__ +#define __JE_COMMON_ARRAY_H__ namespace JinEngine { diff --git a/src/libjin/Common/je_common.h b/src/libjin/Common/je_common.h index 0dfa79a..31b67c6 100644 --- a/src/libjin/Common/je_common.h +++ b/src/libjin/Common/je_common.h @@ -1,6 +1,7 @@ -#ifndef __JE_COMMON_H -#define __JE_COMMON_H +#ifndef __JE_COMMON_H__ +#define __JE_COMMON_H__ +#include "je_exception.h" #include "je_array.hpp" #endif
\ No newline at end of file diff --git a/src/libjin/Common/je_exception.cpp b/src/libjin/Common/je_exception.cpp index e69de29..5489a42 100644 --- a/src/libjin/Common/je_exception.cpp +++ b/src/libjin/Common/je_exception.cpp @@ -0,0 +1,46 @@ +#include <stdarg.h> + +#include "je_exception.h" + +namespace JinEngine +{ + + Exception::Exception(const char *fmt, ...) + { + va_list args; + int size_buffer = 256, size_out; + char *buffer; + while (true) + { + buffer = new char[size_buffer]; + memset(buffer, 0, size_buffer); + + va_start(args, fmt); + size_out = vsnprintf(buffer, size_buffer, fmt, args); + va_end(args); + + // see http://perfec.to/vsnprintf/pasprintf.c + // if size_out ... + // == -1 --> output was truncated + // == size_buffer --> output was truncated + // == size_buffer-1 --> ambiguous, /may/ have been truncated + // > size_buffer --> output was truncated, and size_out + // bytes would have been written + if (size_out == size_buffer || size_out == -1 || size_out == size_buffer - 1) + size_buffer *= 2; + else if (size_out > size_buffer) + size_buffer = size_out + 2; // to avoid the ambiguous case + else + break; + + delete[] buffer; + } + mMessage = std::string(buffer); + delete[] buffer; + } + + Exception::~Exception() throw() + { + } + +} // namespace JinEngine
\ No newline at end of file diff --git a/src/libjin/Common/je_exception.h b/src/libjin/Common/je_exception.h index 7c66af8..c319ebd 100644 --- a/src/libjin/Common/je_exception.h +++ b/src/libjin/Common/je_exception.h @@ -1,19 +1,42 @@ -#ifndef __JE_EXCEPTION_H -#define __JE_EXCEPTION_H +#ifndef __JE_EXCEPTION_H__ +#define __JE_EXCEPTION_H__ #include <exception> +#include <string> namespace JinEngine { /// - /// Built-in exception class. + /// Jin Exception. /// - class JinException : public std::exception + class Exception : public std::exception { public: - JinException(); - const char* what() const throw(); + + /// + /// Creates a new Exception according to printf-rules. + /// + /// @param fmt The format string (see printf). + /// + Exception(const char *fmt, ...); + virtual ~Exception() throw(); + + /// + /// Returns a string containing reason for the exception. + /// + /// @return A description of the exception. + /// + inline virtual const char *what() const throw() + { + return mMessage.c_str(); + } + + private: + /// + /// Exception message. + /// + std::string mMessage; }; diff --git a/src/libjin/Common/je_noncopyable.h b/src/libjin/Common/je_noncopyable.h index 89a3e68..eff7121 100644 --- a/src/libjin/Common/je_noncopyable.h +++ b/src/libjin/Common/je_noncopyable.h @@ -1,5 +1,5 @@ -#ifndef __JE_NONCOPYABLE_H -#define __JE_NONCOPYABLE_H +#ifndef __JE_NONCOPYABLE_H__ +#define __JE_NONCOPYABLE_H__ namespace JinEngine { diff --git a/src/libjin/Common/je_object.h b/src/libjin/Common/je_object.h index c256879..1afbf67 100644 --- a/src/libjin/Common/je_object.h +++ b/src/libjin/Common/je_object.h @@ -1,5 +1,5 @@ -#ifndef __JE_OBJECT_H -#define __JE_OBJECT_H +#ifndef __JE_OBJECT_H__ +#define __JE_OBJECT_H__ namespace JinEngine { @@ -9,6 +9,8 @@ namespace JinEngine /// class Object { + public: + }; } // namespace JinEngine diff --git a/src/libjin/Common/je_pool.hpp b/src/libjin/Common/je_pool.hpp index 1107fd5..cb96c5b 100644 --- a/src/libjin/Common/je_pool.hpp +++ b/src/libjin/Common/je_pool.hpp @@ -1,11 +1,177 @@ -#ifndef __JE_POOL_H -#define __JE_POOL_H +/// +/// An O(1) Object Pool. Original from https://www.codeproject.com/Articles/746630/O-Object-Pool-in-Cplusplus +/// +#ifndef __JE_POOL_H__ +#define __JE_POOL_H__ + +#include <stdlib.h> +#include <iostream> + +#include "je_types.h" namespace JinEngine { + class DefaultMemoryAllocator + { + public: + static inline void *Allocate(size_t size) + { + return ::operator new(size, ::std::nothrow); + } + static inline void Deallocate(void *pointer, size_t size) + { + ::operator delete(pointer); + } + }; + + template<typename T, class TMemoryAllocator = DefaultMemoryAllocator> + class Pool + { + private: + struct _Node + { + void *_memory; + size_t _capacity; + _Node *_nextNode; + + _Node(size_t capacity) + { + if (capacity < 1) + throw std::invalid_argument("capacity must be at least 1."); + + _memory = TMemoryAllocator::Allocate(_itemSize * capacity); + if (_memory == NULL) + throw std::bad_alloc(); + + _capacity = capacity; + _nextNode = NULL; + } + ~_Node() + { + TMemoryAllocator::Deallocate(_memory, _itemSize * _capacity); + } + }; + + void *_nodeMemory; + T *_firstDeleted; + size_t _countInNode; + size_t _nodeCapacity; + _Node _firstNode; + _Node *_lastNode; + size_t _maxBlockLength; + + static const size_t _itemSize; + + Pool(const Pool<T, TMemoryAllocator> &source); + void operator = (const Pool<T, TMemoryAllocator> &source); + + void _AllocateNewNode() + { + size_t size = _countInNode; + if (size >= _maxBlockLength) + size = _maxBlockLength; + else + { + size *= 2; + + if (size < _countInNode) + throw std::overflow_error("size became too big."); + + if (size >= _maxBlockLength) + size = _maxBlockLength; + } + + _Node *newNode = new _Node(size); + _lastNode->_nextNode = newNode; + _lastNode = newNode; + _nodeMemory = newNode->_memory; + _countInNode = 0; + _nodeCapacity = size; + } + + public: + explicit Pool(size_t initialCapacity = 32, size_t maxBlockLength = 1000000) + : _firstDeleted(NULL) + , _countInNode(0) + , _nodeCapacity(initialCapacity) + , _firstNode(initialCapacity) + , _maxBlockLength(maxBlockLength) + { + if (maxBlockLength < 1) + throw std::invalid_argument("maxBlockLength must be at least 1."); + + _nodeMemory = _firstNode._memory; + _lastNode = &_firstNode; + } + ~Pool() + { + _Node *node = _firstNode._nextNode; + while (node) + { + _Node *nextNode = node->_nextNode; + delete node; + node = nextNode; + } + } + + T *New() + { + if (_firstDeleted) + { + T *result = _firstDeleted; + _firstDeleted = *((T **)_firstDeleted); + new(result) T(); + return result; + } + + if (_countInNode >= _nodeCapacity) + _AllocateNewNode(); + + char *address = (char *)_nodeMemory; + address += _countInNode * _itemSize; + T *result = new(address) T(); + _countInNode++; + return result; + } + + // This method is useful if you want to call a non-default constructor. + // It should be used like this: + // new (pool.GetNextWithoutInitializing()) ObjectType(... parameters ...); + T *GetNextWithoutInitializing() + { + if (_firstDeleted) + { + T *result = (T *)_firstDeleted; + _firstDeleted = *((T **)_firstDeleted); + return result; + } + + if (_countInNode >= _nodeCapacity) + _AllocateNewNode(); + + char *address = (char *)_nodeMemory; + address += _countInNode * _itemSize; + _countInNode++; + return (T *)address; + } + void Delete(T *content) + { + content->~T(); + + *((T **)content) = _firstDeleted; + _firstDeleted = content; + } + void DeleteWithoutDestroying(T *content) + { + *((T **)content) = _firstDeleted; + _firstDeleted = content; + } + }; + template<typename T, class TMemoryAllocator> + const size_t Pool<T, TMemoryAllocator>::_itemSize = ((sizeof(T) + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *); -} +} // namespace JinEngine #endif
\ No newline at end of file diff --git a/src/libjin/Common/je_singleton.hpp b/src/libjin/Common/je_singleton.hpp index e981e7a..d7f52c9 100644 --- a/src/libjin/Common/je_singleton.hpp +++ b/src/libjin/Common/je_singleton.hpp @@ -1,5 +1,5 @@ -#ifndef __JE_SINGLETON_H -#define __JE_SINGLETON_H +#ifndef __JE_SINGLETON_H__ +#define __JE_SINGLETON_H__ namespace JinEngine { @@ -77,4 +77,4 @@ namespace JinEngine } // namespace JinEngine -#endif // __JE_SINGLETON_H
\ No newline at end of file +#endif // __JE_SINGLETON_H__ diff --git a/src/libjin/Common/je_stringmap.hpp b/src/libjin/Common/je_stringmap.hpp index 43e3e9b..7a3bd80 100644 --- a/src/libjin/Common/je_stringmap.hpp +++ b/src/libjin/Common/je_stringmap.hpp @@ -1,5 +1,5 @@ -#ifndef __JE_COMMON_SREINGMAP_H -#define __JE_COMMON_SREINGMAP_H +#ifndef __JE_COMMON_SREINGMAP_H__ +#define __JE_COMMON_SREINGMAP_H__ namespace JinEngine { diff --git a/src/libjin/Common/je_subsystem.hpp b/src/libjin/Common/je_subsystem.hpp index d8e106d..c015bef 100644 --- a/src/libjin/Common/je_subsystem.hpp +++ b/src/libjin/Common/je_subsystem.hpp @@ -1,5 +1,5 @@ -#ifndef __JE_COMMON_SUBSYSTEM_H -#define __JE_COMMON_SUBSYSTEM_H +#ifndef __JE_COMMON_SUBSYSTEM_H__ +#define __JE_COMMON_SUBSYSTEM_H__ #include "../utils/je_macros.h" diff --git a/src/libjin/Common/je_temporary.h b/src/libjin/Common/je_temporary.h index 5af8704..647bfba 100644 --- a/src/libjin/Common/je_temporary.h +++ b/src/libjin/Common/je_temporary.h @@ -1,5 +1,5 @@ -#ifndef __JE_ON_STACK_H -#define __JE_ON_STACK_H +#ifndef __JE_TEMPORARY_H__ +#define __JE_TEMPORARY_H__ namespace JinEngine { diff --git a/src/libjin/Common/je_types.h b/src/libjin/Common/je_types.h index 446c413..448d7ac 100644 --- a/src/libjin/Common/je_types.h +++ b/src/libjin/Common/je_types.h @@ -1,5 +1,5 @@ -#ifndef __JE_TYPES_H -#define __JE_TYPES_H +#ifndef __JE_TYPES_H__ +#define __JE_TYPES_H__ #include <stdint.h> namespace JinEngine diff --git a/src/libjin/Common/je_utf8.h b/src/libjin/Common/je_utf8.h index a11850c..d840b75 100644 --- a/src/libjin/Common/je_utf8.h +++ b/src/libjin/Common/je_utf8.h @@ -1,5 +1,5 @@ -#ifndef __JE_COMMON_UTF8_H -#define __JE_COMMON_UTF8_H +#ifndef __JE_COMMON_UTF8_H__ +#define __JE_COMMON_UTF8_H__ #include "../core/je_configuration.h" #if jin_os == jin_os_windows @@ -31,4 +31,4 @@ namespace JinEngine #endif // jin_os == jin_os_windows -#endif // __JE_COMMON_UTF8_H
\ No newline at end of file +#endif // __JE_COMMON_UTF8_H__ |