ReactOS 0.4.16-dev-853-g88d9285
locale_refcounting.cpp
Go to the documentation of this file.
1/***
2*localref.c - Contains the __[add|remove]localeref() functions.
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* Contains the __[add|remove]localeref() functions.
8*
9*******************************************************************************/
10#include <corecrt_internal.h>
11#include <locale.h>
12
13
14
15/***
16* __acrt_add_locale_ref(__crt_locale_data* ptloci)
17*
18* Purpose:
19* Increment the refrence count for each element in the localeinfo struct.
20*
21*******************************************************************************/
23{
25
26 if (ptloci->lconv_intl_refcount != nullptr)
27 {
29 }
30
31 if (ptloci->lconv_mon_refcount != nullptr)
32 {
34 }
35
36 if (ptloci->lconv_num_refcount != nullptr)
37 {
39 }
40
41 if (ptloci->ctype1_refcount != nullptr)
42 {
44 }
45
46 for (int category = LC_MIN; category <= LC_MAX; ++category)
47 {
49 ptloci->lc_category[category].wrefcount != nullptr)
50 {
52 }
53
54 if (ptloci->lc_category[category].locale != nullptr &&
55 ptloci->lc_category[category].refcount != nullptr)
56 {
58 }
59 }
60
62}
63
64/***
65* __acrt_release_locale_ref(__crt_locale_data* ptloci)
66*
67* Purpose:
68* Decrement the refrence count for each elemnt in the localeinfo struct.
69*
70******************************************************************************/
72{
73 if (ptloci == nullptr)
74 return;
75
77
78 if (ptloci->lconv_intl_refcount != nullptr)
80
81 if (ptloci->lconv_mon_refcount != nullptr)
83
84 if (ptloci->lconv_num_refcount != nullptr)
86
87 if (ptloci->ctype1_refcount != nullptr)
89
90 for (int category = LC_MIN; category <= LC_MAX; ++category)
91 {
93 ptloci->lc_category[category].wrefcount != nullptr)
94 {
96 }
97
98 if (ptloci->lc_category[category].locale != nullptr &&
99 ptloci->lc_category[category].refcount != nullptr)
100 {
102 }
103 }
104
106}
107
108
109/***
110*__acrt_free_locale() - free __crt_locale_data
111*
112*Purpose:
113* Free up the per-thread locale info structure specified by the passed
114* pointer.
115*
116*Entry:
117* __crt_locale_data* ptloci
118*
119*Exit:
120*
121*Exceptions:
122*
123*******************************************************************************/
124
126{
127 /*
128 * Free up lconv struct
129 */
130 if (ptloci->lconv != nullptr &&
131 ptloci->lconv != &__acrt_lconv_c &&
132 ptloci->lconv_intl_refcount != nullptr &&
133 *ptloci->lconv_intl_refcount == 0)
134 {
135 if (ptloci->lconv_mon_refcount != nullptr && *ptloci->lconv_mon_refcount == 0)
136 {
139 }
140
141 if (ptloci->lconv_num_refcount != nullptr && *ptloci->lconv_num_refcount == 0)
142 {
145 }
146
148 _free_crt(ptloci->lconv);
149 }
150
151 /*
152 * Free up ctype tables
153 */
154 if (ptloci->ctype1_refcount != nullptr && *ptloci->ctype1_refcount == 0)
155 {
156 _free_crt(ptloci->ctype1 - _COFFSET);
157 _free_crt(const_cast<unsigned char*>(ptloci->pclmap - _COFFSET - 1));
158 _free_crt(const_cast<unsigned char*>(ptloci->pcumap - _COFFSET - 1));
159 _free_crt(ptloci->ctype1_refcount);
160 }
161
163
164 for (int category = LC_MIN; category <= LC_MAX; ++category)
165 {
167 ptloci->lc_category[category].wrefcount != nullptr &&
168 *ptloci->lc_category[category].wrefcount == 0)
169 {
172 }
173
174 _ASSERTE((ptloci->lc_category[category].locale != nullptr && ptloci->lc_category[category].refcount != nullptr) ||
175 (ptloci->lc_category[category].locale == nullptr && ptloci->lc_category[category].refcount == nullptr));
176
177 if (ptloci->lc_category[category].locale != nullptr &&
178 ptloci->lc_category[category].refcount != nullptr &&
179 *ptloci->lc_category[category].refcount == 0)
180 {
182 }
183 }
184
185 /*
186 * Free up the __crt_locale_data struct
187 */
188 _free_crt(ptloci);
189}
190
191
192/***
193*
194* _updatelocinfoEx_nolock(__crt_locale_data* *pptlocid, __crt_locale_data* ptlocis)
195*
196* Purpose:
197* Update *pptlocid to ptlocis. This might include freeing contents of *pptlocid.
198*
199******************************************************************************/
201 __crt_locale_data** pptlocid,
202 __crt_locale_data* ptlocis
203 )
204{
205 if (ptlocis == nullptr || pptlocid == nullptr)
206 return nullptr;
207
208 __crt_locale_data* const ptloci = *pptlocid;
209 if (ptloci == ptlocis)
210 return ptlocis;
211
212 /*
213 * Update to the current locale info structure and increment the
214 * reference counts.
215 */
216 *pptlocid = ptlocis;
217 __acrt_add_locale_ref(ptlocis);
218
219 /*
220 * Decrement the reference counts in the old locale info
221 * structure.
222 */
223 if (ptloci != nullptr)
224 {
226 }
227
228 /*
229 * Free the old locale info structure, if necessary. Must be done
230 * after incrementing reference counts in current locale in case
231 * any refcounts are shared with the old locale.
232 */
233 if (ptloci != nullptr &&
234 ptloci->refcount == 0 &&
236 {
237 __acrt_free_locale(ptloci);
238 }
239
240 return ptlocis;
241}
242
243
244/***
245*__acrt_update_thread_locale_data() - refresh the thread's locale info
246*
247*Purpose:
248* If this thread does not have it's ownlocale which means that either
249* ownlocale flag in ptd is not set or ptd->ptloci == nullptr, then Update
250* the current thread's reference to the locale information to match the
251* current global locale info. Decrement the reference on the old locale
252* information struct and if this count is now zero (so that no threads
253* are using it), free it.
254*
255*Entry:
256*
257*Exit:
258*
259* if (!_getptd()->ownlocale || _getptd()->ptlocinfo == nullptr)
260* _getptd()->ptlocinfo == __acrt_current_locale_data
261* else
262* _getptd()->ptlocinfo
263*
264*Exceptions:
265*
266*******************************************************************************/
268{
269 __crt_locale_data* ptloci = nullptr;
270 __acrt_ptd* const ptd = __acrt_getptd();
271
272 if (__acrt_should_sync_with_global_locale(ptd) || ptd->_locale_info == nullptr)
273 {
275 __try
276 {
277 ptloci = _updatetlocinfoEx_nolock(&ptd->_locale_info, __acrt_current_locale_data.value());
278 }
280 {
282 }
284 }
285 else
286 {
287 ptloci = ptd->_locale_info;
288 }
289
290 if (!ptloci)
291 {
292 abort();
293 }
294
295 return ptloci;
296}
297
298
299
300//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
301//
302// __crt_lc_time_data reference counting
303//
304//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
305// The C locale lc_time data is immutable and persistent. The lc_time data for
306// any other locale is dynamically allocated (and thus not actually immutable).
307// The lc_time_curr data member of __crt_locale_data is declared const to help
308// ensure that code does not accidentally attempt to modify the C locale lc_time
309// data.
310//
311// These functions encapsulate all mutation of the lc_time_curr. They accept a
312// __crt_lc_time_data const*, handle the C locale as a special case, then cast
313// away constness to mutate the lc_time data.
315 __crt_lc_time_data const* const lc_time
316 )
317{
318 if (lc_time == nullptr || lc_time == &__lc_time_c)
319 {
320 return LONG_MAX;
321 }
322
323 return _InterlockedIncrement(&const_cast<__crt_lc_time_data*>(lc_time)->refcount);
324}
325
327 __crt_lc_time_data const* const lc_time
328 )
329{
330 if (lc_time == nullptr || lc_time == &__lc_time_c)
331 {
332 return LONG_MAX;
333 }
334
335 return _InterlockedDecrement(&const_cast<__crt_lc_time_data*>(lc_time)->refcount);
336}
337
339 __crt_lc_time_data const* const lc_time
340 )
341{
342 if (lc_time == nullptr || lc_time == &__lc_time_c)
343 {
344 return;
345 }
346
347 if (__crt_interlocked_read(&lc_time->refcount) != 0)
348 {
349 return;
350 }
351
353 _free_crt(const_cast<__crt_lc_time_data*>(lc_time));
354}
#define __cdecl
Definition: accygwin.h:79
__acrt_ptd *__cdecl __acrt_getptd(void)
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
@ __acrt_locale_lock
__crt_lc_time_data const __lc_time_c
Definition: nlsdata.cpp:33
void __cdecl __acrt_locale_free_numeric(_Inout_ struct lconv *lconv)
wchar_t __acrt_wide_c_locale_string[]
Definition: nlsdata.cpp:28
#define _COFFSET
__crt_locale_data __acrt_initial_locale_data
Definition: nlsdata.cpp:92
void __cdecl __acrt_locale_free_time(_Inout_opt_ __crt_lc_time_data *lc_time_data)
void __cdecl __acrt_locale_free_monetary(_Inout_ struct lconv *lconv)
#define _ASSERTE(expr)
Definition: crtdbg.h:114
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
__acrt_lock(__acrt_heap_lock)
#define abort()
Definition: i386-dis.c:34
#define LC_MAX
Definition: locale.h:25
#define LC_MIN
Definition: locale.h:24
#define _free_crt
long __cdecl _InterlockedIncrement(_Interlocked_operand_ long volatile *_Addend)
long __cdecl _InterlockedDecrement(_Interlocked_operand_ long volatile *_Addend)
#define LONG_MAX
Definition: intsafe.h:154
void __cdecl __acrt_free_locale(__crt_locale_data *ptloci)
long __cdecl __acrt_locale_add_lc_time_reference(__crt_lc_time_data const *const lc_time)
__crt_locale_data *__cdecl __acrt_update_thread_locale_data()
void __cdecl __acrt_release_locale_ref(__crt_locale_data *ptloci)
void __cdecl __acrt_add_locale_ref(__crt_locale_data *ptloci)
long __cdecl __acrt_locale_release_lc_time_reference(__crt_lc_time_data const *const lc_time)
void __cdecl __acrt_locale_free_lc_time_if_unreferenced(__crt_lc_time_data const *const lc_time)
__crt_locale_data *__cdecl _updatetlocinfoEx_nolock(__crt_locale_data **pptlocid, __crt_locale_data *ptlocis)
__crt_state_management::dual_state_global< __crt_locale_data * > __acrt_current_locale_data
Definition: nlsdata.cpp:132
#define __try
Definition: pseh2_64.h:172
#define __endtry
Definition: pseh2_64.h:175
#define __finally
Definition: pseh2_64.h:174
unsigned char const * pcumap
__crt_locale_refcount lc_category[6]
wchar_t * locale_name[6]
__crt_lc_time_data const * lc_time_curr
unsigned char const * pclmap
unsigned short * ctype1
struct lconv * lconv
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t _Inout_ size_t __crt_lc_time_data const * lc_time
Definition: wcsftime.cpp:385