intl/icu/source/common/umutex.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 **********************************************************************
michael@0 3 * Copyright (C) 1997-2013, International Business Machines
michael@0 4 * Corporation and others. All Rights Reserved.
michael@0 5 **********************************************************************
michael@0 6 *
michael@0 7 * File UMUTEX.H
michael@0 8 *
michael@0 9 * Modification History:
michael@0 10 *
michael@0 11 * Date Name Description
michael@0 12 * 04/02/97 aliu Creation.
michael@0 13 * 04/07/99 srl rewrite - C interface, multiple mutices
michael@0 14 * 05/13/99 stephen Changed to umutex (from cmutex)
michael@0 15 ******************************************************************************
michael@0 16 */
michael@0 17
michael@0 18 #ifndef UMUTEX_H
michael@0 19 #define UMUTEX_H
michael@0 20
michael@0 21 #include "unicode/utypes.h"
michael@0 22 #include "unicode/uclean.h"
michael@0 23 #include "putilimp.h"
michael@0 24
michael@0 25
michael@0 26
michael@0 27 // Forward Declarations. UMutex is not in the ICU namespace (yet) because
michael@0 28 // there are some remaining references from plain C.
michael@0 29 struct UMutex;
michael@0 30
michael@0 31 U_NAMESPACE_BEGIN
michael@0 32 struct UInitOnce;
michael@0 33 U_NAMESPACE_END
michael@0 34
michael@0 35 // Stringify macros, to allow #include of user supplied atomic & mutex files.
michael@0 36 #define U_MUTEX_STR(s) #s
michael@0 37 #define U_MUTEX_XSTR(s) U_MUTEX_STR(s)
michael@0 38
michael@0 39 /****************************************************************************
michael@0 40 *
michael@0 41 * Low Level Atomic Operations.
michael@0 42 * Compiler dependent. Not operating system dependent.
michael@0 43 *
michael@0 44 ****************************************************************************/
michael@0 45 #if defined (U_USER_ATOMICS_H)
michael@0 46 #include U_MUTEX_XSTR(U_USER_ATOMICS_H)
michael@0 47
michael@0 48 #elif U_HAVE_STD_ATOMICS
michael@0 49
michael@0 50 // C++11 atomics are available.
michael@0 51
michael@0 52 #include <atomic>
michael@0 53
michael@0 54 U_NAMESPACE_BEGIN
michael@0 55
michael@0 56 typedef std::atomic<int32_t> u_atomic_int32_t;
michael@0 57 #define ATOMIC_INT32_T_INITIALIZER(val) ATOMIC_VAR_INIT(val)
michael@0 58
michael@0 59 inline int32_t umtx_loadAcquire(u_atomic_int32_t &var) {
michael@0 60 return var.load(std::memory_order_acquire);
michael@0 61 }
michael@0 62
michael@0 63 inline void umtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
michael@0 64 var.store(val, std::memory_order_release);
michael@0 65 }
michael@0 66
michael@0 67 inline int32_t umtx_atomic_inc(u_atomic_int32_t *var) {
michael@0 68 return var->fetch_add(1) + 1;
michael@0 69 }
michael@0 70
michael@0 71 inline int32_t umtx_atomic_dec(u_atomic_int32_t *var) {
michael@0 72 return var->fetch_sub(1) - 1;
michael@0 73 }
michael@0 74 U_NAMESPACE_END
michael@0 75
michael@0 76 #elif U_PLATFORM_HAS_WIN32_API
michael@0 77
michael@0 78 // MSVC compiler. Reads and writes of volatile variables have
michael@0 79 // acquire and release memory semantics, respectively.
michael@0 80 // This is a Microsoft extension, not standard C++ behavior.
michael@0 81 //
michael@0 82 // Update: can't use this because of MinGW, built with gcc.
michael@0 83 // Original plan was to use gcc atomics for MinGW, but they
michael@0 84 // aren't supported, so we fold MinGW into this path.
michael@0 85
michael@0 86 # define WIN32_LEAN_AND_MEAN
michael@0 87 # define VC_EXTRALEAN
michael@0 88 # define NOUSER
michael@0 89 # define NOSERVICE
michael@0 90 # define NOIME
michael@0 91 # define NOMCX
michael@0 92 # ifndef NOMINMAX
michael@0 93 # define NOMINMAX
michael@0 94 # endif
michael@0 95 # include <windows.h>
michael@0 96
michael@0 97 U_NAMESPACE_BEGIN
michael@0 98 typedef volatile LONG u_atomic_int32_t;
michael@0 99 #define ATOMIC_INT32_T_INITIALIZER(val) val
michael@0 100
michael@0 101 inline int32_t umtx_loadAcquire(u_atomic_int32_t &var) {
michael@0 102 return InterlockedCompareExchange(&var, 0, 0);
michael@0 103 }
michael@0 104
michael@0 105 inline void umtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
michael@0 106 InterlockedExchange(&var, val);
michael@0 107 }
michael@0 108
michael@0 109
michael@0 110 inline int32_t umtx_atomic_inc(u_atomic_int32_t *var) {
michael@0 111 return InterlockedIncrement(var);
michael@0 112 }
michael@0 113
michael@0 114 inline int32_t umtx_atomic_dec(u_atomic_int32_t *var) {
michael@0 115 return InterlockedDecrement(var);
michael@0 116 }
michael@0 117 U_NAMESPACE_END
michael@0 118
michael@0 119
michael@0 120 #elif U_HAVE_GCC_ATOMICS
michael@0 121 /*
michael@0 122 * gcc atomic ops. These are available on several other compilers as well.
michael@0 123 */
michael@0 124
michael@0 125 U_NAMESPACE_BEGIN
michael@0 126 typedef int32_t u_atomic_int32_t;
michael@0 127 #define ATOMIC_INT32_T_INITIALIZER(val) val
michael@0 128
michael@0 129 inline int32_t umtx_loadAcquire(u_atomic_int32_t &var) {
michael@0 130 int32_t val = var;
michael@0 131 __sync_synchronize();
michael@0 132 return val;
michael@0 133 }
michael@0 134
michael@0 135 inline void umtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
michael@0 136 __sync_synchronize();
michael@0 137 var = val;
michael@0 138 }
michael@0 139
michael@0 140 inline int32_t umtx_atomic_inc(u_atomic_int32_t *p) {
michael@0 141 return __sync_add_and_fetch(p, 1);
michael@0 142 }
michael@0 143
michael@0 144 inline int32_t umtx_atomic_dec(u_atomic_int32_t *p) {
michael@0 145 return __sync_sub_and_fetch(p, 1);
michael@0 146 }
michael@0 147 U_NAMESPACE_END
michael@0 148
michael@0 149 #else
michael@0 150
michael@0 151 /*
michael@0 152 * Unknown Platform. Use out-of-line functions, which in turn use mutexes.
michael@0 153 * Slow but correct.
michael@0 154 */
michael@0 155
michael@0 156 #define U_NO_PLATFORM_ATOMICS
michael@0 157
michael@0 158 U_NAMESPACE_BEGIN
michael@0 159 typedef int32_t u_atomic_int32_t;
michael@0 160 #define ATOMIC_INT32_T_INITIALIZER(val) val
michael@0 161
michael@0 162 U_COMMON_API int32_t U_EXPORT2
michael@0 163 umtx_loadAcquire(u_atomic_int32_t &var);
michael@0 164
michael@0 165 U_COMMON_API void U_EXPORT2
michael@0 166 umtx_storeRelease(u_atomic_int32_t &var, int32_t val);
michael@0 167
michael@0 168 U_COMMON_API int32_t U_EXPORT2
michael@0 169 umtx_atomic_inc(u_atomic_int32_t *p);
michael@0 170
michael@0 171 U_COMMON_API int32_t U_EXPORT2
michael@0 172 umtx_atomic_dec(u_atomic_int32_t *p);
michael@0 173
michael@0 174 U_NAMESPACE_END
michael@0 175
michael@0 176 #endif /* Low Level Atomic Ops Platfrom Chain */
michael@0 177
michael@0 178
michael@0 179
michael@0 180 /*************************************************************************************************
michael@0 181 *
michael@0 182 * UInitOnce Definitions.
michael@0 183 * These are platform neutral.
michael@0 184 *
michael@0 185 *************************************************************************************************/
michael@0 186
michael@0 187 U_NAMESPACE_BEGIN
michael@0 188
michael@0 189 struct UInitOnce {
michael@0 190 u_atomic_int32_t fState;
michael@0 191 UErrorCode fErrCode;
michael@0 192 void reset() {fState = 0;};
michael@0 193 UBool isReset() {return umtx_loadAcquire(fState) == 0;};
michael@0 194 // Note: isReset() is used by service registration code.
michael@0 195 // Thread safety of this usage needs review.
michael@0 196 };
michael@0 197
michael@0 198 #define U_INITONCE_INITIALIZER {ATOMIC_INT32_T_INITIALIZER(0), U_ZERO_ERROR}
michael@0 199
michael@0 200
michael@0 201 U_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &);
michael@0 202 U_COMMON_API void U_EXPORT2 umtx_initImplPostInit(UInitOnce &);
michael@0 203
michael@0 204 template<class T> void umtx_initOnce(UInitOnce &uio, T *obj, void (T::*fp)()) {
michael@0 205 if (umtx_loadAcquire(uio.fState) == 2) {
michael@0 206 return;
michael@0 207 }
michael@0 208 if (umtx_initImplPreInit(uio)) {
michael@0 209 (obj->*fp)();
michael@0 210 umtx_initImplPostInit(uio);
michael@0 211 }
michael@0 212 }
michael@0 213
michael@0 214
michael@0 215 // umtx_initOnce variant for plain functions, or static class functions.
michael@0 216 // No context parameter.
michael@0 217 inline void umtx_initOnce(UInitOnce &uio, void (*fp)()) {
michael@0 218 if (umtx_loadAcquire(uio.fState) == 2) {
michael@0 219 return;
michael@0 220 }
michael@0 221 if (umtx_initImplPreInit(uio)) {
michael@0 222 (*fp)();
michael@0 223 umtx_initImplPostInit(uio);
michael@0 224 }
michael@0 225 }
michael@0 226
michael@0 227 // umtx_initOnce variant for plain functions, or static class functions.
michael@0 228 // With ErrorCode, No context parameter.
michael@0 229 inline void umtx_initOnce(UInitOnce &uio, void (*fp)(UErrorCode &), UErrorCode &errCode) {
michael@0 230 if (U_FAILURE(errCode)) {
michael@0 231 return;
michael@0 232 }
michael@0 233 if (umtx_loadAcquire(uio.fState) != 2 && umtx_initImplPreInit(uio)) {
michael@0 234 // We run the initialization.
michael@0 235 (*fp)(errCode);
michael@0 236 uio.fErrCode = errCode;
michael@0 237 umtx_initImplPostInit(uio);
michael@0 238 } else {
michael@0 239 // Someone else already ran the initialization.
michael@0 240 if (U_FAILURE(uio.fErrCode)) {
michael@0 241 errCode = uio.fErrCode;
michael@0 242 }
michael@0 243 }
michael@0 244 }
michael@0 245
michael@0 246 // umtx_initOnce variant for plain functions, or static class functions,
michael@0 247 // with a context parameter.
michael@0 248 template<class T> void umtx_initOnce(UInitOnce &uio, void (*fp)(T), T context) {
michael@0 249 if (umtx_loadAcquire(uio.fState) == 2) {
michael@0 250 return;
michael@0 251 }
michael@0 252 if (umtx_initImplPreInit(uio)) {
michael@0 253 (*fp)(context);
michael@0 254 umtx_initImplPostInit(uio);
michael@0 255 }
michael@0 256 }
michael@0 257
michael@0 258 // umtx_initOnce variant for plain functions, or static class functions,
michael@0 259 // with a context parameter and an error code.
michael@0 260 template<class T> void umtx_initOnce(UInitOnce &uio, void (*fp)(T, UErrorCode &), T context, UErrorCode &errCode) {
michael@0 261 if (U_FAILURE(errCode)) {
michael@0 262 return;
michael@0 263 }
michael@0 264 if (umtx_loadAcquire(uio.fState) != 2 && umtx_initImplPreInit(uio)) {
michael@0 265 // We run the initialization.
michael@0 266 (*fp)(context, errCode);
michael@0 267 uio.fErrCode = errCode;
michael@0 268 umtx_initImplPostInit(uio);
michael@0 269 } else {
michael@0 270 // Someone else already ran the initialization.
michael@0 271 if (U_FAILURE(uio.fErrCode)) {
michael@0 272 errCode = uio.fErrCode;
michael@0 273 }
michael@0 274 }
michael@0 275 }
michael@0 276
michael@0 277 U_NAMESPACE_END
michael@0 278
michael@0 279
michael@0 280
michael@0 281 /*************************************************************************************************
michael@0 282 *
michael@0 283 * Mutex Definitions. Platform Dependent, #if platform chain follows.
michael@0 284 * TODO: Add a C++11 version.
michael@0 285 * Need to convert all mutex using files to C++ first.
michael@0 286 *
michael@0 287 *************************************************************************************************/
michael@0 288
michael@0 289 #if defined(U_USER_MUTEX_H)
michael@0 290 // #inlcude "U_USER_MUTEX_H"
michael@0 291 #include U_MUTEX_XSTR(U_USER_MUTEX_H)
michael@0 292
michael@0 293 #elif U_PLATFORM_HAS_WIN32_API
michael@0 294
michael@0 295 /* Windows Definitions.
michael@0 296 * Windows comes first in the platform chain.
michael@0 297 * Cygwin (and possibly others) have both WIN32 and POSIX APIs. Prefer Win32 in this case.
michael@0 298 */
michael@0 299
michael@0 300
michael@0 301 /* For CRITICAL_SECTION */
michael@0 302
michael@0 303 /*
michael@0 304 * Note: there is an earlier include of windows.h in this file, but it is in
michael@0 305 * different conditionals.
michael@0 306 * This one is needed if we are using C++11 for atomic ops, but
michael@0 307 * win32 APIs for Critical Sections.
michael@0 308 */
michael@0 309
michael@0 310 # define WIN32_LEAN_AND_MEAN
michael@0 311 # define VC_EXTRALEAN
michael@0 312 # define NOUSER
michael@0 313 # define NOSERVICE
michael@0 314 # define NOIME
michael@0 315 # define NOMCX
michael@0 316 # ifndef NOMINMAX
michael@0 317 # define NOMINMAX
michael@0 318 # endif
michael@0 319 # include <windows.h>
michael@0 320
michael@0 321
michael@0 322 typedef struct UMutex {
michael@0 323 icu::UInitOnce fInitOnce;
michael@0 324 CRITICAL_SECTION fCS;
michael@0 325 } UMutex;
michael@0 326
michael@0 327 /* Initializer for a static UMUTEX. Deliberately contains no value for the
michael@0 328 * CRITICAL_SECTION.
michael@0 329 */
michael@0 330 #define U_MUTEX_INITIALIZER {U_INITONCE_INITIALIZER}
michael@0 331
michael@0 332
michael@0 333
michael@0 334 #elif U_PLATFORM_IMPLEMENTS_POSIX
michael@0 335
michael@0 336 /*
michael@0 337 * POSIX platform
michael@0 338 */
michael@0 339
michael@0 340 #include <pthread.h>
michael@0 341
michael@0 342 struct UMutex {
michael@0 343 pthread_mutex_t fMutex;
michael@0 344 };
michael@0 345 typedef struct UMutex UMutex;
michael@0 346 #define U_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER}
michael@0 347
michael@0 348 #else
michael@0 349
michael@0 350 /*
michael@0 351 * Unknow platform type.
michael@0 352 * This is an error condition. ICU requires mutexes.
michael@0 353 */
michael@0 354
michael@0 355 #error Unknown Platform.
michael@0 356
michael@0 357 #endif
michael@0 358
michael@0 359
michael@0 360
michael@0 361 /**************************************************************************************
michael@0 362 *
michael@0 363 * Mutex Implementation function declaratations.
michael@0 364 * Declarations are platform neutral.
michael@0 365 * Implementations, in umutex.cpp, are platform specific.
michael@0 366 *
michael@0 367 ************************************************************************************/
michael@0 368
michael@0 369 /* Lock a mutex.
michael@0 370 * @param mutex The given mutex to be locked. Pass NULL to specify
michael@0 371 * the global ICU mutex. Recursive locks are an error
michael@0 372 * and may cause a deadlock on some platforms.
michael@0 373 */
michael@0 374 U_INTERNAL void U_EXPORT2 umtx_lock(UMutex* mutex);
michael@0 375
michael@0 376 /* Unlock a mutex.
michael@0 377 * @param mutex The given mutex to be unlocked. Pass NULL to specify
michael@0 378 * the global ICU mutex.
michael@0 379 */
michael@0 380 U_INTERNAL void U_EXPORT2 umtx_unlock (UMutex* mutex);
michael@0 381
michael@0 382 #endif /* UMUTEX_H */
michael@0 383 /*eof*/

mercurial