Changeset 509

Show
Ignore:
Timestamp:
07/12/06 19:22:10 (6 years ago)
Author:
sean
Message:

Buulk check-in of fixes. Added documentation, restructuring code where necessary to appease DDoc, and made some resource management changes to Thread.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/ares/std/array.d

    r498 r509  
    4545 
    4646 
    47 /** 
    48  * Temporary until a predicate module can be created. 
    49  */ 
    5047template equalTo( Elem ) 
    5148{ 
    5249    /** 
    53      * 
     50     * Temporary until a predicate module can be created. 
    5451     */ 
    5552    bool equalTo( Elem a, Elem  b ) 
     
    6057 
    6158 
    62 /** 
    63  * 
    64  */ 
    6559 /+ 
    6660template find( Elem ) 
     
    7670 
    7771 
    78 /** 
    79  * 
    80  */ 
    8172 template find( Elem, Pred ) 
    8273{ 
     
    109100 
    110101 
    111 /** 
    112  * 
    113  */ 
    114102template find( Elem ) 
    115103{ 
     
    125113 
    126114 
    127 /** 
    128  * 
    129  */ 
    130115template find( Elem, Pred ) 
    131116{ 
     
    248233 
    249234 
    250 /** 
    251  * 
    252  */ 
    253235 /+ 
    254236template rfind( Elem ) 
     
    264246 
    265247 
    266 /** 
    267  * 
    268  */ 
    269248template rfind( Elem, Pred ) 
    270249{ 
     
    302281 
    303282 
    304 /** 
    305  * 
    306  */ 
    307283template rfind( Elem ) 
    308284{ 
     
    318294 
    319295 
    320 /** 
    321  * 
    322  */ 
    323296template rfind( Elem, Pred ) 
    324297{ 
  • trunk/src/ares/std/atomic.d

    r498 r509  
    7676private 
    7777{ 
     78  version( DDoc ) {} else 
     79  { 
    7880    import std.traits; 
    7981 
     
    111113    } 
    112114} 
     115} 
     116 
     117 
     118//////////////////////////////////////////////////////////////////////////////// 
     119// DDoc Documentation for Atomic Functions 
     120//////////////////////////////////////////////////////////////////////////////// 
     121 
     122 
     123version( 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} 
    113295 
    114296 
     
    118300 
    119301 
    120 private 
     302else version( X86 ) 
    121303{ 
    122     version( X86 ) 
     304    private 
    123305    { 
    124306        //////////////////////////////////////////////////////////////////////// 
     
    127309 
    128310 
    129         // 
    130311        // NOTE: Strictly speaking, the x86 supports atomic operations on 
    131312        //       unaligned values.  However, this is far slower than the 
    132313        //       common case, so such behavior should be prohibited. 
    133         // 
    134314        template atomicValueIsProperlyAligned( T ) 
    135315        { 
     
    10941274        } 
    10951275    } 
    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 
    11061282    // 
    11071283    // NOTE: x86 loads implicitly have acquire semantics so a membar is only necessary on release 
    11081284    // 
    11091285 
    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      */ 
    11191286    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; } /// ditto 
    1121     template atomicLoad( msync ms : msync.ddhlb, T ) { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } /// ditto 
    1122     template atomicLoad( msync ms : msync.acq, T )   { alias doAtomicLoad!(isSinkOp!(ms),T) atomicLoad; } /// ditto 
     1287    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; } 
    11231290 
    11241291    // 
     
    11261293    // 
    11271294 
    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      */ 
    11351295    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 
    11521300    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 
    11721305    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 
    11921310    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; } /// ditto 
    1194     template atomicDecrement( msync ms : msync.acq, T )  { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } /// ditto 
    1195     template atomicDecrement( msync ms : msync.rel, T )  { alias doAtomicDecrement!(ms!=msync.none,T) atomicDecrement; } /// ditto 
     1311    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; } 
    11961314} 
    11971315 
     
    12031321 
    12041322/** 
    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. 
    12121332 */ 
    12131333struct Atomic( T ) 
    12141334{ 
     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 
    12151346    /** 
    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. 
    12171349     * 
    12181350     * Returns: 
    12191351     *  The loaded value. 
    12201352     */ 
    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" ); 
    12251370 
    12261371    /** 
    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. 
    12281374     * 
    12291375     * Params: 
    12301376     *  newval  = The value to store. 
    12311377     */ 
    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" ); 
    12361395 
    12371396    /** 
    1238      * Stores 'newval' to the memory referenced by this value if val is equal to 'equalTo'.  This operation 
    1239      * 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. 
    12401399     * 
    12411400     * Returns: 
     
    12461405     *  equalTo = The comparison value. 
    12471406     */ 
    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     */ 
    12531422    static if( isValidNumericType!(T) ) 
    12541423    { 
     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 
    12551435        /** 
    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. 
    12611443         * 
    12621444         * 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 
    12651448         *  occur between the increment and successive load operation. 
    12661449         */ 
    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" ); 
    12711467 
    12721468        /** 
    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. 
    12781476         * 
    12791477         * 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 
    12821481         *  occur between the increment and successive load operation. 
    12831482         */ 
    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        } 
    12881488    } 
    12891489 
     
    13001500private 
    13011501{ 
     1502  version( DDoc ) {} else 
     1503  { 
    13021504    template testLoad( msync ms, T ) 
    13031505    { 
     
    14051607        } 
    14061608    } 
     1609  } 
    14071610} 
    14081611 
  • trunk/src/ares/std/exception.d

    r498 r509  
    199199 *  file = The name of the file that signaled this error. 
    200200 *  line = The line number on which this error occurred. 
    201  *  msg  = An error message supplied by the user. 
    202201 */ 
    203202extern (C) void onAssertError( char[] file, uint line ) 
    204203{ 
    205     if( !assertHandler
     204    if( assertHandler is null
    206205        throw new AssertException( file, line ); 
    207206    assertHandler( file, line ); 
     
    217216 *  file = The name of the file that signaled this error. 
    218217 *  line = The line number on which this error occurred. 
     218 *  msg  = An error message supplied by the user. 
    219219 */ 
    220220extern (C) void onAssertErrorMsg( char[] file, uint line, char[] msg ) 
    221221{ 
    222     if( !assertHandler
     222    if( assertHandler is null
    223223        throw new AssertException( msg, file, line ); 
    224224    assertHandler( file, line, msg ); 
     
    240240extern (C) bool onCollectResource( Object obj ) 
    241241{ 
    242     if( !collectHandler
     242    if( collectHandler is null
    243243        return true; 
    244244    return collectHandler( obj ); 
  • trunk/src/ares/std/thread.d

    r506 r509  
    7676        // entry point for Windows threads 
    7777        // 
    78         extern (Windows) uint threadFunc( void* arg ) 
     78        extern (Windows) uint thread_entryPoint( void* arg ) 
    7979        { 
    8080            Thread  obj = cast(Thread) arg; 
     
    160160        // entry point for POSIX threads 
    161161        // 
    162         extern (C) void* threadFunc( void* arg ) 
     162        extern (C) void* thread_entryPoint( void* arg ) 
    163163        { 
    164164            Thread  obj = cast(Thread) arg; 
     
    177177            // an exception is in-flight? 
    178178 
    179            static extern (C) void cleanupHandler( void* arg ) 
     179            extern (C) void thread_cleanupHandler( void* arg ) 
    180180            { 
    181181                Thread  obj = Thread.getThis(); 
     
    194194 
    195195            pthread_cleanup cleanup; 
    196            cleanup.push( &cleanupHandler, obj ); 
     196            cleanup.push( &thread_cleanupHandler, obj ); 
    197197 
    198198            try 
     
    214214 
    215215 
    216         extern (C) void suspendHandler( int sig ) 
     216        extern (C) void thread_suspendHandler( int sig ) 
    217217        in 
    218218        { 
     
    283283 
    284284 
    285         extern (C) void resumeHandler( int sig ) 
     285        extern (C) void thread_resumeHandler( int sig ) 
    286286        in 
    287287        { 
     
    423423 
    424424 
     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 
    425449    //////////////////////////////////////////////////////////////////////////// 
    426450    // General Actions 
     
    450474            version( Win32 ) 
    451475            { 
    452                 m_hndl = cast(HANDLE) _beginthreadex( null, 0, &threadFunc, this, 0, &m_addr ); 
     476                m_hndl = cast(HANDLE) _beginthreadex( null, 0, &thread_entryPoint, this, 0, &m_addr ); 
    453477                if( cast(size_t) m_hndl == 0 ) 
    454478                    throw new ThreadException( "Error creating thread" ); 
     
    459483                scope( failure ) m_isRunning = false; 
    460484 
    461                 if( pthread_create( &m_addr, null, &threadFunc, this ) != 0 ) 
     485                if( pthread_create( &m_addr, null, &thread_entryPoint, this ) != 0 ) 
    462486                    throw new ThreadException( "Error creating thread" ); 
    463487            } 
     
    480504            if( WaitForSingleObject( m_hndl, INFINITE ) != WAIT_OBJECT_0 ) 
    481505                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; 
    482512        } 
    483513        else version( Posix ) 
     
    485515            if( pthread_join( m_addr, null ) != 0 ) 
    486516                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; 
    487522        } 
    488523    } 
     
    532567    final bool isRunning() 
    533568    { 
    534         if( !m_addr
     569        if( m_addr == m_addr.init
    535570        { 
    536571            return false; 
     
    906941    { 
    907942        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. 
    908947        assert( !t.isRunning ); 
     948    } 
    909949    } 
    910950    body 
     
    926966        //       and having m_next and m_prev be non-null is a good way to 
    927967        //       ensure that. 
    928  
    929         // NOTE: Cleanup of any thread resources should occur as soon as the 
    930         //       thread is detected to no longer be running, and this seemed 
    931         //       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         } 
    943968    } 
    944969 
     
    10131038        else 
    10141039            sigusr1.sa_flags   = 0; 
    1015         sigusr1.sa_handler = &suspendHandler; 
     1040        sigusr1.sa_handler = &thread_suspendHandler; 
    10161041        // NOTE: We want to ignore all signals while in this handler, so fill 
    10171042        //       sa_mask to indicate this. 
     
    10231048        //       restart. 
    10241049        sigusr2.sa_flags   = 0; 
    1025         sigusr2.sa_handler = &resumeHandler; 
     1050        sigusr2.sa_handler = &thread_resumeHandler; 
    10261051        // NOTE: We want to ignore all signals while in this handler, so fill 
    10271052        //       sa_mask to indicate this. 
     
    11341159            } 
    11351160 
    1136            CONTEXT context
     1161            CONTEXT context = void
    11371162            context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; 
    11381163 
  • trunk/src/ares/std/traits.d

    r498 r509  
    7171template isPointerType( T ) 
    7272{ 
    73     const bool isPointerType = is( T : void* )      || 
     73    const bool isPointerType = is( typeof(*T) ); 
     74
     75 
     76 
     77/** 
     78 * 
     79 */ 
     80template isReferenceType( T ) 
     81
     82 
     83    const bool isReferenceType = isPointerType!(T)  || 
    7484                               is( T == class )     || 
    7585                               is( T == interface ) || 
    76                                isFunctionPointerType!( T ) || 
    7786                               is( T == delegate ); 
    7887} 
     
    8493template isCallableType( T ) 
    8594{ 
    86     const bool isCallableType = is( T == function ) || isFunctionPointerType!( T ) || 
     95    const bool isCallableType = is( T == function )             || 
     96                                is( typeof(*T) == function )    || 
    8797                                is( T == delegate ) || 
    8898                                is( typeof(T.opCall) == function ); 
    8999} 
    90  
    91  
    92 // 
    93 // NOTE: This template is a hack to use in place of "is(T==function)" since 
    94 //       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  
    7979        is returned. 
    8080 
    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/)
    8686 
    8787*******************************************************************************/ 
     
    111111        char[] output; 
    112112 
    113         wchar[] result = toUtf8 (input, output); 
     113                char[] result = toUtf8 (input, output); 
    114114 
    115115        // reset output after a realloc 
     
    587587{ 
    588588    /** 
     589     * Transcodes the UTF string src to the UTF format required by dst. 
    589590     * 
     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. 
    590601     */ 
    591     DstElem[] convert (SrcElem[] x, DstElem[] dst=null, uint* ate=null) 
     602    DstElem[] convert (SrcElem[] src, DstElem[] dst=null, uint* ate=null) 
    592603    { 
    593604        static if (is (DstElem == FromElem)) 
    594605        { 
    595             return x
     606            return src
    596607        } 
    597608        else 
     
    601612            static if (is (DstElem == char)) 
    602613            { 
    603                 ret = toUtf8 (x, dst, ate); 
     614                ret = toUtf8 (src, dst, ate); 
    604615            } 
    605616            else static if (is (DstElem == wchar)) 
    606617            { 
    607                 ret = toUtf16 (x, dst, ate); 
     618                ret = toUtf16 (src, dst, ate); 
    608619            } 
    609620            else static if (is (DstElem == dchar)) 
    610621            { 
    611                 ret = toUtf32 (x, dst, ate); 
     622                ret = toUtf32 (src, dst, ate); 
    612623            } 
    613624            else 
    614625            { 
    615                 pragma (msg, "Invalid destination type."); 
    616                 static assert (false); 
     626                static assert (false, "Invalid destination type."); 
    617627            } 
    618628            if (ate) 
  • trunk/src/ares/std/vararg.d

    r498 r509  
    1515 
    1616 
     17/** 
     18 * The base vararg list type. 
     19 */ 
    1720alias void* va_list; 
    1821 
    1922 
     23template va_start( T ) 
     24{ 
    2025/** 
     26     * This function initializes the supplied argument pointer for subsequent 
     27     * use by va_arg and va_end. 
    2128 * 
     29     * Params: 
     30     *  ap      = The argument pointer to initialize. 
     31     *  paramn  = The identifier of the rightmost parameter in the function 
     32     *            parameter list. 
    2233 */ 
    23 template va_start(T) 
    24 { 
    2534    void va_start(out va_list ap, inout T parmn) 
    2635    { 
     
    3039 
    3140 
     41template va_arg( T ) 
     42{ 
    3243/** 
     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. 
    3350 * 
     51     * Returns: 
     52     *  The next argument in the sequence.  The result is undefined if ap 
     53     *  does not point to a valid argument. 
    3454 */ 
    35 template va_arg(T) 
    36 { 
    3755    T va_arg(inout va_list ap) 
    3856    { 
     
    4563 
    4664/** 
     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. 
    4768 * 
     69 * Params: 
     70 *  ap  = The argument pointer. 
    4871 */ 
    4972void va_end(va_list ap) 
     
    5477 
    5578/** 
     79 * This function copied the argument pointer src to dst. 
    5680 * 
     81 * Params: 
     82 *  src = The source pointer. 
     83 *  dst = The destination pointer. 
    5784 */ 
    58 void va_copy(out va_list dest, va_list src
     85void va_copy( out va_list dst, va_list src
    5986{ 
    60     dest = src; 
     87    dst = src; 
    6188}