Thread locals api wrapper
When looking for the linux equivalents of TlsAlloc etc I found none, since nobody who uses the library I'm making would want to have to check what operating system they're on I've resorted to a wrapper that mimics it as best it can, wandering what you guys think of it. Can it be made better?
Code:
# ifdef PAW_API_MSW
# define PAWTLS
# define PAWTLS_API_BASED
# elif (__GNUC__)
# define PAWTLS __thread
# elif defined( _MSC )
# define PAWTLS _declspec(thread)
# elif PAW_STDC >= 202300L
# include <threads.h>
# define PAWTLS thread_local
# elif PAW_STDC >= 201113L
# define PAWTLS _Thread_local
# else
# define PAWTLS
# define PAWTLS_NO_LOCALS
# endif
Windows:
Code:
PAWAPP_API void* pawtls_create(void) { return (void*)1; }
PAWAPP_API pawvu pawtls_newloc( void *tls, pawvu size )
{ (void)tls; (void)size; return TlsAlloc(); }
PAWAPP_API void pawtls_remloc( void *tls, pawvu i )
{ (void)tls; TlsFree(i); }
PAWAPP_API void* pawtls_getloc( void *tls, pawvu i )
{ (void)tls; return TlsGetValue(i); }
PAWAPP_API void pawtls_setloc( void *tls, pawvu i, void *ud )
{ (void)tls; return TlsSetValue( i, ud ); }
PAWAPP_API void pawtls_delete( void *tls ) { (void)tls; }
Linux:
Code:
typedef struct _pawtls_entry { pawvu size; void *value; } pawtls_entry;
PAWTLS pawbuf pawtls = {0};
PAWAPP_API void* pawtls_create( void ) { return &pawtls; }
PAWAPP_API pawvu pawtls_newloc( void *tls, pawvu size )
{
pawtls_entry *list = pawbuf_gettop(pawtls), *ent = NULL;
pawvu i = 0, len = pawtls.len;
(void)tls;
if ( !size )
return PAWTLS_NO_INDICES;
if ( !list )
{
pawtls = pawbuf_newmax( sizeof(pawtls_entry), PAWCD_WIDTH );
ent = pawbuf_gettop(pawtls);
if ( !ent )
return PAWTLS_NO_INDICES;
ent->size = size;
return 0;
}
for ( ; i < len; ++i )
{
ent = list + i;
if ( ent->size )
continue;
ent->size;
return i;
}
list = pawbuf_fitmax( &pawtls, len * 2 );
if ( !list )
return PAWTLS_NO_INDICES;
ent = list + len;
ent->size = size;
pawtls.len++;
return len;
}
PAWAPP_API void pawtls_remloc( void *tls, pawvu i )
{
pawtls_entry *ent = pawbuf_offset( pawtls, i );
(void)tls;
if ( !ent )
return;
ent->size = 0;
ent->value = NULL;
}
PAWAPP_API void* pawtls_getloc( void *tls, pawvu i )
{
pawtls_entry *ent = pawbuf_offset(pawtls,i);
return ent ? ent->value : NULL;
}
PAWAPP_API void pawtls_setloc( void *tls, pawvu i, void *ud )
{
pawtls_entry *ent = pawbuf_offset( pawtls, i );
(void)tls;
if ( ent )
ent->value = ud;
}
PAWAPP_API void pawtls_delete(void *tls)
{ (void)tls; pawbuf_expire(&pawtls); }