Add a new type of memory pool and factorize test code.
authorcedric <cedric>
Fri, 26 Sep 2008 15:27:46 +0000 (15:27 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 26 Sep 2008 15:27:46 +0000 (15:27 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/PROTO/eina@36267 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

configure.in
src/lib/eina_mempool.c
src/modules/mp/Makefile.am
src/modules/mp/fixed_bitmap/Makefile.am [new file with mode: 0644]
src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c [new file with mode: 0644]
src/tests/eina_test_mempool.c

index 5ca73c6..16b851b 100644 (file)
@@ -126,7 +126,7 @@ EINA_CHECK_STATIC([chained-pool], [chained pool])
 EINA_CHECK_STATIC([ememoa-fixed], [ememoa fixed])
 EINA_CHECK_STATIC([ememoa-unknown], [ememoa unknown])
 EINA_CHECK_STATIC([pass-through], [pass through])
-
+EINA_CHECK_STATIC([fixed-bitmap], [fixed bitmap])
 
 ### Checks for libraries
 
@@ -333,6 +333,7 @@ src/modules/mp/chained_pool/Makefile
 src/modules/mp/ememoa_fixed/Makefile
 src/modules/mp/ememoa_unknown/Makefile
 src/modules/mp/pass_through/Makefile
+src/modules/mp/fixed_bitmap/Makefile
 src/tests/Makefile
 ])
 
index 10f74ab..c404d37 100644 (file)
@@ -83,6 +83,11 @@ Eina_Bool ememoa_fixed_init(void);
 void ememoa_fixed_shutdown(void);
 #endif
 
+#ifdef EINA_STATIC_BUILD_FIXED_BITMAP
+Eina_Bool fixed_bitmap_init(void);
+void fixed_bitmap_shutdown(void);
+#endif
+
 /*============================================================================*
  *                                 Global                                     *
  *============================================================================*/
index 8dc920a..641127c 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = chained_pool ememoa_fixed pass_through ememoa_unknown
+SUBDIRS = chained_pool ememoa_fixed pass_through ememoa_unknown fixed_bitmap
 
 MAINTAINERCLEANFILES = \
 Makefile.in
\ No newline at end of file
diff --git a/src/modules/mp/fixed_bitmap/Makefile.am b/src/modules/mp/fixed_bitmap/Makefile.am
new file mode 100644 (file)
index 0000000..36ce28d
--- /dev/null
@@ -0,0 +1,24 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/src/include \
+@COVERAGE_CFLAGS@
+
+if !EINA_STATIC_BUILD_FIXED_BITMAP
+
+controllerdir = $(libdir)/eina/mp/
+controller_LTLIBRARIES = eina_fixed_bitmap.la
+
+eina_fixed_bitmap_la_SOURCES = \
+eina_fixed_bitmap.c
+
+eina_fixed_bitmap_la_LIBADD = $(top_builddir)/src/lib/libeina.la @COVERAGE_LIBS@
+eina_fixed_bitmap_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
+eina_fixed_bitmap_la_LIBTOOLFLAGS = --tag=disable-static
+eina_fixed_bitmap_la_DEPENDENCIES = $(top_builddir)/src/lib/libeina.la
+
+endif
+
+clean-local:
+       rm -rf *.gcno
diff --git a/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c b/src/modules/mp/fixed_bitmap/eina_fixed_bitmap.c
new file mode 100644 (file)
index 0000000..54ed39d
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+/* EINA - EFL data type library
+ * Copyright (C) 2008 Cedric BAIL
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+
+#include "eina_inlist.h"
+#include "eina_rbtree.h"
+#include "eina_error.h"
+
+#include "eina_mempool.h"
+
+#include "eina_private.h"
+
+typedef struct _Eina_Fixed_Bitmap Eina_Fixed_Bitmap;
+typedef struct _Eina_Fixed_Bitmap_Pool Eina_Fixed_Bitmap_Pool;
+
+struct _Eina_Fixed_Bitmap
+{
+   Eina_Rbtree *lookup;
+   Eina_Inlist *head;
+
+   int item_size;
+};
+
+struct _Eina_Fixed_Bitmap_Pool
+{
+   EINA_RBTREE;
+   EINA_INLIST;
+
+   uint32_t bitmask;
+};
+
+static inline int
+_eina_rbtree_inlist_delta(void)
+{
+   Eina_Fixed_Bitmap_Pool tmp;
+   void *a = &tmp.__rbtree;
+   void *b = &tmp.__in_list;
+
+   return a - b;
+}
+
+static Eina_Rbtree_Direction
+_eina_fixed_cmp(const Eina_Rbtree *left, const Eina_Rbtree *right, __UNUSED__ void *data)
+{
+   if (left - right < 0)
+     return EINA_RBTREE_LEFT;
+   return EINA_RBTREE_RIGHT;
+}
+
+static int
+_eina_fixed_cmp_key(const Eina_Rbtree *node, const void *key, __UNUSED__ int length, Eina_Fixed_Bitmap *mp)
+{
+   const void *a = node;
+   const void *b = key;
+   int delta;
+   int limit;
+
+   limit = sizeof (Eina_Fixed_Bitmap_Pool) + mp->item_size * 32;
+   delta = a - b;
+
+   if (delta > 0)
+     return 1;
+   if (delta + limit < 0)
+     return -1;
+   return 0;
+}
+
+static void
+_eina_fixed_bitmap_pool_free(Eina_Fixed_Bitmap_Pool *pool, __UNUSED__ void *data)
+{
+   free(pool);
+}
+
+static void *
+eina_fixed_bitmap_malloc(void *data, __UNUSED__ unsigned int size)
+{
+   Eina_Fixed_Bitmap *mp = data;
+   Eina_Fixed_Bitmap_Pool *pool;
+   void *ptr;
+   int index;
+
+   if (mp->head)
+     {
+       pool = (Eina_Fixed_Bitmap_Pool*) ((unsigned char*) mp->head + _eina_rbtree_inlist_delta());
+
+       if (pool->bitmask == 0) pool = NULL;
+     }
+
+   if (!pool)
+     {
+       eina_error_set(0);
+       pool = malloc(sizeof (Eina_Fixed_Bitmap_Pool) + mp->item_size * 32);
+       if (!pool)
+         {
+            eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
+            return NULL;
+         }
+
+       pool->bitmask = 0xFFFFFFFF;
+
+       mp->head = eina_inlist_prepend(mp->head, EINA_INLIST_GET(pool));
+       mp->lookup = eina_rbtree_inline_insert(mp->lookup, EINA_RBTREE_GET(pool), EINA_RBTREE_CMP_NODE_CB(_eina_fixed_cmp), NULL);
+     }
+
+   index = ffs(pool->bitmask) - 1;
+   pool->bitmask &= ~(1 << index);
+   ptr = (unsigned char*) (pool + 1) + index * mp->item_size;
+
+   if (pool->bitmask == 0)
+     {
+       mp->head = eina_inlist_remove(mp->head, EINA_INLIST_GET(pool));
+       mp->head = eina_inlist_append(mp->head, EINA_INLIST_GET(pool));
+     }
+
+   return ptr;
+}
+
+#include <stdio.h>
+static void
+eina_fixed_bitmap_free(void *data, void *ptr)
+{
+   Eina_Fixed_Bitmap *mp = data;
+   Eina_Fixed_Bitmap_Pool *pool;
+   void *a;
+   Eina_Bool push_front = EINA_FALSE;
+   int delta;
+
+   pool = (Eina_Fixed_Bitmap_Pool*) eina_rbtree_inline_lookup(mp->lookup,
+                                                             ptr, 0,
+                                                             EINA_RBTREE_CMP_KEY_CB(_eina_fixed_cmp_key), mp);
+   if (!pool) return ;
+   if (pool->bitmask != 0xFFFFFFFF) push_front = EINA_TRUE;
+
+   a = pool;
+   delta = (ptr - a - sizeof (Eina_Fixed_Bitmap_Pool)) / mp->item_size;
+
+   assert(delta >= 0 && delta < 32);
+
+   pool->bitmask |= (1 << (delta & 0x1F));
+
+   if (pool->bitmask == 0xFFFFFFFF)
+     {
+       mp->head = eina_inlist_remove(mp->head, EINA_INLIST_GET(pool));
+       mp->lookup = eina_rbtree_inline_remove(mp->lookup, EINA_RBTREE_GET(pool), EINA_RBTREE_CMP_NODE_CB(_eina_fixed_cmp), NULL);
+       free(pool);
+     }
+   else if (push_front)
+     {
+       mp->head = eina_inlist_remove(mp->head, EINA_INLIST_GET(pool));
+       mp->head = eina_inlist_prepend(mp->head, EINA_INLIST_GET(pool));
+     }
+}
+
+static void *
+eina_fixed_bitmap_realloc(__UNUSED__ void *data, __UNUSED__ void *element, __UNUSED__ unsigned int size)
+{
+   return NULL;
+}
+
+static void*
+eina_fixed_bitmap_init(__UNUSED__ const char *context, __UNUSED__ const char *option, va_list args)
+{
+   Eina_Fixed_Bitmap *mp;
+
+   mp = malloc(sizeof (Eina_Fixed_Bitmap));
+   if (!mp) return NULL;
+
+   mp->item_size = va_arg(args, int);
+   mp->lookup = NULL;
+   mp->head = NULL;
+
+   return mp;
+}
+
+static void
+eina_fixed_bitmap_shutdown(void *data)
+{
+   Eina_Fixed_Bitmap *mp = data;
+
+   eina_rbtree_delete(mp->lookup, EINA_RBTREE_FREE_CB(_eina_fixed_bitmap_pool_free), NULL);
+   free(mp);
+}
+
+static Eina_Mempool_Backend mp_backend = {
+  .name ="fixed_bitmap",
+  .init = &eina_fixed_bitmap_init,
+  .shutdown = &eina_fixed_bitmap_shutdown,
+  .realloc = &eina_fixed_bitmap_realloc,
+  .alloc = &eina_fixed_bitmap_malloc,
+  .free = &eina_fixed_bitmap_free
+};
+
+Eina_Bool fixed_bitmap_init(void)
+{
+   return eina_mempool_register(&mp_backend);
+}
+
+void fixed_bitmap_shutdown(void)
+{
+   eina_mempool_unregister(&mp_backend);
+}
+
+#ifndef EINA_STATIC_BUILD_FIXED_BITMAP
+
+EINA_MODULE_INIT(fixed_bitmap_init);
+EINA_MODULE_SHUTDOWN(fixed_bitmap_shutdown);
+
+#endif /* ! EINA_STATIC_BUILD_FIXED_BITMAP */
+
index 27aa321..cf12082 100644 (file)
@@ -25,7 +25,8 @@
 
 static Eina_List *_modules;
 
-static void _mempool_init(void)
+static void
+_mempool_init(void)
 {
     eina_mempool_init();
     /* force modules to be loaded in case they are not installed */
@@ -33,35 +34,20 @@ static void _mempool_init(void)
     eina_module_list_load(_modules);
 }
 
-static void _mempool_shutdown(void)
+static void
+_mempool_shutdown(void)
 {
    eina_module_list_delete(_modules);
    /* TODO delete the list */
    eina_mempool_shutdown();
 }
 
-START_TEST(eina_mempool_init_shutdown)
-{
-   Eina_Mempool *mp;
-
-   _mempool_init();
-
-   mp = eina_mempool_new("test", "test", NULL);
-   fail_if(mp != NULL);
-
-   _mempool_shutdown();
-}
-END_TEST
-
-START_TEST(eina_mempool_chained_mempool)
+static void
+_eina_mempool_test(Eina_Mempool *mp, Eina_Bool with_realloc, Eina_Bool with_gc)
 {
-   Eina_Mempool *mp;
    int *tbl[512];
    int i;
 
-   _mempool_init();
-
-   mp = eina_mempool_new("chained_mempool", "test", NULL, sizeof (int), 256);
    fail_if(!mp);
 
    for (i = 0; i < 512; ++i)
@@ -77,9 +63,41 @@ START_TEST(eina_mempool_chained_mempool)
    for (i = 0; i < 256; ++i)
      eina_mempool_free(mp, tbl[i]);
 
-   fail_if(eina_mempool_realloc(mp, tbl[500], 25) != NULL);
+   if (with_realloc)
+     fail_if(eina_mempool_realloc(mp, tbl[500], 25) == NULL);
+   else
+     fail_if(eina_mempool_realloc(mp, tbl[500], 25) != NULL);
+
+   if (with_gc)
+     {
+       eina_mempool_gc(mp);
+       eina_mempool_statistics(mp);
+     }
 
    eina_mempool_delete(mp);
+}
+
+START_TEST(eina_mempool_init_shutdown)
+{
+   Eina_Mempool *mp;
+
+   _mempool_init();
+
+   mp = eina_mempool_new("test", "test", NULL);
+   fail_if(mp != NULL);
+
+   _mempool_shutdown();
+}
+END_TEST
+
+START_TEST(eina_mempool_chained_mempool)
+{
+   Eina_Mempool *mp;
+
+   _mempool_init();
+
+   mp = eina_mempool_new("chained_mempool", "test", NULL, sizeof (int), 256);
+   _eina_mempool_test(mp, EINA_FALSE, EINA_FALSE);
 
    _mempool_shutdown();
 }
@@ -88,30 +106,24 @@ END_TEST
 START_TEST(eina_mempool_pass_through)
 {
    Eina_Mempool *mp;
-   int *tbl[512];
-   int i;
 
    _mempool_init();
 
    mp = eina_mempool_new("pass_through", "test", NULL, sizeof (int), 8, 0);
-   fail_if(!mp);
-
-   for (i = 0; i < 512; ++i)
-     {
-       tbl[i] = eina_mempool_alloc(mp, sizeof (int));
-       fail_if(!tbl[i]);
-       *tbl[i] = i;
-     }
+   _eina_mempool_test(mp, EINA_TRUE, EINA_FALSE);
 
-   for (i = 0; i < 512; ++i)
-     fail_if(*tbl[i] != i);
+   _mempool_shutdown();
+}
+END_TEST
 
-   for (i = 0; i < 256; ++i)
-     eina_mempool_free(mp, tbl[i]);
+START_TEST(eina_mempool_fixed_bitmap)
+{
+   Eina_Mempool *mp;
 
-   fail_if(eina_mempool_realloc(mp, tbl[500], 25) == NULL);
+   _mempool_init();
 
-   eina_mempool_delete(mp);
+   mp = eina_mempool_new("fixed_bitmap", "test", NULL, sizeof (int));
+   _eina_mempool_test(mp, EINA_FALSE, EINA_FALSE);
 
    _mempool_shutdown();
 }
@@ -121,33 +133,11 @@ END_TEST
 START_TEST(eina_mempool_ememoa_fixed)
 {
    Eina_Mempool *mp;
-   int *tbl[512];
-   int i;
 
    _mempool_init();
 
    mp = eina_mempool_new("ememoa_fixed", "test", NULL, sizeof (int), 8, 0);
-   fail_if(!mp);
-
-   for (i = 0; i < 512; ++i)
-     {
-       tbl[i] = eina_mempool_alloc(mp, sizeof (int));
-       fail_if(!tbl[i]);
-       *tbl[i] = i;
-     }
-
-   for (i = 0; i < 512; ++i)
-     fail_if(*tbl[i] != i);
-
-   for (i = 0; i < 256; ++i)
-     eina_mempool_free(mp, tbl[i]);
-
-   fail_if(eina_mempool_realloc(mp, tbl[500], 25) != NULL);
-
-   eina_mempool_gc(mp);
-   eina_mempool_statistics(mp);
-
-   eina_mempool_delete(mp);
+   _eina_mempool_test(mp, EINA_FALSE, EINA_TRUE);
 
    _mempool_shutdown();
 }
@@ -156,34 +146,11 @@ END_TEST
 START_TEST(eina_mempool_ememoa_unknown)
 {
    Eina_Mempool *mp;
-   int *tbl[512];
-   int i;
 
    _mempool_init();
 
    mp = eina_mempool_new("ememoa_unknown", "test", NULL, 0, 2, sizeof (int), 8, sizeof (int) * 2, 8);
-   fail_if(!mp);
-
-   for (i = 0; i < 512; ++i)
-     {
-       tbl[i] = eina_mempool_alloc(mp, sizeof (int));
-       fail_if(!tbl[i]);
-       *tbl[i] = i;
-     }
-
-   for (i = 0; i < 512; ++i)
-     fail_if(*tbl[i] != i);
-
-   for (i = 0; i < 256; ++i)
-     eina_mempool_free(mp, tbl[i]);
-
-   for (i = 256; i < 512; ++i)
-     tbl[i] = eina_mempool_realloc(mp, tbl[i], 2 * sizeof (int));
-
-   eina_mempool_gc(mp);
-   eina_mempool_statistics(mp);
-
-   eina_mempool_delete(mp);
+   _eina_mempool_test(mp, EINA_TRUE, EINA_TRUE);
 
    _mempool_shutdown();
 }
@@ -196,6 +163,7 @@ eina_test_mempool(TCase *tc)
    tcase_add_test(tc, eina_mempool_init_shutdown);
    tcase_add_test(tc, eina_mempool_chained_mempool);
    tcase_add_test(tc, eina_mempool_pass_through);
+   tcase_add_test(tc, eina_mempool_fixed_bitmap);
 #ifdef EINA_EMEMOA_SUPPORT
    tcase_add_test(tc, eina_mempool_ememoa_fixed);
    tcase_add_test(tc, eina_mempool_ememoa_unknown);