Changeset 509
- Timestamp:
- 07/12/06 19:22:10 (6 years ago)
- Files:
-
- trunk/src/ares/std/array.d (modified) (9 diffs)
- trunk/src/ares/std/atomic.d (modified) (10 diffs)
- trunk/src/ares/std/exception.d (modified) (3 diffs)
- trunk/src/ares/std/thread.d (modified) (17 diffs)
- trunk/src/ares/std/traits.d (modified) (2 diffs)
- trunk/src/ares/std/unicode.d (modified) (4 diffs)
- trunk/src/ares/std/vararg.d (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/ares/std/array.d
r498 r509 45 45 46 46 47 /**48 * Temporary until a predicate module can be created.49 */50 47 template equalTo( Elem ) 51 48 { 52 49 /** 53 * 50 * Temporary until a predicate module can be created. 54 51 */ 55 52 bool equalTo( Elem a, Elem b ) … … 60 57 61 58 62 /**63 *64 */65 59 /+ 66 60 template find( Elem ) … … 76 70 77 71 78 /**79 *80 */81 72 template find( Elem, Pred ) 82 73 { … … 109 100 110 101 111 /**112 *113 */114 102 template find( Elem ) 115 103 { … … 125 113 126 114 127 /**128 *129 */130 115 template find( Elem, Pred ) 131 116 { … … 248 233 249 234 250 /**251 *252 */253 235 /+ 254 236 template rfind( Elem ) … … 264 246 265 247 266 /**267 *268 */269 248 template rfind( Elem, Pred ) 270 249 { … … 302 281 303 282 304 /**305 *306 */307 283 template rfind( Elem ) 308 284 { … … 318 294 319 295 320 /**321 *322 */323 296 template rfind( Elem, Pred ) 324 297 { trunk/src/ares/std/atomic.d
r498 r509 76 76 private 77 77 { 78 version( DDoc ) {} else 79 { 78 80 import std.traits; 79 81 … … 111 113 } 112 114 } 115 } 116 117 118 //////////////////////////////////////////////////////////////////////////////// 119 // DDoc Documentation for Atomic Functions 120 //////////////////////////////////////////////////////////////////////////////// 121 122 123 version( DDoc ) 124 { 125 //////////////////////////////////////////////////////////////////////////// 126 // Atomic Load 127 //////////////////////////////////////////////////////////////////////////// 128 129 130 /** 131 * Supported msync values: 132 * msync.none 133 * msync.hlb 134 * msync.ddhlb 135 * msync.acq 136 */ 137 template atomicLoad( msync ms, T ) 138 { 139 /** 140 * Refreshes the contents of 'val' from main memory. This operation is 141 * both lock-free and atomic. 142 * 143 * Returns: 144 * The loaded value. 145 * 146 * Params: 147 * val = The value to load. This value must be properly aligned. 148 */ 149 T atomicLoad( inout T val ) 150 { 151 return val; 152 } 153 } 154 155 156 //////////////////////////////////////////////////////////////////////////// 157 // Atomic Store 158 //////////////////////////////////////////////////////////////////////////// 159 160 161 /** 162 * Supported msync values: 163 * msync.none 164 * msync.ssb 165 * msync.acq 166 * msync.rel 167 */ 168 template atomicStore( msync ms, T ) 169 { 170 /** 171 * Stores 'newval' to the memory referenced by 'val'. This operation 172 * is both lock-free and atomic. 173 * 174 * Params: 175 * val = The destination variable. 176 * newval = The value to store. 177 */ 178 void atomicStore( inout T val, T newval ) 179 { 180 181 } 182 } 183 184 185 //////////////////////////////////////////////////////////////////////////// 186 // Atomic StoreIf 187 //////////////////////////////////////////////////////////////////////////// 188 189 190 /** 191 * Supported msync values: 192 * msync.none 193 * msync.ssb 194 * msync.acq 195 * msync.rel 196 */ 197 template atomicStoreIf( msync ms, T ) 198 { 199 /** 200 * Stores 'newval' to the memory referenced by 'val' if val is equal to 201 * 'equalTo'. This operation is both lock-free and atomic. 202 * 203 * Returns: 204 * true if the store occurred, false if not. 205 * 206 * Params: 207 * val = The destination variable. 208 * newval = The value to store. 209 * equalTo = The comparison value. 210 */ 211 bool atomicStoreIf( inout T val, T newval, T equalTo ) 212 { 213 return false; 214 } 215 } 216 217 218 //////////////////////////////////////////////////////////////////////////// 219 // Atomic Increment 220 //////////////////////////////////////////////////////////////////////////// 221 222 223 /** 224 * Supported msync values: 225 * msync.none 226 * msync.ssb 227 * msync.acq 228 * msync.rel 229 */ 230 template atomicIncrement( msync ms, T ) 231 { 232 /** 233 * This operation is only legal for built-in value and pointer types, 234 * and is equivalent to an atomic "val = val + 1" operation. This 235 * function exists to facilitate use of the optimized increment 236 * instructions provided by some architecures. If no such instruction 237 * exists on the target platform then the behavior will perform the 238 * operation using more traditional means. This operation is both 239 * lock-free and atomic. 240 * 241 * Returns: 242 * The result of an atomicLoad of val immediately following the 243 * increment operation. This value is not required to be equal to the 244 * newly stored value. Thus, competing writes are allowed to occur 245 * between the increment and successive load operation. 246 * 247 * Params: 248 * val = The value to increment. 249 */ 250 T atomicIncrement( inout T val ) 251 { 252 return val; 253 } 254 } 255 256 257 //////////////////////////////////////////////////////////////////////////// 258 // Atomic Decrement 259 //////////////////////////////////////////////////////////////////////////// 260 261 262 /** 263 * Supported msync values: 264 * msync.none 265 * msync.ssb 266 * msync.acq 267 * msync.rel 268 */ 269 template atomicDecrement( msync ms, T ) 270 { 271 /** 272 * This operation is only legal for built-in value and pointer types, 273 * and is equivalent to an atomic "val = val - 1" operation. This 274 * function exists to facilitate use of the optimized decrement 275 * instructions provided by some architecures. If no such instruction 276 * exists on the target platform then the behavior will perform the 277 * operation using more traditional means. This operation is both 278 * lock-free and atomic. 279 * 280 * Returns: 281 * The result of an atomicLoad of val immediately following the 282 * increment operation. This value is not required to be equal to the 283 * newly stored value. Thus, competing writes are allowed to occur 284 * between the increment and successive load operation. 285 * 286 * Params: 287 * val = The value to decrement. 288 */ 289 T atomicDecrement( inout T val ) 290 { 291 return val; 292 } 293 } 294 } 113 295 114 296 … … 118 300 119 301 120 private 302 else version( X86 ) 121 303 { 122 version( X86 )304 private 123 305 { 124 306 //////////////////////////////////////////////////////////////////////// … … 127 309 128 310 129 //130 311 // NOTE: Strictly speaking, the x86 supports atomic operations on 131 312 // unaligned values. However, this is far slower than the 132 313 // common case, so such behavior should be prohibited. 133 //134 314 template atomicValueIsProperlyAligned( T ) 135 315 { … … 1094 1274 } 1095 1275 } 1096 } 1097 1098 1099 //////////////////////////////////////////////////////////////////////////////// 1100 // x86 Atomic Function Accessors 1101 //////////////////////////////////////////////////////////////////////////////// 1102 1103 1104 version( X86 ) 1105 { 1276 1277 1278 //////////////////////////////////////////////////////////////////////////// 1279 // x86 Public Atomic Functions 1280 //////////////////////////////////////////////////////////////////////////// 1281 1106 1282 // 1107 1283 // NOTE: x86 loads implicitly have acquire semantics so a membar is only necessary on release 1108 1284 // 1109 1285 1110 /**1111 * Refreshes the contents of 'val' from main memory. This operation is both lock-free and atomic.1112 *1113 * Returns:1114 * The loaded value.1115 *1116 * Params:1117 * val = The value to load. This value must be properly aligned.1118 */1119 1286 template atomicLoad( msync ms : msync.none, T ) { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } 1120 template atomicLoad( msync ms : msync.hlb, T ) { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } /// ditto1121 template atomicLoad( msync ms : msync.ddhlb, T ) { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } /// ditto1122 template atomicLoad( msync ms : msync.acq, T ) { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } /// ditto1287 template atomicLoad( msync ms : msync.hlb, T ) { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } 1288 template atomicLoad( msync ms : msync.ddhlb, T ) { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } 1289 template atomicLoad( msync ms : msync.acq, T ) { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } 1123 1290 1124 1291 // … … 1126 1293 // 1127 1294 1128 /**1129 * Stores 'newval' to the memory referenced by 'val'. This operation is both lock-free and atomic.1130 *1131 * Params:1132 * val = The destination variable.1133 * newval = The value to store.1134 */1135 1295 template atomicStore( msync ms : msync.none, T ) { alias doAtomicStore!(isHoistOp!(ms),T) atomicStore; } 1136 template atomicStore( msync ms : msync.ssb, T ) { alias doAtomicStore!(isHoistOp!(ms),T) atomicStore; } /// ditto 1137 template atomicStore( msync ms : msync.acq, T ) { alias doAtomicStore!(isHoistOp!(ms),T) atomicStore; } /// ditto 1138 template atomicStore( msync ms : msync.rel, T ) { alias doAtomicStore!(isHoistOp!(ms),T) atomicStore; } /// ditto 1139 1140 /** 1141 * Stores 'newval' to the memory referenced by 'val' if val is equal to 'equalTo'. This operation 1142 * is both lock-free and atomic. 1143 * 1144 * Returns: 1145 * true if the store occurred, false if not. 1146 * 1147 * Params: 1148 * val = The destination variable. 1149 * newval = The value to store. 1150 * equalTo = The comparison value. 1151 */ 1296 template atomicStore( msync ms : msync.ssb, T ) { alias doAtomicStore!(isHoistOp!(ms),T) atomicStore; } 1297 template atomicStore( msync ms : msync.acq, T ) { alias doAtomicStore!(isHoistOp!(ms),T) atomicStore; } 1298 template atomicStore( msync ms : msync.rel, T ) { alias doAtomicStore!(isHoistOp!(ms),T) atomicStore; } 1299 1152 1300 template atomicStoreIf( msync ms : msync.none, T ) { alias doAtomicStoreIf!(ms!=msync.none,T) atomicStoreIf; } 1153 template atomicStoreIf( msync ms : msync.ssb, T ) { alias doAtomicStoreIf!(ms!=msync.none,T) atomicStoreIf; } /// ditto 1154 template atomicStoreIf( msync ms : msync.acq, T ) { alias doAtomicStoreIf!(ms!=msync.none,T) atomicStoreIf; } /// ditto 1155 template atomicStoreIf( msync ms : msync.rel, T ) { alias doAtomicStoreIf!(ms!=msync.none,T) atomicStoreIf; } /// ditto 1156 1157 /** 1158 * This operation is only legal for built-in value and pointer types, and is equivalent to an atomic 1159 * "val = val + 1" operation. This function exists to facilitate use of the optimized increment 1160 * instructions provided by some architecures. If no such instruction exists on the target platform 1161 * then the behavior will perform the operation using more traditional means. This operation is both 1162 * lock-free and atomic. 1163 * 1164 * Returns: 1165 * The result of an atomicLoad of val immediately following the increment operation. This value 1166 * is not required to be equal to the newly stored value. Thus, competing writes are allowed to 1167 * occur between the increment and successive load operation. 1168 * 1169 * Params: 1170 * val = The value to increment. 1171 */ 1301 template atomicStoreIf( msync ms : msync.ssb, T ) { alias doAtomicStoreIf!(ms!=msync.none,T) atomicStoreIf; } 1302 template atomicStoreIf( msync ms : msync.acq, T ) { alias doAtomicStoreIf!(ms!=msync.none,T) atomicStoreIf; } 1303 template atomicStoreIf( msync ms : msync.rel, T ) { alias doAtomicStoreIf!(ms!=msync.none,T) atomicStoreIf; } 1304 1172 1305 template atomicIncrement( msync ms : msync.none, T ) { alias doAtomicIncrement!(ms!=msync.none,T) atomicIncrement; } 1173 template atomicIncrement( msync ms : msync.ssb, T ) { alias doAtomicIncrement!(ms!=msync.none,T) atomicIncrement; } /// ditto 1174 template atomicIncrement( msync ms : msync.acq, T ) { alias doAtomicIncrement!(ms!=msync.none,T) atomicIncrement; } /// ditto 1175 template atomicIncrement( msync ms : msync.rel, T ) { alias doAtomicIncrement!(ms!=msync.none,T) atomicIncrement; } /// ditto 1176 1177 /** 1178 * This operation is only legal for built-in value and pointer types, and is equivalent to an atomic 1179 * "val = val - 1" operation. This function exists to facilitate use of the optimized decrement 1180 * instructions provided by some architecures. If no such instruction exists on the target platform 1181 * then the behavior will perform the operation using more traditional means. This operation is both 1182 * lock-free and atomic. 1183 * 1184 * Returns: 1185 * The result of an atomicLoad of val immediately following the increment operation. This value 1186 * is not required to be equal to the newly stored value. Thus, competing writes are allowed to 1187 * occur between the increment and successive load operation. 1188 * 1189 * Params: 1190 * val = The value to decrement. 1191 */ 1306 template atomicIncrement( msync ms : msync.ssb, T ) { alias doAtomicIncrement!(ms!=msync.none,T) atomicIncrement; } 1307 template atomicIncrement( msync ms : msync.acq, T ) { alias doAtomicIncrement!(ms!=msync.none,T) atomicIncrement; } 1308 template atomicIncrement( msync ms : msync.rel, T ) { alias doAtomicIncrement!(ms!=msync.none,T) atomicIncrement; } 1309 1192 1310 template atomicDecrement( msync ms : msync.none, T ) { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } 1193 template atomicDecrement( msync ms : msync.ssb, T ) { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } /// ditto1194 template atomicDecrement( msync ms : msync.acq, T ) { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } /// ditto1195 template atomicDecrement( msync ms : msync.rel, T ) { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } /// ditto1311 template atomicDecrement( msync ms : msync.ssb, T ) { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } 1312 template atomicDecrement( msync ms : msync.acq, T ) { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } 1313 template atomicDecrement( msync ms : msync.rel, T ) { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } 1196 1314 } 1197 1315 … … 1203 1321 1204 1322 /** 1205 * This class represents a value which will be subject to competing access. All accesses to 1206 * this value will be synchronized with main memory, and various memory barriers may be 1207 * employed for instruction ordering. Any primitive type of size equal to or smaller than 1208 * the memory bus size is allowed, so 32-bit machines may use values with size <= int.sizeof 1209 * and 64-bit machines may use values with size <= long.sizeof. The one exception to this 1210 * rule is that architectures that support DCAS will allow double-wide storeIf operations. 1211 * The 32-bit x86 architecture, for example, supports 64-bit storeIf operations. 1323 * This class represents a value which will be subject to competing access. 1324 * All accesses to this value will be synchronized with main memory, and 1325 * various memory barriers may be employed for instruction ordering. Any 1326 * primitive type of size equal to or smaller than the memory bus size is 1327 * allowed, so 32-bit machines may use values with size <= int.sizeof and 1328 * 64-bit machines may use values with size <= long.sizeof. The one exception 1329 * to this rule is that architectures that support DCAS will allow double-wide 1330 * storeIf operations. The 32-bit x86 architecture, for example, supports 1331 * 64-bit storeIf operations. 1212 1332 */ 1213 1333 struct Atomic( T ) 1214 1334 { 1335 //////////////////////////////////////////////////////////////////////////// 1336 // Atomic Load 1337 //////////////////////////////////////////////////////////////////////////// 1338 1339 1340 template load( msync ms ) 1341 { 1342 static assert( ms == msync.none || ms == msync.hlb || 1343 ms == msync.ddhlb || ms == msync.acq, 1344 "ms must be one of: msync.none, msync.hlb, msync.ddhlb, msync.acq" ); 1345 1215 1346 /** 1216 * Refreshes the contents of this value from main memory. This operation is both lock-free and atomic. 1347 * Refreshes the contents of this value from main memory. This 1348 * operation is both lock-free and atomic. 1217 1349 * 1218 1350 * Returns: 1219 1351 * The loaded value. 1220 1352 */ 1221 template load( msync ms : msync.none ) { T load() { return atomicLoad!(ms,T)( m_val ); } } 1222 template load( msync ms : msync.hlb ) { T load() { return atomicLoad!(ms,T)( m_val ); } } /// ditto 1223 template load( msync ms : msync.ddhlb ) { T load() { return atomicLoad!(ms,T)( m_val ); } } /// ditto 1224 template load( msync ms : msync.acq ) { T load() { return atomicLoad!(ms,T)( m_val ); } } /// ditto 1353 T load() 1354 { 1355 return atomicLoad!(ms,T)( m_val ); 1356 } 1357 } 1358 1359 1360 //////////////////////////////////////////////////////////////////////////// 1361 // Atomic Store 1362 //////////////////////////////////////////////////////////////////////////// 1363 1364 1365 template store( msync ms ) 1366 { 1367 static assert( ms == msync.none || ms == msync.ssb || 1368 ms == msync.acq || ms == msync.rel, 1369 "ms must be one of: msync.none, msync.ssb, msync.acq, msync.rel" ); 1225 1370 1226 1371 /** 1227 * Stores 'newval' to the memory referenced by this value. This operation is both lock-free and atomic. 1372 * Stores 'newval' to the memory referenced by this value. This 1373 * operation is both lock-free and atomic. 1228 1374 * 1229 1375 * Params: 1230 1376 * newval = The value to store. 1231 1377 */ 1232 template store( msync ms : msync.none ) { void store( T newval ) { atomicStore!(ms,T)( m_val, newval ); } } 1233 template store( msync ms : msync.ssb ) { void store( T newval ) { atomicStore!(ms,T)( m_val, newval ); } } /// ditto 1234 template store( msync ms : msync.acq ) { void store( T newval ) { atomicStore!(ms,T)( m_val, newval ); } } /// ditto 1235 template store( msync ms : msync.rel ) { void store( T newval ) { atomicStore!(ms,T)( m_val, newval ); } } /// ditto 1378 void store( T newval ) 1379 { 1380 atomicStore!(ms,T)( m_val, newval ); 1381 } 1382 } 1383 1384 1385 //////////////////////////////////////////////////////////////////////////// 1386 // Atomic StoreIf 1387 //////////////////////////////////////////////////////////////////////////// 1388 1389 1390 template storeIf( msync ms ) 1391 { 1392 static assert( ms == msync.none || ms == msync.ssb || 1393 ms == msync.acq || ms == msync.rel, 1394 "ms must be one of: msync.none, msync.ssb, msync.acq, msync.rel" ); 1236 1395 1237 1396 /** 1238 * Stores 'newval' to the memory referenced by this value if val is equal to 'equalTo'. This operation1239 *is both lock-free and atomic.1397 * Stores 'newval' to the memory referenced by this value if val is 1398 * equal to 'equalTo'. This operation is both lock-free and atomic. 1240 1399 * 1241 1400 * Returns: … … 1246 1405 * equalTo = The comparison value. 1247 1406 */ 1248 template storeIf( msync ms : msync.none ) { bool storeIf( T newval, T equalTo ) { return atomicStoreIf!(ms,T)( m_val, newval, equalTo ); } } 1249 template storeIf( msync ms : msync.ssb ) { bool storeIf( T newval, T equalTo ) { return atomicStoreIf!(ms,T)( m_val, newval, equalTo ); } } /// ditto 1250 template storeIf( msync ms : msync.acq ) { bool storeIf( T newval, T equalTo ) { return atomicStoreIf!(ms,T)( m_val, newval, equalTo ); } } /// ditto 1251 template storeIf( msync ms : msync.rel ) { bool storeIf( T newval, T equalTo ) { return atomicStoreIf!(ms,T)( m_val, newval, equalTo ); } } /// ditto 1252 1407 bool storeIf( T newval, T equalTo ) 1408 { 1409 return atomicStoreIf!(ms,T)( m_val, newval, equalTo ); 1410 } 1411 } 1412 1413 1414 //////////////////////////////////////////////////////////////////////////// 1415 // Numeric Functions 1416 //////////////////////////////////////////////////////////////////////////// 1417 1418 1419 /** 1420 * The following additional functions are available for integer types. 1421 */ 1253 1422 static if( isValidNumericType!(T) ) 1254 1423 { 1424 //////////////////////////////////////////////////////////////////////// 1425 // Atomic Increment 1426 //////////////////////////////////////////////////////////////////////// 1427 1428 1429 template increment( msync ms ) 1430 { 1431 static assert( ms == msync.none || ms == msync.ssb || 1432 ms == msync.acq || ms == msync.rel, 1433 "ms must be one of: msync.none, msync.ssb, msync.acq, msync.rel" ); 1434 1255 1435 /** 1256 * This operation is only legal for built-in value and pointer types, and is equivalent to an atomic 1257 * "val = val + 1" operation. This function exists to facilitate use of the optimized increment 1258 * instructions provided by some architecures. If no such instruction exists on the target platform 1259 * then the behavior will perform the operation using more traditional means. This operation is both 1260 * lock-free and atomic. 1436 * This operation is only legal for built-in value and pointer 1437 * types, and is equivalent to an atomic "val = val + 1" operation. 1438 * This function exists to facilitate use of the optimized 1439 * increment instructions provided by some architecures. If no 1440 * such instruction exists on the target platform then the 1441 * behavior will perform the operation using more traditional 1442 * means. This operation is both lock-free and atomic. 1261 1443 * 1262 1444 * Returns: 1263 * The result of an atomicLoad of val immediately following the increment operation. This value 1264 * is not required to be equal to the newly stored value. Thus, competing writes are allowed to 1445 * The result of an atomicLoad of val immediately following the 1446 * increment operation. This value is not required to be equal to 1447 * the newly stored value. Thus, competing writes are allowed to 1265 1448 * occur between the increment and successive load operation. 1266 1449 */ 1267 template increment( msync ms : msync.none ) { T increment() { return atomicIncrement!(ms,T)( m_val ); } } 1268 template increment( msync ms : msync.ssb ) { T increment() { return atomicIncrement!(ms,T)( m_val ); } } /// ditto 1269 template increment( msync ms : msync.acq ) { T increment() { return atomicIncrement!(ms,T)( m_val ); } } /// ditto 1270 template increment( msync ms : msync.rel ) { T increment() { return atomicIncrement!(ms,T)( m_val ); } } /// ditto 1450 T increment() 1451 { 1452 return atomicIncrement!(ms,T)( m_val ); 1453 } 1454 } 1455 1456 1457 //////////////////////////////////////////////////////////////////////// 1458 // Atomic Decrement 1459 //////////////////////////////////////////////////////////////////////// 1460 1461 1462 template decrement( msync ms ) 1463 { 1464 static assert( ms == msync.none || ms == msync.ssb || 1465 ms == msync.acq || ms == msync.rel, 1466 "ms must be one of: msync.none, msync.ssb, msync.acq, msync.rel" ); 1271 1467 1272 1468 /** 1273 * This operation is only legal for built-in value and pointer types, and is equivalent to an atomic 1274 * "val = val - 1" operation. This function exists to facilitate use of the optimized decrement 1275 * instructions provided by some architecures. If no such instruction exists on the target platform 1276 * then the behavior will perform the operation using more traditional means. This operation is both 1277 * lock-free and atomic. 1469 * This operation is only legal for built-in value and pointer 1470 * types, and is equivalent to an atomic "val = val - 1" operation. 1471 * This function exists to facilitate use of the optimized 1472 * decrement instructions provided by some architecures. If no 1473 * such instruction exists on the target platform then the behavior 1474 * will perform the operation using more traditional means. This 1475 * operation is both lock-free and atomic. 1278 1476 * 1279 1477 * Returns: 1280 * The result of an atomicLoad of val immediately following the increment operation. This value 1281 * is not required to be equal to the newly stored value. Thus, competing writes are allowed to 1478 * The result of an atomicLoad of val immediately following the 1479 * increment operation. This value is not required to be equal to 1480 * the newly stored value. Thus, competing writes are allowed to 1282 1481 * occur between the increment and successive load operation. 1283 1482 */ 1284 template decrement( msync ms : msync.none ) { T decrement() { return atomicDecrement!(ms,T)( m_val ); } } 1285 template decrement( msync ms : msync.ssb ) { T decrement() { return atomicDecrement!(ms,T)( m_val ); } } /// ditto 1286 template decrement( msync ms : msync.acq ) { T decrement() { return atomicDecrement!(ms,T)( m_val ); } } /// ditto 1287 template decrement( msync ms : msync.rel ) { T decrement() { return atomicDecrement!(ms,T)( m_val ); } } /// ditto 1483 T decrement() 1484 { 1485 return atomicDecrement!(ms,T)( m_val ); 1486 } 1487 } 1288 1488 } 1289 1489 … … 1300 1500 private 1301 1501 { 1502 version( DDoc ) {} else 1503 { 1302 1504 template testLoad( msync ms, T ) 1303 1505 { … … 1405 1607 } 1406 1608 } 1609 } 1407 1610 } 1408 1611 trunk/src/ares/std/exception.d
r498 r509 199 199 * file = The name of the file that signaled this error. 200 200 * line = The line number on which this error occurred. 201 * msg = An error message supplied by the user.202 201 */ 203 202 extern (C) void onAssertError( char[] file, uint line ) 204 203 { 205 if( !assertHandler)204 if( assertHandler is null ) 206 205 throw new AssertException( file, line ); 207 206 assertHandler( file, line ); … … 217 216 * file = The name of the file that signaled this error. 218 217 * line = The line number on which this error occurred. 218 * msg = An error message supplied by the user. 219 219 */ 220 220 extern (C) void onAssertErrorMsg( char[] file, uint line, char[] msg ) 221 221 { 222 if( !assertHandler)222 if( assertHandler is null ) 223 223 throw new AssertException( msg, file, line ); 224 224 assertHandler( file, line, msg ); … … 240 240 extern (C) bool onCollectResource( Object obj ) 241 241 { 242 if( !collectHandler)242 if( collectHandler is null ) 243 243 return true; 244 244 return collectHandler( obj ); trunk/src/ares/std/thread.d
r506 r509 76 76 // entry point for Windows threads 77 77 // 78 extern (Windows) uint thread Func( void* arg )78 extern (Windows) uint thread_entryPoint( void* arg ) 79 79 { 80 80 Thread obj = cast(Thread) arg; … … 160 160 // entry point for POSIX threads 161 161 // 162 extern (C) void* thread Func( void* arg )162 extern (C) void* thread_entryPoint( void* arg ) 163 163 { 164 164 Thread obj = cast(Thread) arg; … … 177 177 // an exception is in-flight? 178 178 179 static extern (C) voidcleanupHandler( void* arg )179 extern (C) void thread_cleanupHandler( void* arg ) 180 180 { 181 181 Thread obj = Thread.getThis(); … … 194 194 195 195 pthread_cleanup cleanup; 196 cleanup.push( &cleanupHandler, obj );196 cleanup.push( &thread_cleanupHandler, obj ); 197 197 198 198 try … … 214 214 215 215 216 extern (C) void suspendHandler( int sig )216 extern (C) void thread_suspendHandler( int sig ) 217 217 in 218 218 { … … 283 283 284 284 285 extern (C) void resumeHandler( int sig )285 extern (C) void thread_resumeHandler( int sig ) 286 286 in 287 287 { … … 423 423 424 424 425 /** 426 * Cleans up any remaining resources used by this object. 427 */ 428 ~this() 429 { 430 if( m_addr == m_addr.init ) 431 { 432 return; 433 } 434 435 version( Win32 ) 436 { 437 m_addr = m_addr.init; 438 CloseHandle( m_hndl ); 439 m_hndl = m_hndl.init; 440 } 441 else version( Posix ) 442 { 443 pthread_detach( m_addr ); 444 m_addr = m_addr.init; 445 } 446 } 447 448 425 449 //////////////////////////////////////////////////////////////////////////// 426 450 // General Actions … … 450 474 version( Win32 ) 451 475 { 452 m_hndl = cast(HANDLE) _beginthreadex( null, 0, &thread Func, this, 0, &m_addr );476 m_hndl = cast(HANDLE) _beginthreadex( null, 0, &thread_entryPoint, this, 0, &m_addr ); 453 477 if( cast(size_t) m_hndl == 0 ) 454 478 throw new ThreadException( "Error creating thread" ); … … 459 483 scope( failure ) m_isRunning = false; 460 484 461 if( pthread_create( &m_addr, null, &thread Func, this ) != 0 )485 if( pthread_create( &m_addr, null, &thread_entryPoint, this ) != 0 ) 462 486 throw new ThreadException( "Error creating thread" ); 463 487 } … … 480 504 if( WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 ) 481 505 throw new ThreadException( "Unable to join thread" ); 506 // NOTE: m_addr must be cleared before m_hndl is closed to avoid 507 // a race condition with isRunning. The operation is labeled 508 // volatile to prevent compiler reordering. 509 volatile m_addr = m_addr.init; 510 CloseHandle( m_hndl ); 511 m_hndl = m_hndl.init; 482 512 } 483 513 else version( Posix ) … … 485 515 if( pthread_join( m_addr, null ) != 0 ) 486 516 throw new ThreadException( "Unable to join thread" ); 517 // NOTE: pthread_join acts as a substitute for pthread_detach, 518 // which is normally called by the dtor. Setting m_addr 519 // to zero ensures that pthread_detach will not be called 520 // on object destruction. 521 volatile m_addr = m_addr.init; 487 522 } 488 523 } … … 532 567 final bool isRunning() 533 568 { 534 if( !m_addr)569 if( m_addr == m_addr.init ) 535 570 { 536 571 return false; … … 906 941 { 907 942 assert( t.m_next || t.m_prev ); 943 version( Win32 ) 944 { 945 // NOTE: This doesn't work for Posix as m_isRunning must be set to 946 // false after the thread is removed during normal execution. 908 947 assert( !t.isRunning ); 948 } 909 949 } 910 950 body … … 926 966 // and having m_next and m_prev be non-null is a good way to 927 967 // ensure that. 928 929 // NOTE: Cleanup of any thread resources should occur as soon as the930 // thread is detected to no longer be running, and this seemed931 // like the most reasonable place to do so.932 version( Win32 )933 {934 CloseHandle( t.m_hndl );935 t.m_hndl = t.m_hndl.init;936 t.m_addr = t.m_addr.init;937 }938 else version( Posix )939 {940 pthread_detach( t.m_addr );941 t.m_addr = t.m_addr.init;942 }943 968 } 944 969 … … 1013 1038 else 1014 1039 sigusr1.sa_flags = 0; 1015 sigusr1.sa_handler = & suspendHandler;1040 sigusr1.sa_handler = &thread_suspendHandler; 1016 1041 // NOTE: We want to ignore all signals while in this handler, so fill 1017 1042 // sa_mask to indicate this. … … 1023 1048 // restart. 1024 1049 sigusr2.sa_flags = 0; 1025 sigusr2.sa_handler = & resumeHandler;1050 sigusr2.sa_handler = &thread_resumeHandler; 1026 1051 // NOTE: We want to ignore all signals while in this handler, so fill 1027 1052 // sa_mask to indicate this. … … 1134 1159 } 1135 1160 1136 CONTEXT context;1161 CONTEXT context = void; 1137 1162 context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; 1138 1163 trunk/src/ares/std/traits.d
r498 r509 71 71 template isPointerType( T ) 72 72 { 73 const bool isPointerType = is( T : void* ) || 73 const bool isPointerType = is( typeof(*T) ); 74 } 75 76 77 /** 78 * 79 */ 80 template isReferenceType( T ) 81 { 82 83 const bool isReferenceType = isPointerType!(T) || 74 84 is( T == class ) || 75 85 is( T == interface ) || 76 isFunctionPointerType!( T ) ||77 86 is( T == delegate ); 78 87 } … … 84 93 template isCallableType( T ) 85 94 { 86 const bool isCallableType = is( T == function ) || isFunctionPointerType!( T ) || 95 const bool isCallableType = is( T == function ) || 96 is( typeof(*T) == function ) || 87 97 is( T == delegate ) || 88 98 is( typeof(T.opCall) == function ); 89 99 } 90 91 92 //93 // NOTE: This template is a hack to use in place of "is(T==function)" since94 // it actually detects a function alias, not a function pointer.95 //96 private template isFunctionPointerType( T )97 {98 const bool isFunctionPointerType = T.mangleof.length > 2 &&99 T.mangleof[0] == 'P' &&100 T.mangleof[1] == 'F';101 }trunk/src/ares/std/unicode.d
r498 r509 79 79 is returned. 80 80 81 For details on Unicode processing see 82 $( LINK http://www.utf-8.com/)83 $( LINK http://www.hackcraft.net/xmlUnicode/)84 $( LINK http://www.azillionmonkeys.com/qed/unicode.html/)85 $( LINK http://icu.sourceforge.net/docs/papers/forms_of_unicode/)81 For details on Unicode processing see: 82 $(UL $(LINK http://www.utf-8.com/)) 83 $(UL $(LINK http://www.hackcraft.net/xmlUnicode/)) 84 $(UL $(LINK http://www.azillionmonkeys.com/qed/unicode.html/)) 85 $(UL $(LINK http://icu.sourceforge.net/docs/papers/forms_of_unicode/)) 86 86 87 87 *******************************************************************************/ … … 111 111 char[] output; 112 112 113 wchar[] result = toUtf8 (input, output);113 char[] result = toUtf8 (input, output); 114 114 115 115 // reset output after a realloc … … 587 587 { 588 588 /** 589 * Transcodes the UTF string src to the UTF format required by dst. 589 590 * 591 * Params: 592 * src = The source string to convert. 593 * dst = The destination buffer. 594 * ate = The number of elements consumed from src. 595 * 596 * Returns: 597 * The converted string. 598 * 599 * Throws: 600 * UnicodeException. 590 601 */ 591 DstElem[] convert (SrcElem[] x, DstElem[] dst=null, uint* ate=null)602 DstElem[] convert (SrcElem[] src, DstElem[] dst=null, uint* ate=null) 592 603 { 593 604 static if (is (DstElem == FromElem)) 594 605 { 595 return x;606 return src; 596 607 } 597 608 else … … 601 612 static if (is (DstElem == char)) 602 613 { 603 ret = toUtf8 ( x, dst, ate);614 ret = toUtf8 (src, dst, ate); 604 615 } 605 616 else static if (is (DstElem == wchar)) 606 617 { 607 ret = toUtf16 ( x, dst, ate);618 ret = toUtf16 (src, dst, ate); 608 619 } 609 620 else static if (is (DstElem == dchar)) 610 621 { 611 ret = toUtf32 ( x, dst, ate);622 ret = toUtf32 (src, dst, ate); 612 623 } 613 624 else 614 625 { 615 pragma (msg, "Invalid destination type."); 616 static assert (false); 626 static assert (false, "Invalid destination type."); 617 627 } 618 628 if (ate) trunk/src/ares/std/vararg.d
r498 r509 15 15 16 16 17 /** 18 * The base vararg list type. 19 */ 17 20 alias void* va_list; 18 21 19 22 23 template va_start( T ) 24 { 20 25 /** 26 * This function initializes the supplied argument pointer for subsequent 27 * use by va_arg and va_end. 21 28 * 29 * Params: 30 * ap = The argument pointer to initialize. 31 * paramn = The identifier of the rightmost parameter in the function 32 * parameter list. 22 33 */ 23 template va_start(T)24 {25 34 void va_start(out va_list ap, inout T parmn) 26 35 { … … 30 39 31 40 41 template va_arg( T ) 42 { 32 43 /** 44 * This function returns the next argument in the sequence referenced by 45 * the supplied argument pointer. The argument pointer will be adjusted 46 * to point to the next arggument in the sequence. 47 * 48 * Params: 49 * ap = The argument pointer. 33 50 * 51 * Returns: 52 * The next argument in the sequence. The result is undefined if ap 53 * does not point to a valid argument. 34 54 */ 35 template va_arg(T)36 {37 55 T va_arg(inout va_list ap) 38 56 { … … 45 63 46 64 /** 65 * This function cleans up any resources allocated by va_start. It is 66 * currently a no-op and exists mostly for syntax compatibility with 67 * the variadric argument functions for C. 47 68 * 69 * Params: 70 * ap = The argument pointer. 48 71 */ 49 72 void va_end(va_list ap) … … 54 77 55 78 /** 79 * This function copied the argument pointer src to dst. 56 80 * 81 * Params: 82 * src = The source pointer. 83 * dst = The destination pointer. 57 84 */ 58 void va_copy( out va_list dest, va_list src)85 void va_copy( out va_list dst, va_list src ) 59 86 { 60 d est = src;87 dst = src; 61 88 }
