unsigned lastUsed;
};
- // notice that we must use an accessor function and not a static variable
- // because when the TLS variables support is implemented in the library (and
- // not by the compiler), the global s_cache variable could be not yet
- // initialized when a ctor of another global object is executed and if that
- // ctor uses any wxString methods, bad things happen
- static Cache& GetCache()
+#ifndef wxHAS_COMPILER_TLS
+ // we must use an accessor function and not a static variable when the TLS
+ // variables support is implemented in the library (and not by the compiler)
+ // because the global s_cache variable could be not yet initialized when a
+ // ctor of another global object is executed and if that ctor uses any
+ // wxString methods, bad things happen
+ //
+ // however notice that this approach does not work when compiler TLS is used,
+ // at least not with g++ 4.1.2 under amd64 as it apparently compiles code
+ // using this accessor incorrectly when optimizations are enabled (-O2 is
+ // enough) -- luckily we don't need it then neither as static __thread
+ // variables are initialized by 0 anyhow then and so we can use the variable
+ // directly
+ WXEXPORT static Cache& GetCache()
{
static wxTLS_TYPE(Cache) s_cache;
return wxTLS_VALUE(s_cache);
}
-
- static Cache::Element *GetCacheBegin() { return GetCache().cached; }
- static Cache::Element *GetCacheEnd() { return GetCacheBegin() + Cache::SIZE; }
- static unsigned& LastUsedCacheElement() { return GetCache().lastUsed; }
-
+
// this helper struct is used to ensure that GetCache() is called during
// static initialization time, i.e. before any threads creation, as otherwise
// the static s_cache construction inside GetCache() wouldn't be MT-safe
friend struct wxStrCacheInitializer;
+#else // wxHAS_COMPILER_TLS
+ static wxTLS_TYPE(Cache) ms_cache;
+ static Cache& GetCache() { return wxTLS_VALUE(ms_cache); }
+#endif // !wxHAS_COMPILER_TLS/wxHAS_COMPILER_TLS
+
+ static Cache::Element *GetCacheBegin() { return GetCache().cached; }
+ static Cache::Element *GetCacheEnd() { return GetCacheBegin() + Cache::SIZE; }
+ static unsigned& LastUsedCacheElement() { return GetCache().lastUsed; }
// this is used in debug builds only to provide a convenient function,
// callable from a debugger, to show the cache contents
// profiling seems to show a small but consistent gain if we use this
// simple loop instead of starting from the last used element (there are
// a lot of misses in this function...)
- for ( Cache::Element *c = GetCacheBegin(); c != GetCacheEnd(); c++ )
+ Cache::Element * const cacheBegin = GetCacheBegin();
+#ifndef wxHAS_COMPILER_TLS
+ // during destruction tls calls may return NULL, in this case return NULL
+ // immediately without accessing anything else
+ if ( cacheBegin == NULL )
+ return NULL;
+#endif
+ Cache::Element * const cacheEnd = GetCacheEnd();
+ for ( Cache::Element *c = cacheBegin; c != cacheEnd; c++ )
{
if ( c->str == this )
return c;
// truncate the string to given length
wxString& Truncate(size_t uiLen);
// empty string contents
- void Empty()
- {
- Truncate(0);
-
- wxASSERT_MSG( empty(), _T("string not empty after call to Empty()?") );
- }
+ void Empty() { clear(); }
// empty the string and free memory
void Clear() { clear(); }
{ return at(n); }
#endif // size_t != unsigned int
- // explicit conversion to C string (use this with printf()!)
+
+ /*
+ Overview of wxString conversions, implicit and explicit:
+
+ - wxString has a std::[w]string-like c_str() method, however it does
+ not return a C-style string directly but instead returns wxCStrData
+ helper object which is convertible to either "char *" narrow string
+ or "wchar_t *" wide string. Usually the correct conversion will be
+ applied by the compiler automatically but if this doesn't happen you
+ need to explicitly choose one using wxCStrData::AsChar() or AsWChar()
+ methods or another wxString conversion function.
+
+ - One of the places where the conversion does *NOT* happen correctly is
+ when c_str() is passed to a vararg function such as printf() so you
+ must *NOT* use c_str() with them. Either use wxPrintf() (all wx
+ functions do handle c_str() correctly, even if they appear to be
+ vararg (but they're not, really)) or add an explicit AsChar() or, if
+ compatibility with previous wxWidgets versions is important, add a
+ cast to "const char *".
+
+ - In non-STL mode only, wxString is also implicitly convertible to
+ wxCStrData. The same warning as above applies.
+
+ - c_str() is polymorphic as it can be converted to either narrow or
+ wide string. If you explicitly need one or the other, choose to use
+ mb_str() (for narrow) or wc_str() (for wide) instead. Notice that
+ these functions can return either the pointer to string directly (if
+ this is what the string uses internally) or a temporary buffer
+ containing the string and convertible to it. Again, conversion will
+ usually be done automatically by the compiler but beware of the
+ vararg functions: you need an explicit cast when using them.
+
+ - There are also non-const versions of mb_str() and wc_str() called
+ char_str() and wchar_str(). They are only meant to be used with
+ non-const-correct functions and they always return buffers.
+
+ - Finally wx_str() returns whatever string representation is used by
+ wxString internally. It may be either a narrow or wide string
+ depending on wxWidgets build mode but it will always be a raw pointer
+ (and not a buffer).
+ */
+
+ // explicit conversion to wxCStrData
wxCStrData c_str() const { return wxCStrData(this); }
wxCStrData data() const { return c_str(); }
- // implicit conversion to C string
+ // implicit conversion to wxCStrData
operator wxCStrData() const { return c_str(); }
// the first two operators conflict with operators for conversion to