forked from enlightenment/efl
eina: Introduce Eina_Slstr for short-lived strings
Built on top of the new 'postponed' free queue, the short-lived strings API allows users to return new strings without caring about freeing them. EFL main loop will do this automatically for them you at a later point in time (at the end of an iteration). The APIs provided will either duplicate (copy) or more generally steal an existing string (char *, stringshare, tmpstr, strbuf), taking ownership of it and controling its lifetime. Those strings can then be safely returned by an API. From a user point of view, those strings must be considered like simple const char *, ie. no need to free() them and their validity is limited to the local scope. There is no function to remove such a string from the freeq. The short lived strings API is not thread-safe: do not send a short-lived object from one thread to another. @feature
This commit is contained in:
parent
4f5e64fdea
commit
4550b4cf83
|
@ -103,7 +103,8 @@ lib/eina/eina_inline_safepointer.x \
|
|||
lib/eina/eina_slice.h \
|
||||
lib/eina/eina_inline_slice.x \
|
||||
lib/eina/eina_inline_modinfo.x \
|
||||
lib/eina/eina_freeq.h
|
||||
lib/eina/eina_freeq.h \
|
||||
lib/eina/eina_slstr.h
|
||||
|
||||
|
||||
lib_eina_libeina_la_SOURCES = \
|
||||
|
@ -177,7 +178,8 @@ lib/eina/eina_strbuf_common.h \
|
|||
lib/eina/eina_quaternion.c \
|
||||
lib/eina/eina_bezier.c \
|
||||
lib/eina/eina_safepointer.c \
|
||||
lib/eina/eina_freeq.c
|
||||
lib/eina/eina_freeq.c \
|
||||
lib/eina/eina_slstr.c
|
||||
|
||||
|
||||
if HAVE_WIN32
|
||||
|
@ -348,7 +350,8 @@ tests/eina/eina_test_vector.c \
|
|||
tests/eina/eina_test_bezier.c \
|
||||
tests/eina/eina_test_safepointer.c \
|
||||
tests/eina/eina_test_slice.c \
|
||||
tests/eina/eina_test_freeq.c
|
||||
tests/eina/eina_test_freeq.c \
|
||||
tests/eina/eina_test_slstr.c
|
||||
|
||||
tests_eina_eina_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
|
||||
-DTESTS_WD=\"`pwd`\" \
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#define EINA_SLSTR_INTERNAL
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
|
@ -2388,6 +2390,11 @@ process_all: /*-*********************************************************/
|
|||
done: /*-*****************************************************************/
|
||||
/* Agressively flush animator */
|
||||
_ecore_animator_flush();
|
||||
if (!once_only)
|
||||
{
|
||||
/* Free all short lived strings */
|
||||
eina_slstr_local_clear();
|
||||
}
|
||||
in_main_loop--;
|
||||
}
|
||||
|
||||
|
|
|
@ -271,6 +271,7 @@ extern "C" {
|
|||
#include <eina_safepointer.h>
|
||||
#include <eina_slice.h>
|
||||
#include <eina_freeq.h>
|
||||
#include <eina_slstr.h>
|
||||
|
||||
#undef EAPI
|
||||
#define EAPI
|
||||
|
|
|
@ -89,7 +89,8 @@ typedef enum _Eina_FreeQ_Type
|
|||
* immediately. Use this kind of freeq for debugging and additional memory
|
||||
* safety purposes only.
|
||||
*
|
||||
* This type of free queue is thread-safe.
|
||||
* As this type of free queue is thread-safe, the free functions used must
|
||||
* also be thread-safe (eg. libc free()).
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#include "eina_value.h"
|
||||
#include "eina_evlog.h"
|
||||
#include "eina_freeq.h"
|
||||
#include "eina_slstr.h"
|
||||
|
||||
/*============================================================================*
|
||||
* Local *
|
||||
|
@ -153,6 +154,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL;
|
|||
S(rbtree);
|
||||
S(file);
|
||||
S(safepointer);
|
||||
S(slstr);
|
||||
#undef S
|
||||
|
||||
struct eina_desc_setup
|
||||
|
@ -198,6 +200,7 @@ static const struct eina_desc_setup _eina_desc_setup[] = {
|
|||
S(rbtree),
|
||||
S(file),
|
||||
S(safepointer),
|
||||
S(slstr),
|
||||
#undef S
|
||||
};
|
||||
static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#define EINA_SLSTR_INTERNAL
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Eina.h"
|
||||
#include "eina_private.h"
|
||||
|
||||
// ========================================================================= //
|
||||
|
||||
static int _slstr_init = 0;
|
||||
static Eina_FreeQ *_slstr_main_fq = NULL;
|
||||
static Eina_TLS _slstr_tls = 0;
|
||||
|
||||
// ========================================================================= //
|
||||
|
||||
#if 0
|
||||
// 2 extension ideas here: slices for short-lived raw data buffers
|
||||
EAPI Eina_Rw_Slice eina_slslice_new(size_t length); // alloc
|
||||
EAPI Eina_Rw_Slice eina_slslice_copy(Eina_Slice slice); // copies
|
||||
EAPI Eina_Rw_Slice eina_slslice_free(Eina_Rw_Slice slice); // steals
|
||||
#endif
|
||||
|
||||
static void
|
||||
_slstr_tls_free_cb(void *ptr)
|
||||
{
|
||||
Eina_FreeQ *fq = ptr;
|
||||
|
||||
eina_freeq_free(fq);
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
eina_slstr_init(void)
|
||||
{
|
||||
if (_slstr_init++) return EINA_TRUE;
|
||||
|
||||
_slstr_main_fq = eina_freeq_new(EINA_FREEQ_POSTPONED);
|
||||
if (!_slstr_main_fq) goto fail;
|
||||
if (!eina_tls_cb_new(&_slstr_tls, _slstr_tls_free_cb)) goto fail_tls;
|
||||
|
||||
return EINA_TRUE;
|
||||
|
||||
fail_tls:
|
||||
eina_tls_free(_slstr_tls);
|
||||
_slstr_tls = 0;
|
||||
fail:
|
||||
eina_freeq_free(_slstr_main_fq);
|
||||
_slstr_main_fq = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
eina_slstr_shutdown(void)
|
||||
{
|
||||
if (_slstr_init == 0) return EINA_FALSE;
|
||||
if (--_slstr_init) return EINA_TRUE;
|
||||
|
||||
eina_freeq_free(_slstr_main_fq);
|
||||
eina_tls_free(_slstr_tls);
|
||||
_slstr_main_fq = NULL;
|
||||
_slstr_tls = 0;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_FreeQ *
|
||||
_slstr_freeq_get(Eina_Bool nocreate)
|
||||
{
|
||||
if (eina_main_loop_is())
|
||||
return _slstr_main_fq;
|
||||
else
|
||||
{
|
||||
Eina_FreeQ *fq;
|
||||
|
||||
fq = eina_tls_get(_slstr_tls);
|
||||
if (!nocreate && EINA_UNLIKELY(!fq))
|
||||
{
|
||||
fq = eina_freeq_new(EINA_FREEQ_POSTPONED);
|
||||
eina_tls_set(_slstr_tls, fq);
|
||||
}
|
||||
return fq;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_copy_new(const char *string)
|
||||
{
|
||||
Eina_FreeQ *fq;
|
||||
char *copy;
|
||||
size_t len = 0;
|
||||
|
||||
if (!string) return NULL;
|
||||
|
||||
fq = _slstr_freeq_get(EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fq, NULL);
|
||||
|
||||
copy = eina_strdup(string);
|
||||
if (!copy) return NULL;
|
||||
#ifdef DEBUG
|
||||
len = strlen(string) + 1;
|
||||
#endif
|
||||
eina_freeq_ptr_add(fq, copy, free, len);
|
||||
return copy;
|
||||
}
|
||||
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_steal_new(char *string)
|
||||
{
|
||||
Eina_FreeQ *fq;
|
||||
size_t len = 0;
|
||||
|
||||
if (!string) return NULL;
|
||||
|
||||
fq = _slstr_freeq_get(EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fq, NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
len = strlen(string) + 1;
|
||||
#endif
|
||||
eina_freeq_ptr_add(fq, string, free, len);
|
||||
return string;
|
||||
}
|
||||
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_stringshare_new(Eina_Stringshare *string)
|
||||
{
|
||||
Eina_FreeQ *fq;
|
||||
size_t len = 0;
|
||||
|
||||
if (!string) return NULL;
|
||||
|
||||
fq = _slstr_freeq_get(EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fq, NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
len = eina_stringshare_strlen(string) + 1;
|
||||
#endif
|
||||
eina_freeq_ptr_add(fq, (void *) string, EINA_FREE_CB(eina_stringshare_del), len);
|
||||
return string;
|
||||
}
|
||||
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_tmpstr_new(Eina_Tmpstr *string)
|
||||
{
|
||||
Eina_FreeQ *fq;
|
||||
size_t len = 0;
|
||||
|
||||
if (!string) return NULL;
|
||||
|
||||
fq = _slstr_freeq_get(EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fq, NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
len = eina_tmpstr_strlen(string) + 1;
|
||||
#endif
|
||||
eina_freeq_ptr_add(fq, (void *) string, EINA_FREE_CB(eina_tmpstr_del), len);
|
||||
return string;
|
||||
}
|
||||
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_strbuf_new(Eina_Strbuf *string)
|
||||
{
|
||||
Eina_FreeQ *fq;
|
||||
size_t len = 0;
|
||||
char *str;
|
||||
|
||||
if (!string) return NULL;
|
||||
|
||||
fq = _slstr_freeq_get(EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fq, NULL);
|
||||
|
||||
str = eina_strbuf_release(string);
|
||||
#ifdef DEBUG
|
||||
len = eina_strbuf_length_get(string) + 1;
|
||||
#endif
|
||||
eina_freeq_ptr_add(fq, str, free, len);
|
||||
return str;
|
||||
}
|
||||
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_vasprintf_new(const char *fmt, va_list args)
|
||||
{
|
||||
Eina_FreeQ *fq;
|
||||
size_t len = 0;
|
||||
char *str;
|
||||
int r;
|
||||
|
||||
fq = _slstr_freeq_get(EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(fq, NULL);
|
||||
|
||||
r = vasprintf(&str, fmt, args);
|
||||
if (r == -1) return NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
len = r + 1;
|
||||
#endif
|
||||
eina_freeq_ptr_add(fq, str, free, len);
|
||||
return str;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
eina_slstr_local_clear(void)
|
||||
{
|
||||
Eina_FreeQ *fq;
|
||||
|
||||
fq = _slstr_freeq_get(EINA_TRUE);
|
||||
if (!fq) return;
|
||||
|
||||
eina_freeq_clear(fq);
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
#ifndef EINA_SLSTR_H_
|
||||
#define EINA_SLSTR_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "eina_config.h"
|
||||
|
||||
#include "eina_types.h"
|
||||
#include "eina_tmpstr.h"
|
||||
#include "eina_strbuf.h"
|
||||
#include "eina_stringshare.h"
|
||||
#include "eina_slice.h"
|
||||
|
||||
/**
|
||||
* @addtogroup Eina_Slstr Short lived strings
|
||||
* @ingroup Eina
|
||||
*
|
||||
* @brief API for short lived strings (thread- and scope-local)
|
||||
*
|
||||
* This set of APIs provide a convenience feature to create and return strings
|
||||
* that are meant to be consumed in the local scope of the calling code block.
|
||||
* The lifecycle of those strings is bound to the loop of the current thread
|
||||
* or until the clear function is called explicitely.
|
||||
*
|
||||
* These strings will be automatically deleted.
|
||||
*
|
||||
* These functions shall return NULL only if out of memory.
|
||||
*
|
||||
* Do not call free or any similar function on a string created with this API!
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
|
||||
typedef const char Eina_Slstr;
|
||||
|
||||
/**
|
||||
* @brief Create a new short lived string by duplicating another string.
|
||||
*
|
||||
* @param string An existing string, it will be copied.
|
||||
* @return A new Eina_Slstr or NULL if out of memory.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* char local[200];
|
||||
* sprintf(local, "Hello %d", value);
|
||||
* return eina_slstr_copy_new(local);
|
||||
* @endcode
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_copy_new(const char *string);
|
||||
|
||||
/**
|
||||
* @brief Create a new short lived string by taking ownership of a string.
|
||||
*
|
||||
* @param string An existing string. It will not be duplicated.
|
||||
* @return A new Eina_Slstr or NULL if out of memory.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* char *local = strdup("Hello");
|
||||
* return eina_slstr_steal_new(local);
|
||||
* @endcode
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_steal_new(char *string);
|
||||
|
||||
/**
|
||||
* @brief Create a new short lived string by taking ownership of a stringshare.
|
||||
*
|
||||
* @param string An existing stringshare, one reference belongs to this slstr.
|
||||
* @return A new Eina_Slstr or NULL if out of memory.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* Eina_Stringshare *local = eina_stringshare_add("Hello");
|
||||
* return eina_slstr_stringshare_new(local);
|
||||
* @endcode
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_stringshare_new(Eina_Stringshare *string);
|
||||
|
||||
/**
|
||||
* @brief Create a new short lived string by taking ownership of a tmpstr.
|
||||
*
|
||||
* @param string An existing tmpstr, it will be freed later.
|
||||
* @return A new Eina_Slstr or NULL if out of memory.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* Eina_Tmpstr *local = eina_tmpstr_add("Hello");
|
||||
* return eina_slstr_tmpstr_new(local);
|
||||
* @endcode
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_tmpstr_new(Eina_Tmpstr *string);
|
||||
|
||||
/**
|
||||
* @brief Create a new short lived string by taking ownership of a strbuf.
|
||||
*
|
||||
* @param string An existing strbuf, that will be released (ie. steal + free).
|
||||
* @return A new Eina_Slstr or NULL if out of memory.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* Eina_Strbuf *local = eina_strbuf_new();
|
||||
* eina_strbuf_append(local, "Hello");
|
||||
* eina_strbuf_append(local, " world");
|
||||
* return eina_slstr_strbuf_new(local);
|
||||
* @endcode
|
||||
*
|
||||
* @note Use eina_slstr_steal_new() if the strbuf will be used after this call.
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_strbuf_new(Eina_Strbuf *string);
|
||||
|
||||
/**
|
||||
* @brief Create a new short lived string using sprintf.
|
||||
*
|
||||
* @param fmt Format string for printf
|
||||
* @param args List of format parameters for printf
|
||||
* @return A new Eina_Slstr or NULL if out of memory.
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
EAPI Eina_Slstr *
|
||||
eina_slstr_vasprintf_new(const char *fmt, va_list args);
|
||||
|
||||
/**
|
||||
* @brief Create a new short lived string using sprintf.
|
||||
*
|
||||
* @param fmt Format string for printf
|
||||
* @param args List of format parameters for printf
|
||||
* @return A new Eina_Slstr or NULL if out of memory.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* return eina_slstr_printf("Hello world %d!", 42);
|
||||
* @endcode
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
static inline Eina_Slstr *
|
||||
eina_slstr_printf(const char *fmt, ...)
|
||||
{
|
||||
Eina_Slstr *str;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
str = eina_slstr_vasprintf_new(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifdef EINA_SLSTR_INTERNAL
|
||||
/**
|
||||
* @brief Internal function to clear the strings.
|
||||
*
|
||||
* This internal function will be called by the local thread's loop to free
|
||||
* all the strings. Do not call this function unless you are absolutely certain
|
||||
* that no string in the queue will be used after this point.
|
||||
*
|
||||
* @since 1.19
|
||||
*/
|
||||
EAPI void
|
||||
eina_slstr_local_clear(void);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -86,6 +86,7 @@ static const Efl_Test_Case etc[] = {
|
|||
{ "Slice", eina_test_slice },
|
||||
{ "Free Queue", eina_test_freeq },
|
||||
{ "Util", eina_test_util },
|
||||
{ "Short Lived Strings", eina_test_slstr },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -73,5 +73,6 @@ void eina_test_bezier(TCase *tc);
|
|||
void eina_test_safepointer(TCase *tc);
|
||||
void eina_test_slice(TCase *tc);
|
||||
void eina_test_freeq(TCase *tc);
|
||||
void eina_test_slstr(TCase *tc);
|
||||
|
||||
#endif /* EINA_SUITE_H_ */
|
||||
|
|
|
@ -0,0 +1,208 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#define EINA_SLSTR_INTERNAL
|
||||
#include <Eina.h>
|
||||
|
||||
#include "eina_suite.h"
|
||||
|
||||
static Eina_Slstr *
|
||||
_slstr_copy(void)
|
||||
{
|
||||
const char local[] = "Hello world 1";
|
||||
|
||||
return eina_slstr_copy_new(local);
|
||||
}
|
||||
|
||||
START_TEST(slstr_copy)
|
||||
{
|
||||
Eina_Slstr *str;
|
||||
|
||||
eina_init();
|
||||
|
||||
str = _slstr_copy();
|
||||
ck_assert_str_eq(str, "Hello world 1");
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Eina_Slstr *
|
||||
_slstr_steal(void)
|
||||
{
|
||||
char *local = strdup("Hello world 2");
|
||||
|
||||
return eina_slstr_copy_new(local);
|
||||
}
|
||||
|
||||
START_TEST(slstr_steal)
|
||||
{
|
||||
Eina_Slstr *str;
|
||||
|
||||
eina_init();
|
||||
|
||||
str = _slstr_steal();
|
||||
ck_assert_str_eq(str, "Hello world 2");
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Eina_Slstr *
|
||||
_slstr_stringshare(void)
|
||||
{
|
||||
Eina_Stringshare *str = eina_stringshare_add("Hello world 3");
|
||||
|
||||
return eina_slstr_stringshare_new(str);
|
||||
}
|
||||
|
||||
START_TEST(slstr_stringshare)
|
||||
{
|
||||
Eina_Stringshare *ss;
|
||||
Eina_Slstr *str;
|
||||
|
||||
eina_init();
|
||||
|
||||
str = _slstr_stringshare();
|
||||
ss = eina_stringshare_add("Hello world 3");
|
||||
fail_if(ss != str);
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Eina_Slstr *
|
||||
_slstr_tmpstr(void)
|
||||
{
|
||||
Eina_Tmpstr *str = eina_tmpstr_add("Hello world 4");
|
||||
|
||||
return eina_slstr_tmpstr_new(str);
|
||||
}
|
||||
|
||||
START_TEST(slstr_tmpstr)
|
||||
{
|
||||
Eina_Slstr *str;
|
||||
|
||||
eina_init();
|
||||
|
||||
str = _slstr_tmpstr();
|
||||
ck_assert_str_eq(str, "Hello world 4");
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Eina_Slstr *
|
||||
_slstr_strbuf(void)
|
||||
{
|
||||
Eina_Strbuf *str = eina_strbuf_new();
|
||||
|
||||
eina_strbuf_append(str, "Hello ");
|
||||
eina_strbuf_append(str, "world ");
|
||||
eina_strbuf_append_printf(str, "%d", 5);
|
||||
|
||||
return eina_slstr_strbuf_new(str);
|
||||
}
|
||||
|
||||
START_TEST(slstr_strbuf)
|
||||
{
|
||||
Eina_Slstr *str;
|
||||
|
||||
eina_init();
|
||||
|
||||
str = _slstr_strbuf();
|
||||
ck_assert_str_eq(str, "Hello world 5");
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Eina_Slstr *
|
||||
_slstr_printf(int val)
|
||||
{
|
||||
return eina_slstr_printf("Hello %s %d", "world", val);
|
||||
}
|
||||
|
||||
START_TEST(slstr_slstr_printf)
|
||||
{
|
||||
Eina_Slstr *str;
|
||||
|
||||
eina_init();
|
||||
|
||||
str = _slstr_printf(6);
|
||||
ck_assert_str_eq(str, "Hello world 6");
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
_many_do(void)
|
||||
{
|
||||
const int many = 2048;
|
||||
Eina_Slstr *str;
|
||||
int k;
|
||||
|
||||
for (k = 0; k < many; k++)
|
||||
{
|
||||
char local[64];
|
||||
|
||||
str = _slstr_printf(k);
|
||||
sprintf(local, "Hello world %d", k);
|
||||
ck_assert_str_eq(str, local);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(slstr_many)
|
||||
{
|
||||
eina_init();
|
||||
|
||||
_many_do();
|
||||
|
||||
eina_slstr_local_clear();
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void *
|
||||
_thread_cb(void *data EINA_UNUSED, Eina_Thread th EINA_UNUSED)
|
||||
{
|
||||
_many_do();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
START_TEST(slstr_thread)
|
||||
{
|
||||
const int threads = 8;
|
||||
Eina_Thread th[threads];
|
||||
int k;
|
||||
|
||||
eina_init();
|
||||
|
||||
for (k = 0; k < threads; k++)
|
||||
fail_if(!eina_thread_create(&th[k], EINA_THREAD_NORMAL, -1, _thread_cb, NULL));
|
||||
|
||||
for (k = 0; k < threads; k++)
|
||||
eina_thread_join(th[k]);
|
||||
|
||||
eina_slstr_local_clear();
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
eina_test_slstr(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, slstr_copy);
|
||||
tcase_add_test(tc, slstr_steal);
|
||||
tcase_add_test(tc, slstr_stringshare);
|
||||
tcase_add_test(tc, slstr_tmpstr);
|
||||
tcase_add_test(tc, slstr_strbuf);
|
||||
tcase_add_test(tc, slstr_slstr_printf);
|
||||
tcase_add_test(tc, slstr_many);
|
||||
tcase_add_test(tc, slstr_thread);
|
||||
}
|
Loading…
Reference in New Issue