Update prototype of memory functions
to always get the memory context parameter (even if it is not needed) to provide a cleaner and simpler user interface (instead of requesting the user to use directly m_context).
This commit is contained in:
1 parent
f585167fa8
commit
3721129da1
19 files changed
+155
-118
No files matched your search
@@ -1041,18 +1041,37 @@ In which case, this enables you to close the file even if an exception is thrown
|
||||
|
||||
Memory Allocation functions can be globally set by overriding the following macros before using the definition `_DEF` macros:
|
||||
|
||||
* `M_MEMORY_ALLOC (type)` --> `ptr`: return a pointer to a new object of type `type`.
|
||||
* `M_MEMORY_DEL (ptr)`: free the single object pointed by `ptr`.
|
||||
* `M_MEMORY_REALLOC (type, ptr, old_number, new_number)` --> `ptr`: return a pointer to an array of `new_number` objects of type `type`, reusing the old array pointed by `ptr` of `old_number` objects. `ptr` can be NULL, in which case the array will be created.
|
||||
* `M_MEMORY_FREE (type, ptr, number)`: free the array of `number` objects of type `type` pointed by `ptr`.
|
||||
* `M_MEMORY_ALLOC (context, type)` --> `ptr`: return a pointer to a new object of type `type`.
|
||||
* `M_MEMORY_DEL (context, ptr)`: free the single object pointed by `ptr`.
|
||||
* `M_MEMORY_REALLOC (context, type, ptr, old_number, new_number)` --> `ptr`: return a pointer to an array of `new_number` objects of type `type`, reusing the old array pointed by `ptr` of `old_number` objects. `ptr` can be NULL, in which case the array will be created.
|
||||
* `M_MEMORY_FREE (context, type, ptr, number)`: free the array of `number` objects of type `type` pointed by `ptr`.
|
||||
|
||||
`ALLOC` and `DEL` operators are supposed to allocate fixed size single element object (no array).
|
||||
> [!NOTE]
|
||||
> You can use `sizeof (type)` and `alignof (type)` to get the size and the alignement of the object.
|
||||
|
||||
> [!NOTE]
|
||||
> For `M_MEMORY_DEL`, `sizeof *ptr` always identifies the size of the object.
|
||||
|
||||
`ALLOC` and `DEL` operators are supposed to allocate **fixed** size single element object (no array).
|
||||
These objects are not expected to grow.
|
||||
`REALLOC` and `FREE` operators deal with allocated memory for growing objects.
|
||||
Do not mix pointers between both: a pointer allocated by `ALLOC` (resp. `REALLOC`) is supposed
|
||||
to be only freed by `DEL` (resp. `FREE`). There are separated 'free' operators to enable
|
||||
specialization in the allocator (a good allocator can take this hint into account).
|
||||
|
||||
`context` is a local user context used to identify the memory context to use for the allocation.
|
||||
This parameter **only** exists if the library is compiled with the `M_USE_CONTEXT` customization parameter enabled globally.
|
||||
Otherwise this parameter identifies a non existing symbol `m_context`.
|
||||
|
||||
This parameter shall be discarded if `M_USE_CONTEXT` is not defined (it shall not exist anymore after preprocessing step).
|
||||
For that, you can define the macros to ignore the first parameter
|
||||
or you can use GAIA to adapt the call to what your function expects.
|
||||
|
||||
> [!NOTE]
|
||||
> If you get error on `m_context` being undefined
|
||||
> it is likely because one of your memory is trying to evaluate the memory context
|
||||
> without defining `M_USE_CONTEXT`.
|
||||
|
||||
`M_MEMORY_ALLOC` and `M_MEMORY_REALLOC` are supposed to return NULL in case of memory allocation failure.
|
||||
The defaults are `malloc`, `free`, `realloc` and `free`.
|
||||
|
||||
@@ -4724,7 +4743,7 @@ void f(void) {
|
||||
shared_data_push(p, 23);
|
||||
shared_data_push(p, 32);
|
||||
// And send it through 2 channels of communication
|
||||
comm_buffer_push(comm1, p); // shared_data_acquire is done by the buffer to acquite ownership of the data
|
||||
comm_buffer_push(comm1, p); // shared_data_acquire is done by the buffer to acquit ownership of the data
|
||||
comm_buffer_push(comm2, p);
|
||||
// Release our ownership of the data
|
||||
shared_data_clear(p);
|
||||
@@ -4909,7 +4928,7 @@ This method is created only if the `PUSH` operator is defined.
|
||||
##### `bool name_try_push_move(name_t *a, sub_type *el)`
|
||||
|
||||
Try to push in `*a` the element `*el`,if the container is not full and clear `*el` (return true in this case).
|
||||
Return false otherwise (cannot push element) and `*el` is still initializated.
|
||||
Return false otherwise (cannot push element) and `*el` is still initialized.
|
||||
This method is created only if the `PUSH_MOVE` operator is defined.
|
||||
|
||||
##### `bool name_try_emplace<emplace_suffix>(name_t *a[, <emplace_args> args])`
|
||||
@@ -7967,22 +7986,28 @@ void struct_init_set(struct_t d, struct_t s)
|
||||
|
||||
All these macro can be overridden before including the header [m-core.h](#m-core) so that they can be adapted to a particular memory pool.
|
||||
|
||||
##### `type *M_MEMORY_ALLOC (type)`
|
||||
##### `type *M_MEMORY_ALLOC (context, type)`
|
||||
|
||||
Return a pointer to a new allocated non-initialized object of type `type`.
|
||||
In case of allocation error, it returns NULL.
|
||||
|
||||
`context` parameter is the memory context parameter as provided by the user.
|
||||
It only exists if the library is built with `M_USE_CONTEXT`
|
||||
|
||||
The default used function is the `malloc` function of the LIBC.
|
||||
|
||||
##### `void M_MEMORY_DEL (type *ptr)`
|
||||
##### `void M_MEMORY_DEL (context, type *ptr)`
|
||||
|
||||
Delete the cleared object pointed by the pointer `ptr`
|
||||
that was previously allocated by the macro `M_MEMORY_ALLOC`.
|
||||
`ptr` can not be NULL.
|
||||
|
||||
`context` parameter is the memory context parameter as provided by the user.
|
||||
It only exists if the library is built with `M_USE_CONTEXT`
|
||||
|
||||
The default used function is the `free` function of the LIBC.
|
||||
|
||||
##### `type *M_MEMORY_REALLOC (type, ptr, old_number, new_number)`
|
||||
##### `type *M_MEMORY_REALLOC (context, type, ptr, old_number, new_number)`
|
||||
|
||||
Return a pointer to an array of `new_number` objects of type `type`
|
||||
`ptr` is either NULL (in which the array is allocated),
|
||||
@@ -7994,14 +8019,20 @@ The address of the previous objects may have moved and the `MOVE` operator
|
||||
is not used in this case.
|
||||
In case of allocation error, it returns NULL.
|
||||
|
||||
`context` parameter is the memory context parameter as provided by the user.
|
||||
It only exists if the library is built with `M_USE_CONTEXT`
|
||||
|
||||
The default used function is the `realloc` function of the LIBC.
|
||||
|
||||
##### `void M_MEMORY_FREE (type, ptr, number)`
|
||||
##### `void M_MEMORY_FREE (context, type, ptr, number)`
|
||||
|
||||
Delete the cleared array of `number` objects of type `type pointed by the pointer `ptr`.
|
||||
The pointer was previously allocated by the macro `M_MEMORY_REALLOC`.
|
||||
If `ptr` is NULL, the function shall do nothing.
|
||||
|
||||
`context` parameter is the memory context parameter as provided by the user.
|
||||
It only exists if the library is built with `M_USE_CONTEXT`
|
||||
|
||||
The default used function is the `free` function of the LIBC.
|
||||
|
||||
##### `void M_MEMORY_FULL (type, number)`
|
||||
@@ -9591,8 +9622,8 @@ It is possible to give a custom memory context parameter to the memory methods `
|
||||
For this, you need to define `M_USE_CONTEXT` to the type of the custom memory context parameter.
|
||||
The definition of this global parameter modifies the generation of **all** functions
|
||||
so that the functions that may allocate or free something will add a new argument,
|
||||
the memory context parameter `m_context` of type `M_USE_CONTEXT`,
|
||||
as their first arguement.
|
||||
the memory context parameter `m_context` of the user provided type `M_USE_CONTEXT`,
|
||||
as their first argument.
|
||||
It will also modifies the `OPLIST` definition so that they request the parameter named `m_context`
|
||||
for such methods.
|
||||
|
||||
@@ -9601,29 +9632,26 @@ The memory context can be an [arena allocator](https://www.rfleury.com/p/untangl
|
||||
> [!Note]
|
||||
> The memory context parameter is not stored in the container
|
||||
> because it is not efficient in memory usage and is redundant when you
|
||||
> create container of other containers (example `array` of `string_t)`
|
||||
> The user shall ensure of the coherence of the memory context for a given container
|
||||
> so that it is the same memory context since its construction to its destruction.
|
||||
> create container of other containers (example `array` of `string_t`).
|
||||
|
||||
The user shall ensure of the coherence of the memory context for a given container
|
||||
so that the same memory context is used from its construction to its destruction.
|
||||
|
||||
If you master your own memory, you may want to control when performing the Garbage Collecting.
|
||||
This Garbage Collecting may be quite efficient in reclaiming allocated memory in a single and efficient pass:
|
||||
in such a case, you may not want calling the destructors of the containers as their operation of freeing the memory
|
||||
back to the memory allocator will be redundant and inefficient.
|
||||
As a consequence, the following guarantee is ensured:
|
||||
|
||||
The destructors of all containers except the thread safe ones only free back memory.
|
||||
As such, it is safe not to call the destructors of these containers if you have another way to reclaim your memory.
|
||||
If the destructor of a mutex is also a no-op on your system, this guarantee is extended to the thread safe containers too.
|
||||
If the destructor of a mutex is also a no-op on your system, this guarantee is extended to all containers
|
||||
(including the thread safe containers too).
|
||||
|
||||
In order to use such feature, you need to:
|
||||
|
||||
* define globally `M_USE_CONTEXT` with your type.
|
||||
* define globally an override of the memory functions `M_MEMORY_ALLOC`, `M_MEMORY_DEL`, `M_MEMORY_REALLOC` and `M_MEMORY_FREE`.
|
||||
|
||||
You will realize that the expected definitions of these macros don't expect the memory context parameter.
|
||||
Instead, the macros themselves shall directly use the named argument `m_context` for this purpose.
|
||||
This argument is ensure to be defined by the function when using this macro.
|
||||
|
||||
FIXME: Seems bad design when written...
|
||||
* define globally an override of the memory functions `M_MEMORY_ALLOC`, `M_MEMORY_DEL`, `M_MEMORY_REALLOC` and `M_MEMORY_FREE` to use your context.
|
||||
|
||||
Example
|
||||
|
||||
@@ -9634,16 +9662,16 @@ typedef int *context_t;
|
||||
// Define the realloc / free that accepts the memory context.
|
||||
static void *my_realloc(void *ptr, size_t old, size_t new, size_t base, context_t context)
|
||||
{
|
||||
(void) context; // TODO
|
||||
(void) old; // TODO
|
||||
(void) context; // TODO what you want with it.
|
||||
(void) old; // TODO what you want with it.
|
||||
return realloc(ptr, new*base);
|
||||
}
|
||||
|
||||
static void my_free(void *ptr, size_t old, size_t base, context_t context)
|
||||
{
|
||||
(void) context; // TODO
|
||||
(void) old; // TODO
|
||||
(void) base; // TODO
|
||||
(void) context; // TODO what you want with it.
|
||||
(void) old; // TODO what you want with it.
|
||||
(void) base; // TODO what you want with it.
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
@@ -9652,13 +9680,14 @@ static void my_free(void *ptr, size_t old, size_t base, context_t context)
|
||||
|
||||
// Overloaded memory functions to use the custom ones.
|
||||
// m_context is the name of the memory context parameter
|
||||
# define M_MEMORY_REALLOC(type, ptr, o, n) my_realloc(ptr, o, n, sizeof (type), m_context)
|
||||
# define M_MEMORY_FREE(type, ptr, o) my_free(ptr, o, sizeof (type), m_context)
|
||||
# define M_MEMORY_REALLOC(ctx, type, ptr, o, n) my_realloc(ptr, o, n, sizeof (type), ctx)
|
||||
# define M_MEMORY_FREE(ctx, type, ptr, o) my_free(ptr, o, sizeof (type), ctx)
|
||||
|
||||
# define M_MEMORY_ALLOC(type) my_realloc(NULL, 0, 1, sizeof (type), m_context)
|
||||
# define M_MEMORY_DEL(ptr) my_free(ptr, 1, sizeof (*ptr), m_context)
|
||||
# define M_MEMORY_ALLOC(ctx, type) my_realloc(NULL, 0, 1, sizeof (type), ctx)
|
||||
# define M_MEMORY_DEL(ctx, ptr) my_free(ptr, 1, sizeof (*ptr), ctx)
|
||||
|
||||
// Now you may include M*LIB headers.
|
||||
#include "m-array.h"
|
||||
```
|
||||
|
||||
This works great for local allocators for a thread. However some containers are designed to handle
|
||||
@@ -9667,9 +9696,9 @@ objects accross several threads: shared pointer, communication queue, ...
|
||||
For such containers, a local allocator has no meaning: it will be very hard to ensure the same allocator
|
||||
is used for both the producor thread and the user threads.
|
||||
|
||||
As a concequence, shared pointer, communication queue container and all thread containers
|
||||
As a consequence, shared pointer, communication queue container and all thread containers
|
||||
will use a global memory context:
|
||||
M\*LIB won't add a new argument `m_context` to the functions of such containers. Instead it will generate
|
||||
M\*LIB won't add a context argument to the functions of such containers. Instead it will generate
|
||||
a local parameter initialize to the global memory context.
|
||||
The global memory context is defined by the macro `M_USE_GLOBAL_CONTEXT` which shall define and initialize
|
||||
the named argument to the global memory context. In the absence of definition of such macro, the default is
|
||||
|
||||
@@ -90,6 +90,7 @@ V0.8.0 : * The prototypes of REALLOC / FREE operators are incompatible:
|
||||
Add the old number of elements of the array as argument of REALLOC
|
||||
Add the number of elements of the array and its base type as arguments of FREE.
|
||||
(You can ignore the new arguments which are only hints provided to memory functions).
|
||||
Add the memory context argument.
|
||||
Also impact M_MEMORY_REALLOC & M_MEMORY_FREE
|
||||
This allows more and efficient integration into custom allocators.
|
||||
* M_MEMORY_FULL: replace the failed size allocation size argument
|
||||
|
||||
+4
-4
@@ -43,12 +43,12 @@ static void my_array_free(void *ptr)
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Allocate for single object
|
||||
# define M_MEMORY_ALLOC(type) my_alloc (sizeof (type))
|
||||
# define M_MEMORY_DEL(ptr) my_free(ptr, sizeof *ptr)
|
||||
# define M_MEMORY_ALLOC(ctx, type) my_alloc (sizeof (type))
|
||||
# define M_MEMORY_DEL(ctx, ptr) my_free(ptr, sizeof *ptr)
|
||||
|
||||
// Allocate for array of objects
|
||||
# define M_MEMORY_REALLOC(type, ptr, o, n) my_array_alloc (sizeof (type), ptr, n)
|
||||
# define M_MEMORY_FREE(type, ptr, n) my_array_free(ptr)
|
||||
# define M_MEMORY_REALLOC(ctx, type, ptr, o, n) my_array_alloc (sizeof (type), ptr, n)
|
||||
# define M_MEMORY_FREE(ctx, type, ptr, n) my_array_free(ptr)
|
||||
|
||||
#include "m-list.h"
|
||||
#include "m-array.h"
|
||||
|
||||
+4
-4
@@ -23,8 +23,8 @@ static void my_free(void *ptr, size_t s)
|
||||
}
|
||||
|
||||
// Allocate for single object
|
||||
# define MY_MEMORY_ALLOC(type) my_alloc (sizeof (type))
|
||||
# define MY_MEMORY_DEL(ptr) my_free(ptr, sizeof *ptr)
|
||||
# define MY_MEMORY_ALLOC(ctx, type) my_alloc (sizeof (type))
|
||||
# define MY_MEMORY_DEL(ctx, ptr) my_free(ptr, sizeof *ptr)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -76,8 +76,8 @@ static void my_array_free(void *ptr)
|
||||
}
|
||||
|
||||
// Allocate for array of objects
|
||||
# define MY_MEMORY_REALLOC(type, ptr, o, n) my_array_alloc (sizeof (type), ptr, n)
|
||||
# define MY_MEMORY_FREE(type, ptr, n) my_array_free(ptr)
|
||||
# define MY_MEMORY_REALLOC(ctx, type, ptr, o, n) my_array_alloc (sizeof (type), ptr, n)
|
||||
# define MY_MEMORY_FREE(ctx, type, ptr, n) my_array_free(ptr)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -23,12 +23,11 @@ static void my_free(void *ptr, size_t old, size_t base, context_t context)
|
||||
# define M_USE_CONTEXT context_t
|
||||
|
||||
// Overloaded memory functions to use the custom ones.
|
||||
// m_context is the name of the memory context parameter
|
||||
# define M_MEMORY_REALLOC(type, ptr, o, n) my_realloc(ptr, o, n, sizeof (type), m_context)
|
||||
# define M_MEMORY_FREE(type, ptr, o) my_free(ptr, o, sizeof (*ptr), m_context)
|
||||
# define M_MEMORY_REALLOC(ctx, type, ptr, o, n) my_realloc(ptr, o, n, sizeof (type), ctx)
|
||||
# define M_MEMORY_FREE(ctx, type, ptr, o) my_free(ptr, o, sizeof (*ptr), ctx)
|
||||
|
||||
# define M_MEMORY_ALLOC(type) my_realloc(NULL, 0, 1, sizeof (type), m_context)
|
||||
# define M_MEMORY_DEL(ptr) my_free(ptr, 1, sizeof (*ptr), m_context)
|
||||
# define M_MEMORY_ALLOC(ctx, type) my_realloc(NULL, 0, 1, sizeof (type), ctx)
|
||||
# define M_MEMORY_DEL(ctx, ptr) my_free(ptr, 1, sizeof (*ptr), ctx)
|
||||
|
||||
// Now we can include M*LIB functions.
|
||||
#include "m-string.h"
|
||||
|
||||
+6
-6
@@ -104,7 +104,7 @@ m_bitset_reset(m_bitset_t t)
|
||||
M_P(void, m_bitset, _clear, m_bitset_t t)
|
||||
{
|
||||
m_bitset_reset(t);
|
||||
M_MEMORY_FREE(m_b1tset_limb_ct, t->ptr, t->alloc);
|
||||
M_MEMORY_FREE(m_context, m_b1tset_limb_ct, t->ptr, t->alloc);
|
||||
// This is not really needed, but is safer
|
||||
// This representation is invalid and will be detected by the contract.
|
||||
// A C compiler should be able to optimize out theses initializations.
|
||||
@@ -122,7 +122,7 @@ M_P(void, m_bitset, _set, m_bitset_t d, const m_bitset_t s)
|
||||
if (M_LIKELY (s->size > 0)) {
|
||||
// Test if enough space in target
|
||||
if (s->size > M_B1TSET_FROM_ALLOC (d->alloc)) {
|
||||
m_b1tset_limb_ct *ptr = M_MEMORY_REALLOC (m_b1tset_limb_ct, d->ptr, d->alloc, needAlloc);
|
||||
m_b1tset_limb_ct *ptr = M_MEMORY_REALLOC (m_context, m_b1tset_limb_ct, d->ptr, d->alloc, needAlloc);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL)) {
|
||||
M_MEMORY_FULL(m_b1tset_limb_ct, needAlloc);
|
||||
}
|
||||
@@ -209,7 +209,7 @@ M_P(void, m_bitset, _push_back, m_bitset_t v, bool x)
|
||||
M_MEMORY_FULL(m_b1tset_limb_ct, needAlloc);
|
||||
}
|
||||
// Alloc memory
|
||||
m_b1tset_limb_ct *ptr = M_MEMORY_REALLOC (m_b1tset_limb_ct, v->ptr, v->alloc, needAlloc);
|
||||
m_b1tset_limb_ct *ptr = M_MEMORY_REALLOC (m_context, m_b1tset_limb_ct, v->ptr, v->alloc, needAlloc);
|
||||
// Check if success
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL) ) {
|
||||
M_MEMORY_FULL(m_b1tset_limb_ct, needAlloc);
|
||||
@@ -245,7 +245,7 @@ M_P(void, m_bitset, _resize, m_bitset_t v, size_t size)
|
||||
size_t newAlloc = M_B1TSET_TO_ALLOC (size);
|
||||
if (newAlloc > v->alloc) {
|
||||
// Allocate more limbs to store the bitset.
|
||||
m_b1tset_limb_ct *ptr = M_MEMORY_REALLOC (m_b1tset_limb_ct, v->ptr, v->alloc, newAlloc);
|
||||
m_b1tset_limb_ct *ptr = M_MEMORY_REALLOC (m_context, m_b1tset_limb_ct, v->ptr, v->alloc, newAlloc);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL) ) {
|
||||
M_MEMORY_FULL(m_b1tset_limb_ct, newAlloc);
|
||||
}
|
||||
@@ -290,12 +290,12 @@ M_P(void, m_bitset, _reserve, m_bitset_t v, size_t alloc)
|
||||
}
|
||||
if (M_UNLIKELY (newAlloc == 0)) {
|
||||
// Free all memory used by the bitsets
|
||||
M_MEMORY_FREE (m_b1tset_limb_ct, v->ptr, v->alloc);
|
||||
M_MEMORY_FREE (m_context, m_b1tset_limb_ct, v->ptr, v->alloc);
|
||||
v->size = v->alloc = 0;
|
||||
v->ptr = NULL;
|
||||
} else {
|
||||
// Allocate more memory or reduce memory usage
|
||||
m_b1tset_limb_ct *ptr = M_MEMORY_REALLOC (m_b1tset_limb_ct, v->ptr, v->alloc, newAlloc);
|
||||
m_b1tset_limb_ct *ptr = M_MEMORY_REALLOC (m_context, m_b1tset_limb_ct, v->ptr, v->alloc, newAlloc);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL) ) {
|
||||
M_MEMORY_FULL(m_b1tset_limb_ct, newAlloc);
|
||||
}
|
||||
|
||||
+4
-4
@@ -77,7 +77,7 @@ m_bstring_init(m_bstring_t s)
|
||||
M_P(void, m_bstring, _clear, m_bstring_t s)
|
||||
{
|
||||
M_BSTRING_CONTRACT(s);
|
||||
M_MEMORY_FREE(uint8_t, s->ptr, s->alloc);
|
||||
M_MEMORY_FREE(m_context, uint8_t, s->ptr, s->alloc);
|
||||
s->offset = (size_t) -1;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ M_P(uint8_t *, m_bstr1ng, _fit2size, m_bstring_t v, size_t size_alloc, bool exac
|
||||
if (M_UNLIKELY_NOMEM (alloc < size_alloc)) {
|
||||
goto allocation_error;
|
||||
}
|
||||
uint8_t *ptr = M_MEMORY_REALLOC (uint8_t, v->ptr, v->alloc, alloc);
|
||||
uint8_t *ptr = M_MEMORY_REALLOC (m_context, uint8_t, v->ptr, v->alloc, alloc);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL)) {
|
||||
goto allocation_error;
|
||||
}
|
||||
@@ -396,13 +396,13 @@ M_P(void, m_bstring, _reserve, m_bstring_t v, size_t n)
|
||||
n = v->offset + size;
|
||||
}
|
||||
if (n == 0) {
|
||||
M_MEMORY_FREE(uint8_t, v->ptr, v->alloc);
|
||||
M_MEMORY_FREE(m_context, uint8_t, v->ptr, v->alloc);
|
||||
v->offset = 0;
|
||||
v->size = 0;
|
||||
v->alloc = 0;
|
||||
v->ptr = NULL;
|
||||
} else {
|
||||
uint8_t *ptr = M_MEMORY_REALLOC (uint8_t, v->ptr, v->alloc, n);
|
||||
uint8_t *ptr = M_MEMORY_REALLOC (m_context, uint8_t, v->ptr, v->alloc, n);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL)) {
|
||||
M_MEMORY_FULL(uint8_t, n);
|
||||
}
|
||||
|
||||
+12
-12
@@ -97,7 +97,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
M_F(name, _slist_node_ct) *it = *list, *next; \
|
||||
while (it) { \
|
||||
next = it->next; \
|
||||
M_MEMORY_DEL(it); \
|
||||
M_MEMORY_DEL(m_context, it); \
|
||||
it = next; \
|
||||
} \
|
||||
*list = NULL; \
|
||||
@@ -292,14 +292,14 @@ M_BEGIN_PROTECTED_CODE
|
||||
M_F(name, _lf_node_t) *next = atomic_load_explicit(&node->next, \
|
||||
memory_order_relaxed); \
|
||||
M_F(name, _slist_clear)(node->list); \
|
||||
M_MEMORY_DEL(node); \
|
||||
M_MEMORY_DEL(m_context, node); \
|
||||
node = next; \
|
||||
} \
|
||||
/* Dummy node to free too */ \
|
||||
M_F(name, _lf_node_t) *dummy; \
|
||||
dummy = atomic_load_explicit(&list->head, memory_order_relaxed); \
|
||||
M_F(name, _slist_clear)(dummy->list); \
|
||||
M_MEMORY_DEL(dummy); \
|
||||
M_MEMORY_DEL(m_context, dummy); \
|
||||
} \
|
||||
|
||||
/* System node allocator: request memory to the system.
|
||||
@@ -310,7 +310,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
M_F(name, _alloc_node)(unsigned int initial) \
|
||||
{ \
|
||||
M_F(name, _lf_node_t) * node; \
|
||||
node = M_MEMORY_ALLOC(M_F(name, _lf_node_t)); \
|
||||
node = M_MEMORY_ALLOC(m_context, M_F(name, _lf_node_t)); \
|
||||
if (M_UNLIKELY_NOMEM (node == NULL)) { \
|
||||
M_MEMORY_FULL(M_F(name, _lf_node_t), 1); \
|
||||
} \
|
||||
@@ -319,7 +319,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
M_F(name, _slist_init)(node->list); \
|
||||
for(unsigned i = 0; i < initial; i++) { \
|
||||
M_F(name, _slist_node_ct) *n; \
|
||||
n = M_MEMORY_ALLOC(M_F(name, _slist_node_ct)); \
|
||||
n = M_MEMORY_ALLOC(m_context, M_F(name, _slist_node_ct)); \
|
||||
if (M_UNLIKELY_NOMEM (n == NULL)) { \
|
||||
M_MEMORY_FULL(M_F(name, _lf_node_t), 1); \
|
||||
} \
|
||||
@@ -462,7 +462,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
{ \
|
||||
const size_t max_thread = gc_mem->max_thread; \
|
||||
/* Initialize the thread data of the mempool */ \
|
||||
mem->thread_data = M_MEMORY_REALLOC(M_F(name, _lfmp_thread_ct), NULL, 0, max_thread); \
|
||||
mem->thread_data = M_MEMORY_REALLOC(m_context, M_F(name, _lfmp_thread_ct), NULL, 0, max_thread); \
|
||||
if (M_UNLIKELY_NOMEM (mem->thread_data == NULL)) { \
|
||||
M_MEMORY_FULL(M_F(name, _lfmp_thread_ct), max_thread); \
|
||||
} \
|
||||
@@ -494,7 +494,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
for(unsigned i = 0; i < max_thread;i++) { \
|
||||
M_F(name, _lfmp_thread_clear)(&mem->thread_data[i]); \
|
||||
} \
|
||||
M_MEMORY_FREE(M_F(name, _lfmp_thread_ct), mem->thread_data, max_thread); \
|
||||
M_MEMORY_FREE(m_context, M_F(name, _lfmp_thread_ct), mem->thread_data, max_thread); \
|
||||
mem->thread_data = NULL; \
|
||||
M_F(name, _lflist_clear)(mem->empty); \
|
||||
M_F(name, _lflist_clear)(mem->free); \
|
||||
@@ -584,7 +584,7 @@ m_gc_init(m_gc_t gc_mem, size_t max_thread)
|
||||
|
||||
atomic_init(&gc_mem->ticket, 0UL);
|
||||
m_genint_init(gc_mem->thread_alloc, (unsigned int) max_thread);
|
||||
gc_mem->thread_data = M_MEMORY_REALLOC(m_gc_lfmp_thread_ct, NULL, 0, max_thread);
|
||||
gc_mem->thread_data = M_MEMORY_REALLOC(m_context, m_gc_lfmp_thread_ct, NULL, 0, max_thread);
|
||||
if (M_UNLIKELY_NOMEM (gc_mem->thread_data == NULL)) {
|
||||
M_MEMORY_FULL(m_gc_lfmp_thread_ct, max_thread);
|
||||
}
|
||||
@@ -604,7 +604,7 @@ m_gc_clear(m_gc_t gc_mem)
|
||||
for(m_gc_tid_t i = 0; i < gc_mem->max_thread;i++) {
|
||||
m_core_backoff_clear(gc_mem->thread_data[i].bkoff);
|
||||
}
|
||||
M_MEMORY_FREE(m_gc_lfmp_thread_ct, gc_mem->thread_data, gc_mem->max_thread);
|
||||
M_MEMORY_FREE(m_context, m_gc_lfmp_thread_ct, gc_mem->thread_data, gc_mem->max_thread);
|
||||
gc_mem->thread_data = NULL;
|
||||
m_genint_clear(gc_mem->thread_alloc);
|
||||
}
|
||||
@@ -753,7 +753,7 @@ m_vlapool_init(m_vlapool_t mem, m_gc_t gc_mem)
|
||||
const size_t max_thread = gc_mem->max_thread;
|
||||
|
||||
/* Initialize the thread data of the vlapool */
|
||||
mem->thread_data = M_MEMORY_REALLOC(m_vlapool_lfmp_thread_ct, NULL, 0, max_thread);
|
||||
mem->thread_data = M_MEMORY_REALLOC(m_context, m_vlapool_lfmp_thread_ct, NULL, 0, max_thread);
|
||||
if (M_UNLIKELY_NOMEM (mem->thread_data == NULL)) {
|
||||
M_MEMORY_FULL(m_vlapool_lfmp_thread_ct, max_thread);
|
||||
}
|
||||
@@ -779,7 +779,7 @@ m_vlapool_clear(m_vlapool_t mem)
|
||||
for(unsigned i = 0; i < max_thread;i++) {
|
||||
m_vlapool_lfmp_thread_clear(&mem->thread_data[i]);
|
||||
}
|
||||
M_MEMORY_FREE(m_vlapool_lfmp_thread_ct, mem->thread_data, max_thread);
|
||||
M_MEMORY_FREE(m_context, m_vlapool_lfmp_thread_ct, mem->thread_data, max_thread);
|
||||
mem->thread_data = NULL;
|
||||
m_vlapool_lflist_clear(mem->empty);
|
||||
M_ASSERT(m_vlapool_lflist_empty_p(mem->to_be_reclaimed));
|
||||
@@ -802,7 +802,7 @@ m_vlapool_new(m_vlapool_t mem, m_gc_tid_t id, size_t size)
|
||||
size += offsetof(struct m_vlapool_slist_node_s, data);
|
||||
|
||||
// Simply wrap around a system call to get the memory
|
||||
char *ptr = M_MEMORY_REALLOC(char, NULL, 0, size);
|
||||
char *ptr = M_MEMORY_REALLOC(m_context, char, NULL, 0, size);
|
||||
// TODO: save the allocated size somewhere (create a new field in vla)
|
||||
// FIXME: Bug, we call DEL operator to free the node, but we have allocated it with the REALLOC one!
|
||||
// And they are not necessarily compatible as per the spec (even if they are if they both use 'free')
|
||||
|
||||
@@ -363,39 +363,47 @@ M_BEGIN_PROTECTED_CODE
|
||||
explicit cast) */
|
||||
|
||||
/* Define allocators for object:
|
||||
* void *M_MEMORY_ALLOC(type): Return a pointer to a new object of type 'type'
|
||||
* void *M_MEMORY_ALLOC(ctx, type):
|
||||
* Return a pointer to a new object of type 'type'
|
||||
* It returns NULL in case of memory allocation failure.
|
||||
* void M_MEMORY_DEL(ptr): Free the object associated to the pointer.
|
||||
* void M_MEMORY_DEL(ctx, ptr):
|
||||
* Free the object associated to the pointer.
|
||||
* By default, 'context' does nothing.
|
||||
* 'context' is the context parameter given to the memory functions to identify where to create the object.
|
||||
* It exists only if M_USE_CONTEXT has been globally defined.
|
||||
*/
|
||||
#ifndef M_MEMORY_ALLOC
|
||||
#ifdef __cplusplus
|
||||
# include <cstdlib>
|
||||
# define M_MEMORY_ALLOC(type) ((type*)std::malloc (sizeof (type)))
|
||||
# define M_MEMORY_DEL(ptr) std::free(ptr)
|
||||
# define M_MEMORY_ALLOC(ctx, type) ((type*)std::malloc (sizeof (type)))
|
||||
# define M_MEMORY_DEL(ctx, ptr) std::free(ptr)
|
||||
#else
|
||||
# define M_MEMORY_ALLOC(type) malloc (sizeof (type))
|
||||
# define M_MEMORY_DEL(ptr) free(ptr)
|
||||
# define M_MEMORY_ALLOC(ctx, type) malloc (sizeof (type))
|
||||
# define M_MEMORY_DEL(ctx, ptr) free(ptr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define allocators for array
|
||||
* void *M_MEMORY_REALLOC(type, ptr, o, n, perm): Return a pointer to a new array of 'n' object of type 'type'.
|
||||
* void *M_MEMORY_REALLOC(context, type, ptr, o, n, perm):
|
||||
* Return a pointer to a new array of 'n' object of type 'type'.
|
||||
* If ptr is NULL, it creates a new array of type 'type' and size 'n'
|
||||
* If ptr is not null, it reallocates the given array of type 'type' and size 'o' to the new size.
|
||||
* It returns NULL in case of memory allocation failure.
|
||||
* void M_MEMORY_FREE(type, ptr, o): Free the object associated to the array of type 'type' at base 'ptr' of size 'o'.
|
||||
* By default, old size do nothing.
|
||||
* Can use local optional named parameter "m_context" which is defined by the called of the macro if M_USE_CONTEXT is defined.
|
||||
* void M_MEMORY_FREE(type, ptr, o):
|
||||
* Free the object associated to the array of type 'type' at base 'ptr' of size 'o'.
|
||||
* By default, 'o' size and 'context' do nothing.
|
||||
* 'context' is the context parameter given to the memory functions to identify where to create the object.
|
||||
* It exists only if M_USE_CONTEXT has been globally defined.
|
||||
*/
|
||||
#ifndef M_MEMORY_REALLOC
|
||||
#ifdef __cplusplus
|
||||
# include <cstdlib>
|
||||
# define M_MEMORY_REALLOC(type, ptr, o, n) \
|
||||
# define M_MEMORY_REALLOC(ctx, type, ptr, o, n) \
|
||||
((type*) (M_UNLIKELY ((n) > SIZE_MAX / sizeof(type)) ? NULL : std::realloc ((ptr), (n)*sizeof (type))))
|
||||
# define M_MEMORY_FREE(type, ptr, o) std::free(ptr)
|
||||
# define M_MEMORY_FREE(ctx, type, ptr, o) std::free(ptr)
|
||||
#else
|
||||
# define M_MEMORY_REALLOC(type, ptr, o, n) (M_UNLIKELY ((n) > SIZE_MAX / sizeof(type)) ? NULL : realloc ((ptr), (n)*sizeof (type)))
|
||||
# define M_MEMORY_FREE(type, ptr, o) free(ptr)
|
||||
# define M_MEMORY_REALLOC(ctx, type, ptr, o, n) (M_UNLIKELY ((n) > SIZE_MAX / sizeof(type)) ? NULL : realloc ((ptr), (n)*sizeof (type)))
|
||||
# define M_MEMORY_FREE(ctx, type, ptr, o) free(ptr)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -3632,7 +3640,6 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
|
||||
#define M_CALL_MOVE(oplist, ...) M_APPLY_API(M_GET_MOVE oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_SWAP(oplist, ...) M_APPLY_API(M_GET_SWAP oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_CLEAR(oplist, ...) M_APPLY_API(M_GET_CLEAR oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_NEW(oplist, ...) M_APPLY_API(M_GET_NEW oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_HASH(oplist, ...) M_APPLY_API(M_GET_HASH oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_EQUAL(oplist, ...) M_APPLY_API(M_GET_EQUAL oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_CMP(oplist, ...) M_APPLY_API(M_GET_CMP oplist, oplist, __VA_ARGS__)
|
||||
@@ -3691,9 +3698,10 @@ M_INLINE size_t m_core_cstr_hash(const char str[])
|
||||
//#define M_CALL_PROPERTIES(oplist, ...) M_APPLY_API(M_GET_PROPERTIES oplist, oplist, __VA_ARGS__)
|
||||
//#define M_CALL_EMPLACE_TYPE(oplist, ...) M_APPLY_API(M_GET_EMPLACE_TYPE oplist, oplist, __VA_ARGS__)
|
||||
// As attribute customization
|
||||
#define M_CALL_DEL(oplist, ...) M_APPLY_API(M_GET_DEL oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_REALLOC(oplist, ...) M_APPLY_API(M_GET_REALLOC oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_FREE(oplist, ...) M_APPLY_API(M_GET_FREE oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_NEW(oplist, ...) M_APPLY_API(M_GET_NEW oplist, oplist, m_context, __VA_ARGS__)
|
||||
#define M_CALL_DEL(oplist, ...) M_APPLY_API(M_GET_DEL oplist, oplist, m_context, __VA_ARGS__)
|
||||
#define M_CALL_REALLOC(oplist, ...) M_APPLY_API(M_GET_REALLOC oplist, oplist, m_context, __VA_ARGS__)
|
||||
#define M_CALL_FREE(oplist, ...) M_APPLY_API(M_GET_FREE oplist, oplist, m_context, __VA_ARGS__)
|
||||
#define M_CALL_MEMPOOL(oplist, ...) M_APPLY_API(M_GET_MEMPOOL oplist, oplist, __VA_ARGS__)
|
||||
#define M_CALL_MEMPOOL_LINKAGE(oplist, ...) M_APPLY_API(M_GET_MEMPOOL_LINKAGE oplist, oplist, __VA_ARGS__)
|
||||
//#define M_CALL_SIZE(oplist, ...) M_APPLY_API(M_GET_SIZE oplist, oplist, __VA_ARGS__)
|
||||
|
||||
@@ -104,9 +104,9 @@
|
||||
|
||||
// OPLIST for the node deletion
|
||||
#ifdef M_USE_CONTEXT
|
||||
#define M_D3QU3_NODE_DEL_OPLIST(name) (DEL(API_0P(M_F(name, _node_list_i_del))))
|
||||
#else
|
||||
#define M_D3QU3_NODE_DEL_OPLIST(name) (DEL(M_F(name, _node_list_i_del)))
|
||||
#else
|
||||
#define M_D3QU3_NODE_DEL_OPLIST(name) (DEL(API(M_F(name, _node_list_i_del), NONE, ARG2)))
|
||||
#endif
|
||||
|
||||
/* Define the types.
|
||||
|
||||
+2
-2
@@ -108,7 +108,7 @@ M_P(void, m_genint, _init, m_genint_t s, unsigned int n)
|
||||
M_ASSERT (s != NULL && n > 0 && n <= M_GENINT_MAX_ALLOC);
|
||||
const size_t alloc = (n + M_GEN1NT_LIMBSIZE - 1) / M_GEN1NT_LIMBSIZE;
|
||||
const unsigned int index = n % M_GEN1NT_LIMBSIZE;
|
||||
atomic_ullong *ptr = M_MEMORY_REALLOC (atomic_ullong, NULL, 0, alloc);
|
||||
atomic_ullong *ptr = M_MEMORY_REALLOC (m_context, atomic_ullong, NULL, 0, alloc);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL)) {
|
||||
M_MEMORY_FULL(atomic_ullong, alloc);
|
||||
}
|
||||
@@ -127,7 +127,7 @@ M_P(void, m_genint, _init, m_genint_t s, unsigned int n)
|
||||
M_P(void, m_genint, _clear, m_genint_t s)
|
||||
{
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
M_MEMORY_FREE(atomic_ullong, s->data, s->max+1);
|
||||
M_MEMORY_FREE(m_context, atomic_ullong, s->data, s->max+1);
|
||||
s->data = NULL;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -116,7 +116,7 @@
|
||||
M_F(name,_init)(name_t mem) \
|
||||
{ \
|
||||
mem->free_list = NULL; \
|
||||
mem->current_segment = M_MEMORY_ALLOC(M_F(name,_segment_ct)); \
|
||||
mem->current_segment = M_MEMORY_ALLOC(m_context, M_F(name,_segment_ct)); \
|
||||
if (M_UNLIKELY_NOMEM(mem->current_segment == NULL)) { \
|
||||
M_MEMORY_FULL(M_F(name,_segment_ct), 1); \
|
||||
} \
|
||||
@@ -132,7 +132,7 @@
|
||||
M_F(name,_segment_ct) *segment = mem->current_segment; \
|
||||
while (segment != NULL) { \
|
||||
M_F(name,_segment_ct) *next = segment->next; \
|
||||
M_MEMORY_DEL (segment); \
|
||||
M_MEMORY_DEL (m_context, segment); \
|
||||
segment = next; \
|
||||
} \
|
||||
/* Clean pointers to be safer */ \
|
||||
@@ -157,7 +157,7 @@
|
||||
unsigned int count = segment->count; \
|
||||
/* If segment is full, allocate a new one from the system */ \
|
||||
if (M_UNLIKELY (count >= M_USE_MEMPOOL_MAX_PER_SEGMENT(type))) { \
|
||||
M_F(name,_segment_ct) *new_segment = M_MEMORY_ALLOC (M_F(name,_segment_ct)); \
|
||||
M_F(name,_segment_ct) *new_segment = M_MEMORY_ALLOC (m_context, M_F(name,_segment_ct)); \
|
||||
if (M_UNLIKELY_NOMEM (new_segment == NULL)) { \
|
||||
M_MEMORY_FULL(M_F(name,_segment_ct), 1); \
|
||||
} \
|
||||
|
||||
+2
-2
@@ -390,7 +390,7 @@ M_P(void, m_snapsh0t, _mrsw_init, m_snapsh0t_mrsw_ct s, size_t n)
|
||||
n += M_SNAPSH0T_SPMC_EXTRA_BUFFER;
|
||||
|
||||
// Initialize the counters to zero (no reader use it)
|
||||
atomic_uint *ptr = M_MEMORY_REALLOC (atomic_uint, NULL, 0, n);
|
||||
atomic_uint *ptr = M_MEMORY_REALLOC (m_context, atomic_uint, NULL, 0, n);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL)) {
|
||||
M_MEMORY_FULL(atomic_uint, n);
|
||||
}
|
||||
@@ -416,7 +416,7 @@ M_P(void, m_snapsh0t, _mrsw_init, m_snapsh0t_mrsw_ct s, size_t n)
|
||||
M_P(void, m_snapsh0t, _mrsw_clear, m_snapsh0t_mrsw_ct s)
|
||||
{
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
M_MEMORY_FREE (atomic_uint, s->cptTab, s->n_reader+M_SNAPSH0T_SPMC_EXTRA_BUFFER);
|
||||
M_MEMORY_FREE (m_context, atomic_uint, s->cptTab, s->n_reader+M_SNAPSH0T_SPMC_EXTRA_BUFFER);
|
||||
m_genint_clear M_R(s->freeList);
|
||||
s->cptTab = NULL;
|
||||
s->n_reader = 0;
|
||||
|
||||
+5
-5
@@ -285,7 +285,7 @@ M_P(void, m_string, _clear, m_string_t v)
|
||||
{
|
||||
M_STR1NG_CONTRACT(v);
|
||||
if (!m_str1ng_embedded_p(v)) {
|
||||
M_MEMORY_FREE(char, v->u.heap.ptr, m_string_capacity(v));
|
||||
M_MEMORY_FREE(m_context, char, v->u.heap.ptr, m_string_capacity(v));
|
||||
v->u.heap.ptr = NULL;
|
||||
}
|
||||
/* This is not needed but is safer to make
|
||||
@@ -309,7 +309,7 @@ M_P(char *, m_string, _clear_get_cstr, m_string_t v)
|
||||
p = &v->u.buffer[0];
|
||||
// Need to allocate a heap string to return the copy.
|
||||
size_t alloc = m_string_size(v)+1;
|
||||
char *ptr = M_MEMORY_REALLOC (char, NULL, 0, alloc);
|
||||
char *ptr = M_MEMORY_REALLOC (m_context, char, NULL, 0, alloc);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL)) {
|
||||
M_MEMORY_FULL(char, alloc);
|
||||
}
|
||||
@@ -386,7 +386,7 @@ M_P(char *, m_str1ng, _fit2size, m_string_t v, size_t size_alloc)
|
||||
}
|
||||
char *ptr = m_str1ng_embedded_p(v) ? NULL : v->u.heap.ptr;
|
||||
//FIXME: old_alloc may not be NULL if ptr is NULL.
|
||||
ptr = M_MEMORY_REALLOC (char, ptr, old_alloc, alloc);
|
||||
ptr = M_MEMORY_REALLOC (m_context, char, ptr, old_alloc, alloc);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL)) {
|
||||
M_MEMORY_FULL(char, alloc);
|
||||
}
|
||||
@@ -429,7 +429,7 @@ M_P(void, m_string, _reserve, m_string_t v, size_t alloc)
|
||||
char *oldptr = v->u.heap.ptr;
|
||||
memcpy(ptr, oldptr, size+1);
|
||||
// Free the allocated memory on the heap
|
||||
M_MEMORY_FREE(char, oldptr, m_string_capacity(v));
|
||||
M_MEMORY_FREE(m_context, char, oldptr, m_string_capacity(v));
|
||||
v->u.buffer[sizeof(m_string_t)-2] = 0;
|
||||
v->u.buffer[sizeof(m_string_t)-1] = (char) size;
|
||||
} else {
|
||||
@@ -444,7 +444,7 @@ M_P(void, m_string, _reserve, m_string_t v, size_t alloc)
|
||||
M_MEMORY_FULL(char, alloc);
|
||||
}
|
||||
char *ptr = m_str1ng_embedded_p(v) ? NULL : v->u.heap.ptr;
|
||||
ptr = M_MEMORY_REALLOC (char, ptr, m_string_capacity(v), r_alloc);
|
||||
ptr = M_MEMORY_REALLOC (m_context, char, ptr, m_string_capacity(v), r_alloc);
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL) ) {
|
||||
M_MEMORY_FULL(char, alloc);
|
||||
}
|
||||
|
||||
+4
-4
@@ -237,7 +237,7 @@ typedef struct m_worker_sync_s {
|
||||
M_GLOBAL_CONTEXT(); \
|
||||
M_MAP3(M_WORK3R_SPAWN_EXTEND_DEF_CALLBACK_CLEAR, data, __VA_ARGS__) \
|
||||
/* TODO: Overload */ \
|
||||
M_MEMORY_DEL(p); \
|
||||
M_MEMORY_DEL(m_context, p); \
|
||||
} \
|
||||
\
|
||||
M_INLINE void \
|
||||
@@ -265,7 +265,7 @@ typedef struct m_worker_sync_s {
|
||||
{ \
|
||||
M_GLOBAL_CONTEXT(); \
|
||||
if (!m_work3r_queue_full_p(block->worker->queue_g)) { \
|
||||
struct M_C3(m_worker_, name, _s) *p = M_MEMORY_ALLOC ( struct M_C3(m_worker_, name, _s)); \
|
||||
struct M_C3(m_worker_, name, _s) *p = M_MEMORY_ALLOC (m_context, struct M_C3(m_worker_, name, _s)); \
|
||||
if (M_UNLIKELY_NOMEM(p == NULL)) { \
|
||||
M_MEMORY_FULL(struct M_C3(m_worker_, name, _s), 1); \
|
||||
} \
|
||||
@@ -412,7 +412,7 @@ m_worker_init(m_worker_t g, int numWorker, unsigned int extraQueue, void (*reset
|
||||
M_ASSERT(numWorker >= 0);
|
||||
size_t numWorker_st = (size_t) numWorker;
|
||||
M_GLOBAL_CONTEXT();
|
||||
g->worker = M_MEMORY_REALLOC(m_work3r_thread_ct, NULL, 0, numWorker_st);
|
||||
g->worker = M_MEMORY_REALLOC(m_context, m_work3r_thread_ct, NULL, 0, numWorker_st);
|
||||
if (M_UNLIKELY_NOMEM (g->worker == NULL)) {
|
||||
M_MEMORY_FULL(m_work3r_thread_ct, numWorker_st);
|
||||
}
|
||||
@@ -457,7 +457,7 @@ m_worker_clear(m_worker_t g)
|
||||
m_thread_join(g->worker[i].id);
|
||||
}
|
||||
// Clear memory
|
||||
M_MEMORY_FREE(m_work3r_thread_ct, g->worker, g->numWorker_g);
|
||||
M_MEMORY_FREE(m_context, m_work3r_thread_ct, g->worker, g->numWorker_g);
|
||||
m_mutex_clear(g->lock);
|
||||
m_cond_clear(g->a_thread_ends);
|
||||
m_work3r_queue_clear (g->queue_g);
|
||||
|
||||
@@ -271,7 +271,7 @@ typedef struct test_s {
|
||||
static void test_init(test_t *p) { memset(p->buffer, 0x00, 52); }
|
||||
static void test_clear(test_t *p) { memset(p->buffer, 0xFF, 52); }
|
||||
ISHARED_PTR_DEF(ishared_itest, test_t,
|
||||
(INIT(test_init M_IPTR), CLEAR(test_clear M_IPTR), DEL(free)))
|
||||
(INIT(test_init M_IPTR), CLEAR(test_clear M_IPTR), DEL(API(free, NONE, ARG2))))
|
||||
|
||||
typedef struct test2_s {
|
||||
ISHARED_PTR_INTERFACE(ishared_itest2, struct test_s);
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ START_COVERAGE
|
||||
ILIST_DEF(ilist_tname, test_t, M_OPEXTEND(M_POD_OPLIST, EQUAL(API_6(test_equal_p))))
|
||||
END_COVERAGE
|
||||
|
||||
ILIST_DEF(ilist_free, test_t, (DEL(free)))
|
||||
ILIST_DEF(ilist_free, test_t, (DEL(API(free, NONE, ARG2))))
|
||||
|
||||
typedef struct testd_s {
|
||||
double n;
|
||||
|
||||
@@ -37,16 +37,16 @@ static inline void test_obj_except_trigger(void);
|
||||
extern int test_obj_except__malloc_counter;
|
||||
#ifdef __cplusplus
|
||||
# include <cstdlib>
|
||||
# define M_MEMORY_ALLOC(type) (test_obj_except_trigger(), test_obj_except__malloc_counter++, (type*)std::malloc (sizeof (type)))
|
||||
# define M_MEMORY_DEL(ptr) (test_obj_except__malloc_counter-=(ptr != NULL), std::free(ptr))
|
||||
# define M_MEMORY_REALLOC(type, ptr, o, n) \
|
||||
# define M_MEMORY_ALLOC(ctx, type) (test_obj_except_trigger(), test_obj_except__malloc_counter++, (type*)std::malloc (sizeof (type)))
|
||||
# define M_MEMORY_DEL(ctx, ptr) (test_obj_except__malloc_counter-=(ptr != NULL), std::free(ptr))
|
||||
# define M_MEMORY_REALLOC(ctx, type, ptr, o, n) \
|
||||
((type*) (test_obj_except_trigger(), test_obj_except__malloc_counter+= (ptr == NULL), std::realloc ((ptr), (n)*sizeof (type))))
|
||||
# define M_MEMORY_FREE(type, ptr, o) (test_obj_except__malloc_counter-=(ptr != NULL), std::free(ptr))
|
||||
# define M_MEMORY_FREE(ctx, type, ptr, o) (test_obj_except__malloc_counter-=(ptr != NULL), std::free(ptr))
|
||||
#else
|
||||
# define M_MEMORY_ALLOC(type) (test_obj_except_trigger(), test_obj_except__malloc_counter++, malloc (sizeof (type)))
|
||||
# define M_MEMORY_DEL(ptr) (test_obj_except__malloc_counter-=(ptr != NULL), free(ptr))
|
||||
# define M_MEMORY_REALLOC(type, ptr, o, n) (test_obj_except_trigger(), test_obj_except__malloc_counter+=(ptr == NULL), realloc ((ptr), (n)*sizeof (type)))
|
||||
# define M_MEMORY_FREE(type, ptr, o) (test_obj_except__malloc_counter-=(ptr != NULL), free(ptr))
|
||||
# define M_MEMORY_ALLOC(ctx, type) (test_obj_except_trigger(), test_obj_except__malloc_counter++, malloc (sizeof (type)))
|
||||
# define M_MEMORY_DEL(ctx, ptr) (test_obj_except__malloc_counter-=(ptr != NULL), free(ptr))
|
||||
# define M_MEMORY_REALLOC(ctx, type, ptr, o, n) (test_obj_except_trigger(), test_obj_except__malloc_counter+=(ptr == NULL), realloc ((ptr), (n)*sizeof (type)))
|
||||
# define M_MEMORY_FREE(ctx, type, ptr, o) (test_obj_except__malloc_counter-=(ptr != NULL), free(ptr))
|
||||
#endif
|
||||
|
||||
// Include M*LIB headers
|
||||
|
||||
+2
-2
@@ -68,8 +68,8 @@ static inline void overloaded_free(size_t st, void *ptr, size_t n)
|
||||
free(p);
|
||||
}
|
||||
|
||||
#define M_MEMORY_REALLOC(type, ptr, o, n) (type *) overloaded_realloc(sizeof(type), ptr, o, n)
|
||||
#define M_MEMORY_FREE(type, ptr, o) overloaded_free(sizeof(type), ptr, o)
|
||||
#define M_MEMORY_REALLOC(ctx, type, ptr, o, n) (type *) overloaded_realloc(sizeof(type), ptr, o, n)
|
||||
#define M_MEMORY_FREE(ctx, type, ptr, o) overloaded_free(sizeof(type), ptr, o)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Reference in new issue
Block a user