forked from enlightenment/efl
eina: add eina_mempool_repack.
WARNING: HIGHLY UNTESTED PIECE OF CODE ! USE IT AT YOUR OWN RISK ! SVN revision: 58554
This commit is contained in:
parent
8e68291273
commit
29639eea35
|
@ -45,3 +45,4 @@
|
||||||
2011-05-11 Cedric Bail
|
2011-05-11 Cedric Bail
|
||||||
|
|
||||||
* Add eina_inlist_sort.
|
* Add eina_inlist_sort.
|
||||||
|
* Add eina_mempool_repack.
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct _Eina_Mempool_Backend
|
||||||
void (*garbage_collect)(void *data);
|
void (*garbage_collect)(void *data);
|
||||||
void (*statistics)(void *data);
|
void (*statistics)(void *data);
|
||||||
void (*shutdown)(void *data);
|
void (*shutdown)(void *data);
|
||||||
|
void (*repack)(void *data, Eina_Mempool_Repack_Cb cb, void *cb_data);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Eina_Mempool
|
struct _Eina_Mempool
|
||||||
|
|
|
@ -84,6 +84,14 @@ typedef struct _Eina_Mempool Eina_Mempool;
|
||||||
*/
|
*/
|
||||||
typedef struct _Eina_Mempool_Backend Eina_Mempool_Backend;
|
typedef struct _Eina_Mempool_Backend Eina_Mempool_Backend;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Eina_Mempool_Repack_Cb
|
||||||
|
* Type for a callback who need to unreference an old object from a mempool
|
||||||
|
* and reference the new one instead. Memcpy is taken care by the mempool.
|
||||||
|
*/
|
||||||
|
typedef void (*Eina_Mempool_Repack_Cb)(void *dst, void *src, void *data);
|
||||||
|
|
||||||
EAPI extern Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE;
|
EAPI extern Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE;
|
||||||
|
|
||||||
EAPI Eina_Mempool *eina_mempool_add(const char *module, const char *context, const char *options, ...) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
EAPI Eina_Mempool *eina_mempool_add(const char *module, const char *context, const char *options, ...) EINA_MALLOC EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||||
|
@ -93,6 +101,9 @@ static inline void *eina_mempool_realloc(Eina_Mempool *mp, void *element, unsign
|
||||||
static inline void *eina_mempool_malloc(Eina_Mempool *mp, unsigned int size) EINA_MALLOC EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
|
static inline void *eina_mempool_malloc(Eina_Mempool *mp, unsigned int size) EINA_MALLOC EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
|
||||||
static inline void eina_mempool_free(Eina_Mempool *mp, void *element) EINA_ARG_NONNULL(1);
|
static inline void eina_mempool_free(Eina_Mempool *mp, void *element) EINA_ARG_NONNULL(1);
|
||||||
|
|
||||||
|
EAPI void eina_mempool_repack(Eina_Mempool *mp,
|
||||||
|
Eina_Mempool_Repack_Cb cb,
|
||||||
|
void *data) EINA_ARG_NONNULL(1, 2);
|
||||||
EAPI void eina_mempool_gc(Eina_Mempool *mp) EINA_ARG_NONNULL(1);
|
EAPI void eina_mempool_gc(Eina_Mempool *mp) EINA_ARG_NONNULL(1);
|
||||||
EAPI void eina_mempool_statistics(Eina_Mempool *mp) EINA_ARG_NONNULL(1);
|
EAPI void eina_mempool_statistics(Eina_Mempool *mp) EINA_ARG_NONNULL(1);
|
||||||
|
|
||||||
|
|
|
@ -319,6 +319,14 @@ EAPI void eina_mempool_del(Eina_Mempool *mp)
|
||||||
free(mp);
|
free(mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAPI void eina_mempool_repack(Eina_Mempool *mp, Eina_Mempool_Repack_Cb cb, void *data)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(mp);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(mp->backend.shutdown);
|
||||||
|
DBG("mp=%p", mp);
|
||||||
|
mp->backend.repack(mp->backend_data, cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
EAPI void eina_mempool_gc(Eina_Mempool *mp)
|
EAPI void eina_mempool_gc(Eina_Mempool *mp)
|
||||||
{
|
{
|
||||||
EINA_SAFETY_ON_NULL_RETURN(mp);
|
EINA_SAFETY_ON_NULL_RETURN(mp);
|
||||||
|
|
|
@ -94,6 +94,8 @@
|
||||||
#define EINA_MAGIC_SIMPLE_XML_DATA 0x98761261
|
#define EINA_MAGIC_SIMPLE_XML_DATA 0x98761261
|
||||||
#define EINA_MAGIC_SIMPLE_XML_ATTRIBUTE 0x98761262
|
#define EINA_MAGIC_SIMPLE_XML_ATTRIBUTE 0x98761262
|
||||||
|
|
||||||
|
#define EINA_MAGIC_CLASS 0x9877CB30
|
||||||
|
|
||||||
/* undef the following, we want out version */
|
/* undef the following, we want out version */
|
||||||
#undef FREE
|
#undef FREE
|
||||||
#define FREE(ptr) \
|
#define FREE(ptr) \
|
||||||
|
|
|
@ -269,7 +269,8 @@ static Eina_Mempool_Backend _backend = {
|
||||||
NULL, /* realloc */
|
NULL, /* realloc */
|
||||||
NULL, /* garbage collect */
|
NULL, /* garbage collect */
|
||||||
&_statistics,
|
&_statistics,
|
||||||
&_shutdown
|
&_shutdown,
|
||||||
|
NULL /* repack */
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool buddy_init(void)
|
Eina_Bool buddy_init(void)
|
||||||
|
|
|
@ -151,6 +151,94 @@ _eina_chained_mp_pool_free(Chained_Pool *p)
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_eina_chained_mempool_usage_cmp(const Eina_Inlist *l1, const Eina_Inlist *l2)
|
||||||
|
{
|
||||||
|
const Chained_Pool *p1;
|
||||||
|
const Chained_Pool *p2;
|
||||||
|
|
||||||
|
p1 = EINA_INLIST_CONTAINER_GET(l1, const Chained_Pool);
|
||||||
|
p2 = EINA_INLIST_CONTAINER_GET(l2, const Chained_Pool);
|
||||||
|
|
||||||
|
return p2->usage - p1->usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
_eina_chained_mempool_alloc_in(Chained_Mempool *pool, Chained_Pool *p)
|
||||||
|
{
|
||||||
|
void *mem;
|
||||||
|
|
||||||
|
if (p->last)
|
||||||
|
{
|
||||||
|
mem = p->last;
|
||||||
|
p->last += pool->item_alloc;
|
||||||
|
if (p->last >= p->limit)
|
||||||
|
p->last = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifndef NVALGRIND
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(p->base, pool->item_alloc);
|
||||||
|
#endif
|
||||||
|
// Request a free pointer
|
||||||
|
mem = eina_trash_pop(&p->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move to end - it just filled up
|
||||||
|
if (!p->base && !p->last)
|
||||||
|
pool->first = eina_inlist_demote(pool->first, EINA_INLIST_GET(p));
|
||||||
|
|
||||||
|
p->usage++;
|
||||||
|
pool->usage++;
|
||||||
|
|
||||||
|
#ifndef NVALGRIND
|
||||||
|
VALGRIND_MEMPOOL_ALLOC(pool, mem, pool->item_alloc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_chained_mempool_free_in(Chained_Mempool *pool, Chained_Pool *p, void *ptr)
|
||||||
|
{
|
||||||
|
void *pmem;
|
||||||
|
|
||||||
|
// pool mem base
|
||||||
|
pmem = (void *)(((unsigned char *)p) + sizeof(Chained_Pool));
|
||||||
|
|
||||||
|
// is it in pool mem?
|
||||||
|
if (ptr < pmem)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
INF("%p is inside the private part of %p pool from %p Chained_Mempool (could be the sign of a buffer underrun).", ptr, p, pool);
|
||||||
|
#endif
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// freed node points to prev free node
|
||||||
|
eina_trash_push(&p->base, ptr);
|
||||||
|
// next free node is now the one we freed
|
||||||
|
p->usage--;
|
||||||
|
pool->usage--;
|
||||||
|
if (p->usage == 0)
|
||||||
|
{
|
||||||
|
// free bucket
|
||||||
|
pool->first = eina_inlist_remove(pool->first, EINA_INLIST_GET(p));
|
||||||
|
pool->root = eina_rbtree_inline_remove(pool->root, EINA_RBTREE_GET(p),
|
||||||
|
_eina_chained_mp_pool_cmp, NULL);
|
||||||
|
_eina_chained_mp_pool_free(p);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// move to front
|
||||||
|
pool->first = eina_inlist_promote(pool->first, EINA_INLIST_GET(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
eina_chained_mempool_malloc(void *data, __UNUSED__ unsigned int size)
|
eina_chained_mempool_malloc(void *data, __UNUSED__ unsigned int size)
|
||||||
{
|
{
|
||||||
|
@ -210,28 +298,7 @@ eina_chained_mempool_malloc(void *data, __UNUSED__ unsigned int size)
|
||||||
_eina_chained_mp_pool_cmp, NULL);
|
_eina_chained_mp_pool_cmp, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->last)
|
mem = _eina_chained_mempool_alloc_in(pool, p);
|
||||||
{
|
|
||||||
mem = p->last;
|
|
||||||
p->last += pool->item_alloc;
|
|
||||||
if (p->last >= p->limit)
|
|
||||||
p->last = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifndef NVALGRIND
|
|
||||||
VALGRIND_MAKE_MEM_DEFINED(p->base, pool->item_alloc);
|
|
||||||
#endif
|
|
||||||
// Request a free pointer
|
|
||||||
mem = eina_trash_pop(&p->base);
|
|
||||||
}
|
|
||||||
|
|
||||||
// move to end - it just filled up
|
|
||||||
if (!p->base && !p->last)
|
|
||||||
pool->first = eina_inlist_demote(pool->first, EINA_INLIST_GET(p));
|
|
||||||
|
|
||||||
p->usage++;
|
|
||||||
pool->usage++;
|
|
||||||
|
|
||||||
#ifdef EFL_HAVE_THREADS
|
#ifdef EFL_HAVE_THREADS
|
||||||
if (_threads_activated)
|
if (_threads_activated)
|
||||||
|
@ -244,10 +311,6 @@ eina_chained_mempool_malloc(void *data, __UNUSED__ unsigned int size)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NVALGRIND
|
|
||||||
VALGRIND_MEMPOOL_ALLOC(pool, mem, pool->item_alloc);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +320,6 @@ eina_chained_mempool_free(void *data, void *ptr)
|
||||||
Chained_Mempool *pool = data;
|
Chained_Mempool *pool = data;
|
||||||
Eina_Rbtree *r;
|
Eina_Rbtree *r;
|
||||||
Chained_Pool *p;
|
Chained_Pool *p;
|
||||||
void *pmem;
|
|
||||||
|
|
||||||
// look 4 pool
|
// look 4 pool
|
||||||
|
|
||||||
|
@ -290,36 +352,7 @@ eina_chained_mempool_free(void *data, void *ptr)
|
||||||
|
|
||||||
p = EINA_RBTREE_CONTAINER_GET(r, Chained_Pool);
|
p = EINA_RBTREE_CONTAINER_GET(r, Chained_Pool);
|
||||||
|
|
||||||
// pool mem base
|
_eina_chained_mempool_free_in(pool, p, ptr);
|
||||||
pmem = (void *)(((unsigned char *)p) + sizeof(Chained_Pool));
|
|
||||||
|
|
||||||
// is it in pool mem?
|
|
||||||
if (ptr < pmem)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
INF("%p is inside the private part of %p pool from %p Chained_Mempool (could be the sign of a buffer underrun).", ptr, p, pool);
|
|
||||||
#endif
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// freed node points to prev free node
|
|
||||||
eina_trash_push(&p->base, ptr);
|
|
||||||
// next free node is now the one we freed
|
|
||||||
p->usage--;
|
|
||||||
pool->usage--;
|
|
||||||
if (p->usage == 0)
|
|
||||||
{
|
|
||||||
// free bucket
|
|
||||||
pool->first = eina_inlist_remove(pool->first, EINA_INLIST_GET(p));
|
|
||||||
pool->root = eina_rbtree_inline_remove(pool->root, EINA_RBTREE_GET(p),
|
|
||||||
_eina_chained_mp_pool_cmp, NULL);
|
|
||||||
_eina_chained_mp_pool_free(p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// move to front
|
|
||||||
pool->first = eina_inlist_promote(pool->first, EINA_INLIST_GET(p));
|
|
||||||
}
|
|
||||||
|
|
||||||
on_error:
|
on_error:
|
||||||
#ifndef NVALGRIND
|
#ifndef NVALGRIND
|
||||||
|
@ -342,6 +375,111 @@ eina_chained_mempool_free(void *data, void *ptr)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eina_chained_mempool_repack(void *data,
|
||||||
|
Eina_Mempool_Repack_Cb cb,
|
||||||
|
void *cb_data)
|
||||||
|
{
|
||||||
|
Chained_Mempool *pool = data;
|
||||||
|
Chained_Pool *start;
|
||||||
|
Chained_Pool *tail;
|
||||||
|
|
||||||
|
/* FIXME: Improvement - per Chained_Pool lock */
|
||||||
|
|
||||||
|
#ifdef EFL_HAVE_THREADS
|
||||||
|
if (_threads_activated)
|
||||||
|
{
|
||||||
|
# ifdef EFL_HAVE_POSIX_THREADS
|
||||||
|
pthread_mutex_lock(&pool->mutex);
|
||||||
|
# else
|
||||||
|
WaitForSingleObject(pool->mutex, INFINITE);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#ifdef EFL_DEBUG_THREADS
|
||||||
|
else
|
||||||
|
assert(pthread_equal(pool->self, pthread_self()));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pool->first = eina_inlist_sort(pool->first,
|
||||||
|
(Eina_Compare_Cb) _eina_chained_mempool_usage_cmp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
idea : remove the almost empty pool at the beginning of the list by
|
||||||
|
moving data in the last pool with empty slot
|
||||||
|
*/
|
||||||
|
tail = EINA_INLIST_CONTAINER_GET(pool->first->last, Chained_Pool);
|
||||||
|
while (tail && tail->usage == pool->pool_size)
|
||||||
|
tail = EINA_INLIST_CONTAINER_GET((EINA_INLIST_GET(tail)->prev), Chained_Pool);
|
||||||
|
|
||||||
|
while (tail)
|
||||||
|
{
|
||||||
|
unsigned char *src;
|
||||||
|
unsigned char *dst;
|
||||||
|
|
||||||
|
start = EINA_INLIST_CONTAINER_GET(pool->first, Chained_Pool);
|
||||||
|
|
||||||
|
if (start == tail || start->usage == pool->pool_size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (src = start->limit - pool->group_size;
|
||||||
|
src != start->limit;
|
||||||
|
src += pool->item_alloc)
|
||||||
|
{
|
||||||
|
Eina_Bool is_free = EINA_FALSE;
|
||||||
|
Eina_Bool is_dead;
|
||||||
|
|
||||||
|
/* Do we have something inside that piece of memory */
|
||||||
|
if (start->last != NULL && src >= start->last)
|
||||||
|
{
|
||||||
|
is_free = EINA_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Eina_Trash *over = start->base;
|
||||||
|
|
||||||
|
while (over != NULL && (unsigned char*) over != src)
|
||||||
|
over = over->next;
|
||||||
|
|
||||||
|
if (over == NULL)
|
||||||
|
is_free = EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_free) continue ;
|
||||||
|
|
||||||
|
/* get a new memory pointer from the latest most occuped pool */
|
||||||
|
dst = _eina_chained_mempool_alloc_in(pool, tail);
|
||||||
|
/* move data from one to another */
|
||||||
|
memcpy(dst, src, pool->item_alloc);
|
||||||
|
/* notify caller */
|
||||||
|
cb(dst, src, cb_data);
|
||||||
|
/* destroy old pointer */
|
||||||
|
is_dead = _eina_chained_mempool_free_in(pool, start, src);
|
||||||
|
|
||||||
|
/* search last tail with empty slot */
|
||||||
|
while (tail && tail->usage == pool->pool_size)
|
||||||
|
tail = EINA_INLIST_CONTAINER_GET((EINA_INLIST_GET(tail)->prev),
|
||||||
|
Chained_Pool);
|
||||||
|
/* no more free space */
|
||||||
|
if (!tail || tail == start) break;
|
||||||
|
if (is_dead) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: improvement - reorder pool so that the most used one get in front */
|
||||||
|
|
||||||
|
#ifdef EFL_HAVE_THREADS
|
||||||
|
if (_threads_activated)
|
||||||
|
{
|
||||||
|
# ifdef EFL_HAVE_POSIX_THREADS
|
||||||
|
pthread_mutex_unlock(&pool->mutex);
|
||||||
|
# else
|
||||||
|
ReleaseMutex(pool->mutex);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
eina_chained_mempool_realloc(__UNUSED__ void *data,
|
eina_chained_mempool_realloc(__UNUSED__ void *data,
|
||||||
__UNUSED__ void *element,
|
__UNUSED__ void *element,
|
||||||
|
@ -451,7 +589,8 @@ static Eina_Mempool_Backend _eina_chained_mp_backend = {
|
||||||
&eina_chained_mempool_realloc,
|
&eina_chained_mempool_realloc,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&eina_chained_mempool_shutdown
|
&eina_chained_mempool_shutdown,
|
||||||
|
&eina_chained_mempool_repack
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool chained_init(void)
|
Eina_Bool chained_init(void)
|
||||||
|
|
|
@ -153,7 +153,8 @@ static Eina_Mempool_Backend _eina_ememoa_mp_backend = {
|
||||||
.alloc = &eina_ememoa_fixed_malloc,
|
.alloc = &eina_ememoa_fixed_malloc,
|
||||||
.free = &eina_ememoa_fixed_free,
|
.free = &eina_ememoa_fixed_free,
|
||||||
.garbage_collect = &eina_ememoa_fixed_gc,
|
.garbage_collect = &eina_ememoa_fixed_gc,
|
||||||
.statistics = &eina_ememoa_fixed_statistics
|
.statistics = &eina_ememoa_fixed_statistics,
|
||||||
|
.repack = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool ememoa_fixed_init(void)
|
Eina_Bool ememoa_fixed_init(void)
|
||||||
|
|
|
@ -160,7 +160,8 @@ static Eina_Mempool_Backend _eina_ememoa_unknown_mp_backend = {
|
||||||
.alloc = &eina_ememoa_unknown_size_malloc,
|
.alloc = &eina_ememoa_unknown_size_malloc,
|
||||||
.free = &eina_ememoa_unknown_size_free,
|
.free = &eina_ememoa_unknown_size_free,
|
||||||
.garbage_collect = &eina_ememoa_unknown_size_gc,
|
.garbage_collect = &eina_ememoa_unknown_size_gc,
|
||||||
.statistics = &eina_ememoa_unknown_size_statistics
|
.statistics = &eina_ememoa_unknown_size_statistics,
|
||||||
|
.repack = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool ememoa_unknown_init(void)
|
Eina_Bool ememoa_unknown_init(void)
|
||||||
|
|
|
@ -247,7 +247,8 @@ static Eina_Mempool_Backend _eina_fixed_bitmap_mp_backend = {
|
||||||
&eina_fixed_bitmap_realloc,
|
&eina_fixed_bitmap_realloc,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&eina_fixed_bitmap_shutdown
|
&eina_fixed_bitmap_shutdown,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool fixed_bitmap_init(void)
|
Eina_Bool fixed_bitmap_init(void)
|
||||||
|
|
|
@ -368,7 +368,8 @@ static Eina_Mempool_Backend _eina_one_big_mp_backend = {
|
||||||
&eina_one_big_realloc,
|
&eina_one_big_realloc,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&eina_one_big_shutdown
|
&eina_one_big_shutdown,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool one_big_init(void)
|
Eina_Bool one_big_init(void)
|
||||||
|
|
|
@ -67,7 +67,8 @@ static Eina_Mempool_Backend _eina_pass_through_mp_backend = {
|
||||||
&eina_pass_through_realloc,
|
&eina_pass_through_realloc,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&eina_pass_through_shutdown
|
&eina_pass_through_shutdown,
|
||||||
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
Eina_Bool pass_through_init(void)
|
Eina_Bool pass_through_init(void)
|
||||||
|
|
Loading…
Reference in New Issue