Remove obsolete m-i-shared.h header
This commit is contained in:
1 parent
7e8cb07a6c
commit
25dcdeed69
4 files changed
-588
No files matched your search
@@ -197,7 +197,6 @@ Finally, headers for compatibility with non C11 compilers:
|
||||
|
||||
The following headers are obsolete and will be removed in the next major release:
|
||||
* [m-concurrent.h](#m-concurrent): header for transforming a container into a concurrent container (thread safe),
|
||||
* [m-i-shared.h](#m-i-shared): header for creating intrusive shared pointer of generic type (Thread Safe).
|
||||
* [m-mempool.h](#m-mempool): header for creating specialized & fast memory allocator,
|
||||
|
||||
Each containers define their iterators (if it is meaningful).
|
||||
@@ -5085,184 +5084,6 @@ Create a new shared object initialized with its `INIT_SET` operator on the given
|
||||
This method is created only if the `INIT_SET` operator is defined.
|
||||
|
||||
|
||||
_________________
|
||||
|
||||
### M-I-SHARED
|
||||
|
||||
> [!NOTE]
|
||||
> This header is obsolete: M-SHARED-PTR should be used instead.
|
||||
|
||||
This header is for creating intrusive shared pointer.
|
||||
|
||||
#### `ISHARED_PTR_INTERFACE(name, type)`
|
||||
|
||||
Extend the definition of the structure of an object of type `type` by adding the
|
||||
necessary interface to handle it as a shared pointer named `name`.
|
||||
It shall be put within the structure definition of the object (See example).
|
||||
|
||||
#### `ISHARED_PTR_STATIC_INIT(name, type)`
|
||||
|
||||
Provide the static initialization value of an object defined with a
|
||||
`ISHARED_PTR_INTERFACE` extra fields. It shall be used only for global
|
||||
variables with the _init_once function.
|
||||
|
||||
Usage (provided that the interface is used as the first element of the structure):
|
||||
|
||||
```C
|
||||
struct mystruct variable = { ISHARED_PTR_STATIC_INIT(ishared_double, struct mystruct) };
|
||||
```
|
||||
|
||||
#### `ISHARED_PTR_STATIC_DESIGNATED_INIT(name, type)`
|
||||
|
||||
Provide the static initialization value of an object defined with a
|
||||
`ISHARED_PTR_INTERFACE` extra fields. It shall be used only for global
|
||||
variables with the _init_once function.
|
||||
|
||||
It uses designated initializers to set the right fields.
|
||||
|
||||
Usage:
|
||||
|
||||
```C
|
||||
struct mystruct variable = {ISHARED_PTR_STATIC_DESIGNATED_INIT(ishared_double, struct mystruct) };
|
||||
```
|
||||
|
||||
#### `ISHARED_PTR_DEF(name, type[, oplist])`
|
||||
#### `ISHARED_PTR_DEF_AS(name, name_t, type[, oplist])`
|
||||
|
||||
Define the associated methods to handle the shared pointer named `name`
|
||||
as `static inline` functions.
|
||||
A shared pointer is a mechanism to keep tracks of all `users` of an object
|
||||
and performs an automatic destruction of the object whenever all users release
|
||||
their need on this object.
|
||||
|
||||
The destruction of the object is thread safe and occurs when the last user
|
||||
of the object releases it. The destruction of the object implies:
|
||||
|
||||
* calling the `CLEAR` operator to clear the object,
|
||||
* calling the `DEL` operator to release the memory used by the object
|
||||
(if the method has not been disabled).
|
||||
|
||||
The object oplist is expected to have the following operators (`CLEAR` and `DEL`),
|
||||
otherwise default methods are used. If there is no given oplist, the default
|
||||
operators are also used. The created methods will use the operators to init, set
|
||||
and clear the contained object.
|
||||
|
||||
There are designed to work with buffers with policy `BUFFER_PUSH_INIT_POP_MOVE`
|
||||
to send a shared pointer across multiple threads.
|
||||
|
||||
It is recommended to use the intrusive shared pointer over the standard one if
|
||||
possible. They are faster and cleaner.
|
||||
|
||||
The default is to use heap allocated entities, which are allocated by `NEW` and
|
||||
freed by `DEL`.
|
||||
|
||||
It can be used for statically allocated entities. However, in this case,
|
||||
you shall disable the operator `NEW` and `DEL` when expanding the oplist
|
||||
so that the destruction doesn't try to free the objects, like this:
|
||||
|
||||
```C
|
||||
(NEW(0), DEL(0))
|
||||
```
|
||||
|
||||
`NEW` and `DEL` operators shall be either both defined, or both disabled.
|
||||
|
||||
`ISHARED_PTR_DEF_AS` is the same as `ISHARED_PTR_DEF` except the name of the type `name_t`
|
||||
is provided.
|
||||
|
||||
Example (dynamic):
|
||||
|
||||
```C
|
||||
typedef struct mystruct_s {
|
||||
ISHARED_PTR_INTERFACE(ishared_mystruct, struct mystruct_s);
|
||||
char *message;
|
||||
} mystruct_t;
|
||||
|
||||
static inline void mystruct_init(mystruct_t *p) { p->message = NULL; }
|
||||
static inline void mystruct_clear(mystruct_t *p) { free(p->message); }
|
||||
|
||||
ISHARED_PTR_DEF(ishared_mystruct, mystruct_t, (INIT(mystruct_init), CLEAR(mystruct_clear M_IPTR)))
|
||||
|
||||
void f(void) {
|
||||
mystruct_t *p = ishared_mystruct_init_new();
|
||||
p->message = strdup ("Hello");
|
||||
buffer_mystruct_push(g_buff1, p);
|
||||
buffer_mystruct_push(g_buff2, p);
|
||||
ishared_mystruct_clear(p);
|
||||
}
|
||||
```
|
||||
|
||||
#### Created types
|
||||
|
||||
The following types are automatically defined by the previous definition macro if not provided by the user:
|
||||
|
||||
##### `name_t`
|
||||
|
||||
It will define name_t as a pointer to shared counted object.
|
||||
This is a synonymous to a pointer to the object.
|
||||
|
||||
#### Specialized methods
|
||||
|
||||
The following specialized methods are automatically created by the previous definition macro:
|
||||
|
||||
##### `name_t name_init(type *object)`
|
||||
|
||||
Return a shared pointer to `object` which owns `object`.
|
||||
It initializes the private fields of `object` handling the shared pointer,
|
||||
returning the same pointer to the object from a value point of view,
|
||||
but with the shared pointer field initialized.
|
||||
|
||||
As a consequence, the shared pointer part of `object` shall not have been initialized yet.
|
||||
The other part of `object` may or may not be initialized before calling this method.
|
||||
|
||||
##### `name_t name_init_set(name_t shared)`
|
||||
|
||||
Return a new shared pointer to the same object than the one pointed by `shared`,
|
||||
incrementing the ownership of the object.
|
||||
This function is thread safe.
|
||||
|
||||
##### `name_t name_init_new(void)`
|
||||
|
||||
Allocate a new object, initialize it and return an initialized shared pointer to it.
|
||||
The used allocation function is the `NEW` operator.
|
||||
|
||||
This method is only created if the `INIT` and `NEW` methods are provided and not disabled.
|
||||
|
||||
##### `name_t name_init_once(type *object)`
|
||||
|
||||
Initialize the new object `object` and return an initialized shared pointer to it.
|
||||
The `INIT` operator of `object` is ensured to be called only once,
|
||||
even if multiple threads try to initialize it at the same time.
|
||||
Once the object is fully cleared, the initialization function may occur once again.
|
||||
|
||||
`object` shall be a global variable initialized with the
|
||||
`ISHARED_PTR_STATIC_INIT` macro.
|
||||
|
||||
This method is only created if the `INIT` and `NEW` methods are provided and not disabled.
|
||||
|
||||
##### `void name_clear(name_t shared)`
|
||||
|
||||
Clear the `shared` pointer, releasing ownership of the object
|
||||
and destroying the shared object if no longer
|
||||
any other `shared` pointers own it.
|
||||
This function is thread safe.
|
||||
|
||||
##### `void name_clear_ptr(name_t *shared)`
|
||||
|
||||
Clear the shared pointer `*shared`, releasing ownership of the object
|
||||
and destroying the shared object if no longer
|
||||
any other `shared` pointers own it.
|
||||
This function is thread safe.
|
||||
Afterwards, `*shared` is set to NULL.
|
||||
|
||||
##### `void name_set(name_t *shared1, name_t shared2)`
|
||||
|
||||
Update the shared pointer `*shared1` to point to the same object than
|
||||
the shared pointer `shared2`.
|
||||
Destroy the shared object pointed by `*shared1` if no longer any other shared
|
||||
pointers own it, set the shared pointer `shared` to the same object
|
||||
than the one pointed by `src`.
|
||||
This function is thread safe.
|
||||
|
||||
_________________
|
||||
|
||||
### M-I-LIST
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "m-generic.h"
|
||||
#include "m-genint.h"
|
||||
#include "m-i-list.h"
|
||||
#include "m-i-shared.h"
|
||||
#include "m-list.h"
|
||||
#include "m-mempool.h"
|
||||
#include "m-prioqueue.h"
|
||||
|
||||
-258
@@ -1,258 +0,0 @@
|
||||
/*
|
||||
* M*LIB - INTRUSIVE SHARED PTR Module
|
||||
*
|
||||
* Copyright (c) 2017-2025, Patrick Pelissier
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* + Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* + Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef MSTARLIB_I_SHARED_PTR_H
|
||||
#define MSTARLIB_I_SHARED_PTR_H
|
||||
|
||||
#include "m-core.h"
|
||||
#include "m-atomic.h"
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L
|
||||
#warning The header m-i-shared.h is obsolete. Use m-shared-ptr header instead.
|
||||
#endif
|
||||
|
||||
M_BEGIN_PROTECTED_CODE
|
||||
|
||||
/* Define the oplist of a intrusive shared pointer.
|
||||
USAGE: ISHARED_OPLIST(name [, oplist_of_the_type]) */
|
||||
#define M_ISHARED_PTR_OPLIST(...) \
|
||||
M_ISHAR3D_PTR_OPLIST_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((__VA_ARGS__, M_BASIC_OPLIST), \
|
||||
(__VA_ARGS__ )))
|
||||
|
||||
|
||||
/* Interface to add to a structure to allow intrusive support.
|
||||
name: name of the intrusive shared pointer.
|
||||
type: name of the type of the structure (aka. struct test_s) - not used currently.
|
||||
NOTE: There can be only one interface of this kind in a type! */
|
||||
#define M_ISHARED_PTR_INTERFACE(name, type) \
|
||||
atomic_int M_F(name, _cpt)
|
||||
|
||||
|
||||
/* Value of the interface field for static initialization (Uses C99 designated element). */
|
||||
#define M_ISHARED_PTR_STATIC_DESIGNATED_INIT(name, type) \
|
||||
.M_F(name, _cpt) = M_ATOMIC_VAR_INIT(0)
|
||||
|
||||
/* Value of the interface field for static initialization (Uses C89 designated element). */
|
||||
#define M_ISHARED_PTR_STATIC_INIT(name, type) \
|
||||
M_ATOMIC_VAR_INIT(0)
|
||||
|
||||
|
||||
/* Define the intrusive shared pointer type and its M_INLINE functions.
|
||||
USAGE: ISHARED_PTR_DEF(name, type, [, oplist]) */
|
||||
#define M_ISHARED_PTR_DEF(name, ...) \
|
||||
M_ISHARED_PTR_DEF_AS(name, M_F(name,_t), __VA_ARGS__)
|
||||
|
||||
|
||||
/* Define the intrusive shared pointer type and its M_INLINE functions
|
||||
as the name name_t
|
||||
USAGE: ISHARED_PTR_DEF_AS(name, name_t, type, [, oplist]) */
|
||||
#define M_ISHARED_PTR_DEF_AS(name, name_t, ...) \
|
||||
M_BEGIN_PROTECTED_CODE \
|
||||
M_ISHAR3D_PTR_DEF_P1(M_IF_NARGS_EQ1(__VA_ARGS__) \
|
||||
((name, __VA_ARGS__, M_GLOBAL_OPLIST_OR_DEF(__VA_ARGS__)(), name_t ), \
|
||||
(name, __VA_ARGS__ , name_t ))) \
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************** INTERNAL ***********************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
// Deferred evaluation
|
||||
#define M_ISHAR3D_PTR_OPLIST_P1(arg) M_ISHAR3D_PTR_OPLIST_P2 arg
|
||||
|
||||
/* Validation of the given oplist */
|
||||
#define M_ISHAR3D_PTR_OPLIST_P2(name, oplist) \
|
||||
M_IF_OPLIST(oplist)(M_ISHAR3D_PTR_OPLIST_P3, M_ISHAR3D_PTR_OPLIST_FAILURE)(name, oplist)
|
||||
|
||||
/* Prepare a clean compilation failure */
|
||||
#define M_ISHAR3D_PTR_OPLIST_FAILURE(name, oplist) \
|
||||
((M_LIB_ERROR(ARGUMENT_OF_ISHARED_PTR_OPLIST_IS_NOT_AN_OPLIST, name, oplist)))
|
||||
|
||||
// Define the oplist
|
||||
#define M_ISHAR3D_PTR_OPLIST_P3(name, oplist) ( \
|
||||
INIT(M_INIT_DEFAULT), \
|
||||
INIT_SET(API_4(M_F(name, _init_set))), \
|
||||
SET(M_F(name, _set) M_IPTR), \
|
||||
CLEAR(M_F(name, _clear)), \
|
||||
RESET(M_F(name, _reset) M_IPTR), \
|
||||
NAME(name), \
|
||||
TYPE(M_F(name, _ct)), GENTYPE(struct M_F(name,_s)*), \
|
||||
OPLIST(oplist), \
|
||||
SUBTYPE(M_F(name, _subtype_ct)) \
|
||||
)
|
||||
|
||||
|
||||
/******************************** INTERNAL ***********************************/
|
||||
|
||||
// Deferred evaluation
|
||||
#define M_ISHAR3D_PTR_DEF_P1(arg) M_ID( M_ISHAR3D_PTR_DEF_P2 arg )
|
||||
|
||||
/* Validate the oplist before going further */
|
||||
#define M_ISHAR3D_PTR_DEF_P2(name, type, oplist, shared_t) \
|
||||
M_IF_OPLIST(oplist)(M_ISHAR3D_PTR_DEF_P3, M_ISHAR3D_PTR_DEF_FAILURE)(name, type, oplist, shared_t)
|
||||
|
||||
/* Stop processing with a compilation failure */
|
||||
#define M_ISHAR3D_PTR_DEF_FAILURE(name, type, oplist, shared_t) \
|
||||
M_STATIC_FAILURE(M_LIB_NOT_AN_OPLIST, "(ISHARED_PTR_DEF): the given argument is not a valid oplist: " #oplist)
|
||||
|
||||
#define M_ISHAR3D_PTR_DEF_P3(name, type, oplist, shared_t) \
|
||||
M_ISHAR3D_PTR_DEF_TYPE(name, type, oplist, shared_t) \
|
||||
M_CHECK_COMPATIBLE_OPLIST(name, 1, type, oplist) \
|
||||
M_ISHAR3D_PTR_DEF_CORE(name, type, oplist, shared_t) \
|
||||
|
||||
/* Define the types */
|
||||
#define M_ISHAR3D_PTR_DEF_TYPE(name, type, oplist, shared_t) \
|
||||
\
|
||||
/* The shared pointer is only a pointer to the type */ \
|
||||
typedef type *shared_t; \
|
||||
\
|
||||
/* Define internal types for oplist */ \
|
||||
typedef shared_t M_F(name, _ct); \
|
||||
typedef type M_F(name, _subtype_ct); \
|
||||
|
||||
/* Define the core functions */
|
||||
#define M_ISHAR3D_PTR_DEF_CORE(name, type, oplist, shared_t) \
|
||||
\
|
||||
M_INLINE shared_t \
|
||||
M_F(name, _init)(type *ptr) \
|
||||
{ \
|
||||
/* Initialize the type referenced by the pointer */ \
|
||||
if (M_LIKELY (ptr != NULL)) { \
|
||||
atomic_init(&ptr->M_F(name, _cpt), 2); \
|
||||
} \
|
||||
return ptr; \
|
||||
} \
|
||||
\
|
||||
M_INLINE shared_t \
|
||||
M_F(name, _init_set)(shared_t shared) \
|
||||
{ \
|
||||
if (M_LIKELY (shared != NULL)) { \
|
||||
int n = atomic_fetch_add(&(shared->M_F(name, _cpt)), 2); \
|
||||
(void) n; \
|
||||
} \
|
||||
return shared; \
|
||||
} \
|
||||
\
|
||||
M_IF_METHOD(INIT, oplist)( \
|
||||
M_IF_DISABLED_METHOD(NEW, oplist) \
|
||||
( \
|
||||
/* This function is only for static object */ \
|
||||
M_INLINE shared_t \
|
||||
M_F(name, _init_once)(type *shared) \
|
||||
{ \
|
||||
if (M_LIKELY (shared != NULL)) { \
|
||||
/* Pretty much like atomic_add, except the first one increment by 1, others by 2 */ \
|
||||
int o = atomic_load(&(shared->M_F(name, _cpt))); \
|
||||
int n; \
|
||||
do { \
|
||||
n = o + 1 + (o != 0); \
|
||||
} while (!atomic_compare_exchange_strong(&(shared->M_F(name, _cpt)), &o, n)); \
|
||||
if (o == 0) { \
|
||||
/* Partial initialization: _cpt is odd */ \
|
||||
/* Call the INIT function once */ \
|
||||
M_CALL_INIT(oplist, *shared); \
|
||||
/* Finish initialization: _cpt is even */ \
|
||||
atomic_fetch_add(&(shared->M_F(name, _cpt)), 1); \
|
||||
} else if ( (o&1) != 0) { \
|
||||
/* Not fully initialized yet: wait for initialization */ \
|
||||
m_core_backoff_ct bkoff; \
|
||||
m_core_backoff_init(bkoff); \
|
||||
/* Wait for _cpt to be _even */ \
|
||||
while ((atomic_load(&(shared->M_F(name, _cpt)))&1) != 0 ) { \
|
||||
m_core_backoff_wait(bkoff); \
|
||||
} \
|
||||
} \
|
||||
M_ASSERT( (atomic_load(&(shared->M_F(name, _cpt)))&1) == 0); \
|
||||
} \
|
||||
return shared; \
|
||||
} \
|
||||
, \
|
||||
/* This function is only for dynamic object */ \
|
||||
M_INLINE shared_t \
|
||||
M_F(name, _init_new)(void) \
|
||||
{ \
|
||||
type *ptr = M_CALL_NEW(oplist, type); \
|
||||
if (M_UNLIKELY_NOMEM (ptr == NULL)) { \
|
||||
M_MEMORY_FULL(type, 1); \
|
||||
} \
|
||||
M_CALL_INIT(oplist, *ptr); \
|
||||
atomic_init (&ptr->M_F(name, _cpt), 2); \
|
||||
return ptr; \
|
||||
} \
|
||||
/* End of NEW */) \
|
||||
, /* End of INIT */) \
|
||||
\
|
||||
M_INLINE void \
|
||||
M_F(name, _clear)(shared_t shared) \
|
||||
{ \
|
||||
if (shared != NULL) { \
|
||||
if (atomic_fetch_sub(&(shared->M_F(name, _cpt)), 2) == 2) { \
|
||||
M_CALL_CLEAR(oplist, *shared); \
|
||||
M_IF_DISABLED_METHOD(DEL, oplist)(, M_CALL_DEL(oplist, shared);) \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
M_INLINE void \
|
||||
M_F(name, _clear_ptr)(shared_t *shared) \
|
||||
{ \
|
||||
M_ASSERT(shared != NULL); \
|
||||
M_F(name, _clear)(*shared); \
|
||||
*shared = NULL; \
|
||||
} \
|
||||
\
|
||||
M_INLINE void \
|
||||
M_F(name, _reset)(shared_t *shared) \
|
||||
{ \
|
||||
M_F(name, _clear)(*shared); \
|
||||
*shared = NULL; \
|
||||
} \
|
||||
\
|
||||
M_INLINE void \
|
||||
M_F(name, _set)(shared_t *ptr, shared_t shared) \
|
||||
{ \
|
||||
M_ASSERT (ptr != NULL); \
|
||||
if (M_LIKELY (*ptr != shared)) { \
|
||||
M_F(name, _clear)(*ptr); \
|
||||
*ptr = M_F(name, _init_set)(shared); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
|
||||
M_END_PROTECTED_CODE
|
||||
|
||||
/******************************** INTERNAL ***********************************/
|
||||
|
||||
#if M_USE_SMALL_NAME
|
||||
#define ISHARED_PTR_OPLIST M_ISHARED_PTR_OPLIST
|
||||
#define ISHARED_PTR_INTERFACE M_ISHARED_PTR_INTERFACE
|
||||
#define ISHARED_PTR_STATIC_DESIGNATED_INIT M_ISHARED_PTR_STATIC_DESIGNATED_INIT
|
||||
#define ISHARED_PTR_STATIC_INIT M_ISHARED_PTR_STATIC_INIT
|
||||
#define ISHARED_PTR_DEF M_ISHARED_PTR_DEF
|
||||
#define ISHARED_PTR_DEF_AS M_ISHARED_PTR_DEF_AS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2025, Patrick Pelissier
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* + Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* + Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "test-obj.h"
|
||||
#include "m-i-shared.h"
|
||||
#include "m-thread.h"
|
||||
#include "coverage.h"
|
||||
|
||||
typedef struct ishared_s {
|
||||
ISHARED_PTR_INTERFACE(ishared1, struct ishared_s);
|
||||
ISHARED_PTR_INTERFACE(ishared2, struct ishared_s);
|
||||
int data[100];
|
||||
} ishared_t[1];
|
||||
|
||||
static bool ishared_init_sleep = false;
|
||||
|
||||
static void ishared_init_data(struct ishared_s *x)
|
||||
{
|
||||
for(int i = 0 ; i < 100; i++)
|
||||
x->data[i] = i * i;
|
||||
if (ishared_init_sleep) {
|
||||
// Slow down init
|
||||
m_thread_sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
static void ishared_test(struct ishared_s *x)
|
||||
{
|
||||
for(int i = 0 ; i < 100; i++) {
|
||||
assert (x->data[i] == i*i);
|
||||
}
|
||||
}
|
||||
|
||||
START_COVERAGE
|
||||
ISHARED_PTR_DEF(ishared1, struct ishared_s, (INIT(API_2(ishared_init_data))))
|
||||
ISHARED_PTR_DEF(ishared2, struct ishared_s, (INIT(API_2(ishared_init_data)), NEW(0), DEL(0)) )
|
||||
END_COVERAGE
|
||||
|
||||
/*ISHARED_PTR_DEF_AS(SharedDouble, SharedDouble, double) */
|
||||
|
||||
static void test_single(void)
|
||||
{
|
||||
ishared1_t p1, p2;
|
||||
p1 = ishared1_init_new();
|
||||
ishared_test(p1);
|
||||
p2 = ishared1_init_set(p1);
|
||||
ishared_test(p2);
|
||||
ishared1_clear(p1);
|
||||
ishared_test(p2);
|
||||
|
||||
p1 = ishared1_init(NULL);
|
||||
ishared1_set(&p1, p2);
|
||||
ishared1_reset(&p2);
|
||||
assert(p2 == NULL);
|
||||
ishared_test(p1);
|
||||
ishared1_clear(p1);
|
||||
|
||||
p1 = ishared1_init_set(p2);
|
||||
assert(p1 == NULL);
|
||||
ishared1_clear(p1);
|
||||
|
||||
ishared1_clear(p2);
|
||||
|
||||
struct ishared_s *x = (struct ishared_s *) malloc(sizeof (struct ishared_s));
|
||||
assert(x != NULL);
|
||||
ishared_init_data(x);
|
||||
p1 = ishared1_init(x);
|
||||
ishared_test(p1);
|
||||
ishared1_clear(p1);
|
||||
}
|
||||
|
||||
static struct ishared_s g_var = {
|
||||
ISHARED_PTR_STATIC_INIT(ishared1, struct ishared_s),
|
||||
ISHARED_PTR_STATIC_INIT(ishared2, struct ishared_s),
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void test_static(void)
|
||||
{
|
||||
ishared2_t p1, p2;
|
||||
p1 = ishared2_init_once(NULL);
|
||||
assert(p1 == NULL);
|
||||
p1 = ishared2_init_once(&g_var);
|
||||
ishared_test(p1);
|
||||
p2 = ishared2_init_once(&g_var);
|
||||
ishared_test(p2);
|
||||
ishared2_clear(p1);
|
||||
ishared_test(p2);
|
||||
ishared2_clear(p2);
|
||||
}
|
||||
|
||||
#define MAX_THREAD 128
|
||||
#define MAX_VAR 5
|
||||
|
||||
#define VAL(x) { ISHARED_PTR_STATIC_INIT(ishared1, struct ishared_s), ISHARED_PTR_STATIC_INIT(ishared2, struct ishared_s), { 0 } }
|
||||
static struct ishared_s g_tab[MAX_VAR] = {
|
||||
M_MAP_C(VAL, M_SEQ(1, MAX_VAR))
|
||||
};
|
||||
|
||||
static void func(void *arg)
|
||||
{
|
||||
int id = (int)(intptr_t) arg;
|
||||
int v = id % MAX_VAR;
|
||||
ishared2_t p = ishared2_init_once(&g_tab[v]);
|
||||
for(int i = 0; i < 100; i++) {
|
||||
ishared_test(p);
|
||||
}
|
||||
ishared2_clear(p);
|
||||
}
|
||||
|
||||
static void test_shared(void)
|
||||
{
|
||||
m_thread_t id[MAX_THREAD];
|
||||
|
||||
ishared_init_sleep = true;
|
||||
for(int i = 0; i < MAX_THREAD; i++) {
|
||||
m_thread_create(id[i], func, (void*) (intptr_t) i);
|
||||
}
|
||||
for(int i = 0; i < MAX_THREAD; i++) {
|
||||
m_thread_join(id[i]);
|
||||
}
|
||||
ishared_init_sleep = false;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_single();
|
||||
test_static();
|
||||
test_shared();
|
||||
exit(0);
|
||||
}
|
||||
Reference in new issue
Block a user