diff options
author | 2012-01-23 20:02:15 -0800 | |
---|---|---|
committer | 2012-01-23 20:02:15 -0800 | |
commit | fa569b32fb925353057f9c0342b7b50009ed38f0 (patch) | |
tree | 99a73b951d422605aef41bfb9a94104d7f418083 /intern.cpp | |
parent | 78f8317de8507dbd5957922619d657348351f08e (diff) |
Made intern'd strings thread safe.
Removed intern_free_all().
Diffstat (limited to 'intern.cpp')
-rw-r--r-- | intern.cpp | 126 |
1 files changed, 29 insertions, 97 deletions
@@ -10,6 +10,7 @@ #include <stdio.h> #include <wchar.h> #include <unistd.h> +#include <set> #include "fallback.h" #include "util.h" @@ -18,112 +19,43 @@ #include "common.h" #include "intern.h" -/** - Table of interned strings -*/ -static hash_table_t *intern_table=0; - -/** - Table of static interned strings -*/ -static hash_table_t *intern_static_table=0; +/** Comparison function for intern'd strings */ +static bool string_table_compare(const wchar_t *a, const wchar_t *b) { + return wcscmp(a, b) < 0; +} -const wchar_t *intern( const wchar_t *in ) -{ - ASSERT_IS_MAIN_THREAD(); - const wchar_t *res=0; +/** The table of intern'd strings */ +typedef std::set<const wchar_t *, bool (*)(const wchar_t *, const wchar_t *b)> string_table_t; +static string_table_t string_table(string_table_compare); -// debug( 0, L"intern %ls", in ); - - if( !in ) - return 0; - - if( !intern_table ) - { - intern_table = (hash_table_t *)malloc( sizeof( hash_table_t ) ); - if( !intern_table ) - { - DIE_MEM(); - } - hash_init( intern_table, &hash_wcs_func, &hash_wcs_cmp ); - } - - if( intern_static_table ) - { - res = (const wchar_t *)hash_get( intern_static_table, in ); - } - - if( !res ) - { - res = (const wchar_t *)hash_get( intern_table, in ); - - if( !res ) - { - res = wcsdup( in ); - if( !res ) - { - DIE_MEM(); - } - - hash_put( intern_table, res, res ); - } - } - - return res; -} +/** The lock to provide thread safety for intern'd strings */ +static pthread_mutex_t intern_lock = PTHREAD_MUTEX_INITIALIZER; -const wchar_t *intern_static( const wchar_t *in ) +static const wchar_t *intern_with_dup( const wchar_t *in, bool dup ) { - const wchar_t *res=0; - if( !in ) - return 0; - - if( !intern_static_table ) - { - intern_static_table = (hash_table_t *)malloc( sizeof( hash_table_t ) ); - if( !intern_static_table ) - { - DIE_MEM(); - } - hash_init( intern_static_table, &hash_wcs_func, &hash_wcs_cmp ); - } - - res = (const wchar_t *)hash_get( intern_static_table, in ); - - if( !res ) - { - res = in; - hash_put( intern_static_table, res, res ); - } - - return res; + return NULL; + +// debug( 0, L"intern %ls", in ); + scoped_lock lock(intern_lock); + const wchar_t *result; + string_table_t::const_iterator iter = string_table.find(in); + if (iter != string_table.end()) { + result = *iter; + } else { + result = dup ? wcsdup(in) : in; + string_table.insert(result); + } + return result; } -/** - Free the specified key/value pair. Should only be called by intern_free_all at shutdown -*/ -static void clear_value( void *key, void *data ) +const wchar_t *intern( const wchar_t *in ) { - debug( 3, L"interned string: '%ls'", data ); - free( (void *)data ); + return intern_with_dup(in, true); } -void intern_free_all() -{ - if( intern_table ) - { - hash_foreach( intern_table, &clear_value ); - hash_destroy( intern_table ); - free( intern_table ); - intern_table=0; - } - if( intern_static_table ) - { - hash_destroy( intern_static_table ); - free( intern_static_table ); - intern_static_table=0; - } - +const wchar_t *intern_static( const wchar_t *in ) +{ + return intern_with_dup(in, false); } |