diff --git a/changelog.dd b/changelog.dd index e6977b368..ba5c89264 100644 --- a/changelog.dd +++ b/changelog.dd @@ -7,6 +7,7 @@ $(VERSION 055, ddd mm, 2011, =================================================, $(LI Values for GDC and LDC were added to std.compiler.Vendor.) $(LI Added functions to std.bitswap for generically handling swapping endianness.) + $(LI Added std.parallelism.TaskPool.workerIndex.) $(LI std.math.tgamma, lgamma, erf, and erfc are now deprecated. The equivalent functions in std.mathspecial should be used instead.) ) diff --git a/std/algorithm.d b/std/algorithm.d index 361003eaa..570ad8ffb 100644 --- a/std/algorithm.d +++ b/std/algorithm.d @@ -4630,8 +4630,8 @@ if (isInputRange!R1 && isInputRange!R2 && !(isSomeString!R1 && isSomeString!R2)) { for (;; r1.popFront(), r2.popFront()) { - if (r1.empty) return -r2.empty; - if (r2.empty) return r1.empty; + if (r1.empty) return -cast(int)!r2.empty; + if (r2.empty) return !r1.empty; auto a = r1.front, b = r2.front; if (binaryFun!pred(a, b)) return -1; if (binaryFun!pred(b, a)) return 1; @@ -4721,6 +4721,16 @@ unittest assert(result > 0); result = cmp("aaa", "aaa"d); assert(result == 0); + result = cmp(cast(int[])[], cast(int[])[]); + assert(result == 0); + result = cmp([1, 2, 3], [1, 2, 3]); + assert(result == 0); + result = cmp([1, 3, 2], [1, 2, 3]); + assert(result > 0); + result = cmp([1, 2, 3], [1L, 2, 3, 4]); + assert(result < 0); + result = cmp([1L, 2, 3], [1, 2]); + assert(result > 0); } // MinType diff --git a/std/bitmanip.d b/std/bitmanip.d index dc329cafe..174c91cda 100644 --- a/std/bitmanip.d +++ b/std/bitmanip.d @@ -28,11 +28,12 @@ import std.traits; private string myToStringx(ulong n) -{ enum s = "0123456789"; +{ + enum s = "0123456789"; if (n < 10) - return s[cast(size_t)n..cast(size_t)n+1]; + return s[cast(size_t)n..cast(size_t)n+1]; else - return myToStringx(n / 10) ~ myToStringx(n % 10); + return myToStringx(n / 10) ~ myToStringx(n % 10); } private string myToString(ulong n) @@ -79,17 +80,17 @@ private template createAccessors( static assert(len == 1); enum result = // getter - "bool " ~ name ~ "() const { return " + "@property bool " ~ name ~ "() const { return " ~"("~store~" & "~myToString(maskAllElse)~") != 0;}\n" // setter - ~"void " ~ name ~ "(bool v){" + ~"@property void " ~ name ~ "(bool v){" ~"if (v) "~store~" |= "~myToString(maskAllElse)~";" ~"else "~store~" &= ~"~myToString(maskAllElse)~";}\n"; } else { // getter - enum result = T.stringof~" "~name~"() const { auto result = " + enum result = "@property "~T.stringof~" "~name~"() const { auto result = " "("~store~" & " ~ myToString(maskAllElse) ~ ") >>" ~ myToString(offset) ~ ";" @@ -99,7 +100,7 @@ private template createAccessors( : "") ~ " return cast("~T.stringof~") result;}\n" // setter - ~"void "~name~"("~T.stringof~" v){ " + ~"@property void "~name~"("~T.stringof~" v){ " ~"assert(v >= "~name~"_min); " ~"assert(v <= "~name~"_max); " ~store~" = cast(typeof("~store~"))" @@ -120,7 +121,7 @@ private template createStoreName(Ts...) static if (Ts.length < 2) enum createStoreName = ""; else - enum createStoreName = Ts[1] ~ createStoreName!(Ts[3 .. $]); + enum createStoreName = "_" ~ Ts[1] ~ createStoreName!(Ts[3 .. $]); } private template createFields(string store, size_t offset, Ts...) @@ -202,6 +203,57 @@ template bitfields(T...) enum { bitfields = createFields!(createStoreName!(T), 0, T).result } } +unittest +{ + static struct Integrals { + bool checkExpectations(bool eb, int ei, short es) { return b == eb && i == ei && s == es; } + + mixin(bitfields!( + bool, "b", 1, + uint, "i", 3, + short, "s", 4)); + } + Integrals i; + assert(i.checkExpectations(false, 0, 0)); + i.b = true; + assert(i.checkExpectations(true, 0, 0)); + i.i = 7; + assert(i.checkExpectations(true, 7, 0)); + i.s = -8; + assert(i.checkExpectations(true, 7, -8)); + i.s = 7; + assert(i.checkExpectations(true, 7, 7)); + + enum A { True, False } + enum B { One, Two, Three, Four } + static struct Enums { + bool checkExpectations(A ea, B eb) { return a == ea && b == eb; } + + mixin(bitfields!( + A, "a", 1, + B, "b", 2, + uint, "", 5)); + } + Enums e; + assert(e.checkExpectations(A.True, B.One)); + e.a = A.False; + assert(e.checkExpectations(A.False, B.One)); + e.b = B.Three; + assert(e.checkExpectations(A.False, B.Three)); + + static struct SingleMember { + bool checkExpectations(bool eb) { return b == eb; } + + mixin(bitfields!( + bool, "b", 1, + uint, "", 7)); + } + SingleMember f; + assert(f.checkExpectations(false)); + f.b = true; + assert(f.checkExpectations(true)); +} + /** Allows manipulating the fraction, exponent, and sign parts of a $(D_PARAM float) separately. The definition is: @@ -304,46 +356,43 @@ struct BitArray { size_t len; size_t* ptr; -version(X86) - enum bitsPerSizeT = 32; -else version(X86_64) - enum bitsPerSizeT = 64; -else - static assert(false, "unknown platform"); + version(X86) + enum bitsPerSizeT = 32; + else version(X86_64) + enum bitsPerSizeT = 64; + else + static assert(false, "unknown platform"); - const size_t dim() + @property const size_t dim() { return (len + (bitsPerSizeT-1)) / bitsPerSizeT; } - @property + @property const size_t length() { - const size_t length() - { - return len; - } + return len; + } - void length(size_t newlen) + @property void length(size_t newlen) + { + if (newlen != len) { - if (newlen != len) + size_t olddim = dim; + size_t newdim = (newlen + (bitsPerSizeT-1)) / bitsPerSizeT; + + if (newdim != olddim) { - size_t olddim = dim(); - size_t newdim = (newlen + (bitsPerSizeT-1)) / bitsPerSizeT; - - if (newdim != olddim) - { - // Create a fake array so we can use D's realloc machinery - auto b = ptr[0 .. olddim]; - b.length = newdim; // realloc - ptr = b.ptr; - if (newdim & (bitsPerSizeT-1)) - { // Set any pad bits to 0 - ptr[newdim - 1] &= ~(~0 << (newdim & (bitsPerSizeT-1))); - } + // Create a fake array so we can use D's realloc machinery + auto b = ptr[0 .. olddim]; + b.length = newdim; // realloc + ptr = b.ptr; + if (newdim & (bitsPerSizeT-1)) + { // Set any pad bits to 0 + ptr[newdim - 1] &= ~(~0 << (newdim & (bitsPerSizeT-1))); } - - len = newlen; } + + len = newlen; } } @@ -392,7 +441,7 @@ else /********************************************** * Support for array.dup property for BitArray. */ - BitArray dup() + @property BitArray dup() { BitArray ba; @@ -428,7 +477,8 @@ else int result; for (size_t i = 0; i < len; i++) - { bool b = opIndex(i); + { + bool b = opIndex(i); result = dg(b); this[i] = b; if (result) @@ -443,7 +493,8 @@ else int result; for (size_t i = 0; i < len; i++) - { bool b = opIndex(i); + { + bool b = opIndex(i); result = dg(i, b); this[i] = b; if (result) @@ -464,7 +515,8 @@ else foreach (b;a) { switch (i) - { case 0: assert(b == true); break; + { + case 0: assert(b == true); break; case 1: assert(b == false); break; case 2: assert(b == true); break; default: assert(0); @@ -475,7 +527,8 @@ else foreach (j,b;a) { switch (j) - { case 0: assert(b == true); break; + { + case 0: assert(b == true); break; case 1: assert(b == false); break; case 2: assert(b == true); break; default: assert(0); @@ -488,29 +541,29 @@ else * Support for array.reverse property for BitArray. */ - BitArray reverse() - out (result) + @property BitArray reverse() + out (result) + { + assert(result == this); + } + body + { + if (len >= 2) { - assert(result == this); - } - body - { - if (len >= 2) - { - bool t; - size_t lo, hi; + bool t; + size_t lo, hi; - lo = 0; - hi = len - 1; - for (; lo < hi; lo++, hi--) - { - t = this[lo]; - this[lo] = this[hi]; - this[hi] = t; - } + lo = 0; + hi = len - 1; + for (; lo < hi; lo++, hi--) + { + t = this[lo]; + this[lo] = this[hi]; + this[hi] = t; } - return this; } + return this; + } unittest { @@ -533,50 +586,50 @@ else * Support for array.sort property for BitArray. */ - BitArray sort() - out (result) + @property BitArray sort() + out (result) + { + assert(result == this); + } + body + { + if (len >= 2) { - assert(result == this); - } - body - { - if (len >= 2) - { - size_t lo, hi; + size_t lo, hi; - lo = 0; - hi = len - 1; + lo = 0; + hi = len - 1; + while (1) + { while (1) { - while (1) - { - if (lo >= hi) - goto Ldone; - if (this[lo] == true) - break; - lo++; - } - - while (1) - { - if (lo >= hi) - goto Ldone; - if (this[hi] == false) - break; - hi--; - } - - this[lo] = false; - this[hi] = true; - + if (lo >= hi) + goto Ldone; + if (this[lo] == true) + break; lo++; + } + + while (1) + { + if (lo >= hi) + goto Ldone; + if (this[hi] == false) + break; hi--; } - Ldone: - ; + + this[lo] = false; + this[hi] = true; + + lo++; + hi--; } - return this; + Ldone: + ; } + return this; + } unittest { @@ -597,7 +650,8 @@ else */ const bool opEquals(const ref BitArray a2) - { int i; + { + int i; if (this.length != a2.length) return 0; // not equal @@ -660,7 +714,8 @@ else break; // not equal } for (uint j = i * 8; j < len; j++) - { ubyte mask = cast(ubyte)(1 << j); + { + ubyte mask = cast(ubyte)(1 << j); int c; c = cast(int)(p1[i] & mask) - cast(int)(p2[i] & mask); @@ -779,7 +834,7 @@ else */ BitArray opCom() { - auto dim = this.dim(); + auto dim = this.dim; BitArray result; @@ -818,7 +873,7 @@ else } body { - auto dim = this.dim(); + auto dim = this.dim; BitArray result; @@ -858,7 +913,7 @@ else } body { - auto dim = this.dim(); + auto dim = this.dim; BitArray result; @@ -898,7 +953,7 @@ else } body { - auto dim = this.dim(); + auto dim = this.dim; BitArray result; @@ -940,7 +995,7 @@ else } body { - auto dim = this.dim(); + auto dim = this.dim; BitArray result; @@ -980,7 +1035,7 @@ else } body { - auto dim = this.dim(); + auto dim = this.dim; for (size_t i = 0; i < dim; i++) ptr[i] &= e2.ptr[i]; @@ -1016,7 +1071,7 @@ else } body { - auto dim = this.dim(); + auto dim = this.dim; for (size_t i = 0; i < dim; i++) ptr[i] |= e2.ptr[i]; @@ -1051,7 +1106,7 @@ else } body { - auto dim = this.dim(); + auto dim = this.dim; for (size_t i = 0; i < dim; i++) ptr[i] ^= e2.ptr[i]; @@ -1088,7 +1143,7 @@ else } body { - auto dim = this.dim(); + auto dim = this.dim; for (size_t i = 0; i < dim; i++) ptr[i] &= ~e2.ptr[i]; diff --git a/std/file.d b/std/file.d index c6285ab22..b8fc4c076 100644 --- a/std/file.d +++ b/std/file.d @@ -1182,7 +1182,7 @@ uint getAttributes(in char[] name) name = The file to get the symbolic link attributes of. Throws: - FileException on error. + $(D FileException) on error. +/ uint getLinkAttributes(in char[] name) { @@ -1206,7 +1206,7 @@ uint getLinkAttributes(in char[] name) name = The path to the file. Throws: - FileException if the given file does not exist. + $(D FileException) if the given file does not exist. Examples: -------------------- @@ -1504,7 +1504,7 @@ unittest name = The path to the file. Throws: - FileException if the given file does not exist. + $(D FileException) if the given file does not exist. +/ @property bool isSymlink(C)(const(C)[] name) { @@ -2650,7 +2650,7 @@ void copy(in char[] from, in char[] to) Set access/modified times of file $(D name). Throws: - $(D_PARAM FileException) on error. + $(D FileException) on error. +/ version(StdDdoc) deprecated void setTimes(in char[] name, d_time fta, d_time ftm); else deprecated void setTimes(C)(in C[] name, d_time fta, d_time ftm) @@ -2764,7 +2764,7 @@ unittest recursively. Throws: - FileException if there is an error (including if the given + $(D FileException) if there is an error (including if the given file is not a directory). +/ void rmdirRecurse(in char[] pathname) @@ -2780,7 +2780,7 @@ void rmdirRecurse(in char[] pathname) recursively. Throws: - FileException if there is an error (including if the given + $(D FileException) if there is an error (including if the given file is not a directory). +/ void rmdirRecurse(ref DirEntry de) @@ -3259,7 +3259,7 @@ unittest name = The file (or directory) to get a DirEntry for. Throws: - FileException) if the file does not exist. + $(D FileException) if the file does not exist. +/ DirEntry dirEntry(in char[] name) { @@ -3515,7 +3515,7 @@ unittest The names in the contents do not include the pathname. Throws: - FileException on error. + $(D FileException) on error. Examples: This program lists all the files and subdirectories in its diff --git a/std/getopt.d b/std/getopt.d index a08d6591c..5a83830b8 100644 --- a/std/getopt.d +++ b/std/getopt.d @@ -92,7 +92,7 @@ void main(string[] args) getopt(args, "verbose", &verbose, "debug", &debugging); --------- - $(LI $(I Numeric options.) If an option is bound to a numeric type, a + )$(LI $(I Numeric options.) If an option is bound to a numeric type, a number is expected as the next option, or right within the option separated with an "=" sign: @@ -118,7 +118,7 @@ To set $(D timeout) to $(D 5), invoke the program with either $(D expects a parameter, e.g. in the command line "--paranoid 42 --paranoid", the "42" does not set $(D paranoid) to 42; instead, $(D paranoid) is set to 2 and "42" is not considered - as part of the normal program arguments.)) + as part of the normal program arguments.))) $(LI $(I Enum options.) If an option is bound to an enum, an enum symbol as a string is expected as the next option, or right within the option separated @@ -131,7 +131,7 @@ To set $(D timeout) to $(D 5), invoke the program with either $(D --------- To set $(D color) to $(D Color.yes), invoke the program with either $(D ---color=yes) or $(D --color yes). +--color=yes) or $(D --color yes).) $(LI $(I String options.) If an option is bound to a string, a string is expected as the next option, or right within the option separated @@ -143,9 +143,9 @@ getopt(args, "output", &outputFile); --------- Invoking the program with "--output=myfile.txt" or "--output - myfile.txt" will set $(D outputFile) to "myfile.txt".) If you want to + myfile.txt" will set $(D outputFile) to "myfile.txt". If you want to pass a string containing spaces, you need to use the quoting that is - appropriate to your shell, e.g. --output='my file.txt'. + appropriate to your shell, e.g. --output='my file.txt'.) $(LI $(I Array options.) If an option is bound to an array, a new element is appended to the array each time the option occurs: @@ -169,7 +169,7 @@ getopt(args, "tune", &tuningParms); --------- Invoking the program with e.g. "--tune=alpha=0.5 --tune beta=0.6" will -set $(D tuningParms) to [ "alpha" : 0.5, "beta" : 0.6 ].) In general, +set $(D tuningParms) to [ "alpha" : 0.5, "beta" : 0.6 ]. In general, keys and values can be of any parsable types.) $(LI $(I Delegate options.) An option can be bound to a delegate with @@ -180,7 +180,7 @@ $(UL $(LI In the $(D void delegate()) case, the delegate is invoked whenever the option is seen.) $(LI In the $(D void delegate(string option)) case, the option string (without the leading dash(es)) is passed to the delegate. After that, the option string is considered -handled and removed from the options array.) +handled and removed from the options array. --------- void main(string[] args) @@ -202,11 +202,11 @@ void main(string[] args) } --------- -$(LI In the $(D void delegate(string option, string value)) case, the +)$(LI In the $(D void delegate(string option, string value)) case, the option string is handled as an option with one argument, and parsed accordingly. The option and its value are passed to the delegate. After that, whatever was passed to the delegate is -considered handled and removed from the list.) +considered handled and removed from the list. --------- void main(string[] args) diff --git a/std/parallelism.d b/std/parallelism.d index 1f9c2346b..e781b6614 100644 --- a/std/parallelism.d +++ b/std/parallelism.d @@ -1135,20 +1135,6 @@ private: if(!isSingleTask) waiterCondition.notifyAll(); } - /* - Gets the index of the current thread relative to this pool. Any thread - not in this pool will receive an index of 0. The worker threads in - this pool receive indices of 1 through this.size(). - - The worker index is used for maintaining worker-local storage. - */ - size_t workerIndex() { - immutable rawInd = threadIndex; - return (rawInd >= instanceStartIndex && - rawInd < instanceStartIndex + size) ? - (rawInd - instanceStartIndex + 1) : 0; - } - // Private constructor for creating dummy pools that only have one thread, // only execute one Task, and then terminate. This is used for // Task.executeInNewThread(). @@ -2184,6 +2170,48 @@ public: } } + /** + Gets the index of the current thread relative to this $(D TaskPool). Any + thread not in this pool will receive an index of 0. The worker threads in + this pool receive unique indices of 1 through $(D this.size). + + This function is useful for maintaining worker-local resources. + + Examples: + --- + // Execute a loop that computes the greatest common divisor of every + // number from 0 through 999 with 42 in parallel. Write the results out to + // a set of files, one for each thread. This allows results to be written + // out without any synchronization. + + import std.stdio, std.conv, std.range, std.numeric, std.parallelism; + + void main() { + auto fileHandles = new File[taskPool.size + 1]; + scope(exit) { + foreach(ref handle; fileHandles) { + handle.close(); + } + } + + foreach(i, ref handle; fileHandles) { + handle = File("workerResults" ~ to!string(i) ~ ".txt", "wb"); + } + + foreach(num; parallel(iota(1_000))) { + auto outHandle = fileHandles[taskPool.workerIndex]; + outHandle.writeln(num, '\t', gcd(num, 42)); + } + } + --- + */ + size_t workerIndex() @property @safe const nothrow { + immutable rawInd = threadIndex; + return (rawInd >= instanceStartIndex && + rawInd < instanceStartIndex + size) ? + (rawInd - instanceStartIndex + 1) : 0; + } + /** Struct for creating worker-local storage. Worker-local storage is thread-local storage that exists only for worker threads in a given diff --git a/std/range.d b/std/range.d index 61c69c5ef..ec307e5b2 100644 --- a/std/range.d +++ b/std/range.d @@ -5483,6 +5483,7 @@ if (isRandomAccessRange!Range) this(Range input) { this._input = input; + if(!__ctfe) debug { // Check the sortedness of the input diff --git a/std/string.d b/std/string.d index d3894c506..4a83e58cd 100644 --- a/std/string.d +++ b/std/string.d @@ -875,7 +875,7 @@ unittest /************************************ * $(RED Scheduled for deprecation in January 2012. - * Please use $(D toLower instead.) + * Please use $(D toLower) instead.) * * Convert string s[] to lower case. */ @@ -934,7 +934,7 @@ unittest /** $(RED Scheduled for deprecation in January 2012. - Please use toLowerInPlace instead.) + Please use $(D toLowerInPlace) instead.) Converts $(D s) to lowercase in place. */ @@ -1050,7 +1050,7 @@ unittest /************************************ * $(RED Scheduled for deprecation in January 2012. - * Please use toUpper instead.) + * Please use $(D toUpper) instead.) * * Convert string s[] to upper case. */ @@ -1360,7 +1360,7 @@ unittest /******************************************** * $(RED Deprecated. It will be removed in February 2012. - * Please use $(XREF array, replicate) instead. + * Please use $(XREF array, replicate) instead.) * * Repeat $(D s) for $(D n) times. */ @@ -1447,7 +1447,7 @@ unittest /***************************************** * $(RED Scheduled for deprecation in January 2012. - * Please use $(D stripLeft) instead. + * Please use $(D stripLeft) instead.) * * Strips leading whitespace. */ @@ -1483,7 +1483,7 @@ S stripLeft(S)(S s) @safe pure /***************************************** * $(RED Scheduled for deprecation in January 2012. - * Please use $(D stripRight) instead. + * Please use $(D stripRight) instead.) * * Strips trailing whitespace. */ @@ -1871,7 +1871,7 @@ body /************************************************ * $(RED Scheduled for deprecation in January 2012. - * Please use $(D detab) instead. + * Please use $(D detab) instead.) * * Replace tabs with the appropriate number of spaces. * tabsize is the distance between tab stops.