digitalmars.D.learn - Newbie problem
- Roger Stokes (26/26) Jun 19 2013 I'd be grateful for advice. The problem is that I can't get the
- Adam D. Ruppe (18/22) Jun 19 2013 The problem here is that byChunk returns a mutable buffer, type
- Roger Stokes (76/89) Jun 19 2013 Many thanks for swift response. I'm still in difficulty, alas.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (38/47) Jun 19 2013 For a clean exit, the owner must tell the worker that there is no more
- Roger Stokes (4/57) Jun 20 2013 Many thanks, Ali
- Adam D. Ruppe (15/22) Jun 19 2013 Oh, I thought you were writing to a socket. Yeah, to a different
- Roger Stokes (2/26) Jun 20 2013
I'd be grateful for advice. The problem is that I can't get the example on page 406-7 of the"The D Programming Language " to compile. I've cut and pasted the text from the website, and corrected the typo (undefined tgt, so use stdout instead). I get this diagnostic: page406x.d(11): Error: cannot implicitly convert expression (__r24.front()) of type ubyte[] to immutable(ubyte)[] from this input: import std.algorithm, std.concurrency, std.stdio; void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach (immutable(ubyte)[] buffer; stdin.byChunk(bufferSize)) { send(tid, buffer); } } void fileWriter() { // Write loop for (;;) { auto buffer = receiveOnly!(immutable(ubyte)[])(); stdout.write(buffer); } }
Jun 19 2013
On Wednesday, 19 June 2013 at 15:25:15 UTC, Roger Stokes wrote:page406x.d(11): Error: cannot implicitly convert expression (__r24.front()) of type ubyte[] to immutable(ubyte)[]foreach (immutable(ubyte)[] buffer; stdin.byChunk(bufferSize)) {The problem here is that byChunk returns a mutable buffer, type ubyte[]. If you said "foreach(ubyte[] buffer; stdin.byChunk(bufferSize)) {...}" you should be able to compile it. I think this was changed after the book was written because byChunk now reuses its buffer. Each time through the loop, it overwrites the old data with the next batch, which means the old data cannot be immutable. (The reason for reusing it is to avoid allocating new memory for a fresh buffer every time.) Since you aren't keeping a copy of the buffer, just changing the type should be enough for your program to work. If you needed an immutable copy, if you were going to store it or something, the way you'd do that is to call buffer.idup: foreach(ubyte[] temporaryBuffer; stdin.byChunk(bufferSize) { immutable(ubyte)[] permanentBuffer = temporaryBuffer.idup; // you can now use the permanentBuffer }
Jun 19 2013
Many thanks for swift response. I'm still in difficulty, alas. There were two possibilities suggested: firstly,Adam D. Ruppe wrote:The problem here is that byChunk returns a mutable buffer, type ubyte[]. If you said "foreach(ubyte[] buffer; stdin.byChunk(bufferSize)) {...}" you should be able to compile it.I tried this, which I hope is correct: --------------------------- void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach (ubyte[] buffer; stdin.byChunk(bufferSize)) { send(tid, buffer); } } void fileWriter() { // Write loop for (;;) { auto buffer = receiveOnly!(immutable(ubyte)[])(); stdout.write(buffer); } } ------------------------------------------------------------ and got this compiler diagnostic: c:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(571): Error: static assert "Aliases to mutable thread-local data not allowed." page406x.d(12): instantiated from here: send!(ubyte[]) For the second possibility, ...Since you aren't keeping a copy of the buffer, just changing the type should be enough for your program to work. If you needed an immutable copy, if you were going to store it or something, the way you'd do that is to call buffer.idup: foreach(ubyte[] temporaryBuffer; stdin.byChunk(bufferSize) { immutable(ubyte)[] permanentBuffer = temporaryBuffer.idup; // you can now use the permanentBuffer }I tried this --------------------------------------------------- import std.algorithm, std.concurrency, std.stdio; void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach(ubyte[] temporaryBuffer; stdin.byChunk(bufferSize)) { immutable(ubyte)[] permanentBuffer = temporaryBuffer.idup; // you can now use the permanentBuffer send(tid, permanentBuffer); } } void fileWriter() { // Write loop for (;;) { auto buffer = receiveOnly!(immutable(ubyte)[])(); stdout.write(buffer); } } -------------------------------- and the result compiled and executed with no error signals, but the resulting output of the file-copy was not the same as the input, it looked like this: std.concurrency.OwnerTerminated std\concurrency.d(248): Owner terminated ---------------- 0x004068EA 0x004081B5 0x00407AB4 0x00407C6A 0x00407CA0 0x00407D1C 0x00407883 0x004068AB 0x004020E9 0x00414D51 0x00434CB4 0x76E51603 in RtlInitializeExceptionChain 0x76E515D6 in RtlInitializeExceptionChain ---------------- [47, 47, 32, 101, 120, 97, .... .... The numbers 47, 47, 32, etc look like the ASCII indexes of the characters which should be in the output, not the characters themselves! Any further help would be much appreciated. Regards, Roger Stokes
Jun 19 2013
On 06/19/2013 12:14 PM, Roger Stokes wrote:and the result compiled and executed with no error signals, but the resulting output of the file-copy was not the same as the input, it looked like this: std.concurrency.OwnerTerminated std\concurrency.d(248): Owner terminatedFor a clean exit, the owner must tell the worker that there is no more data (see struct Done below). It must then wait for it to exit (see core.thread.thread_joinAll below): import std.stdio; import std.concurrency; import core.thread; struct Done {} void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach (ubyte[] buffer; stdin.byChunk(bufferSize)) { send(tid, buffer.idup); } tid.send(Done()); import core.thread; thread_joinAll(); } void fileWriter() { // Write loop bool done = false; while (!done) { receive( (immutable(ubyte)[] buffer) { stdout.write(buffer); }, (Done _) { done = true; }); } }---------------- [47, 47, 32, 101, 120, 97, .... .... The numbers 47, 47, 32, etc look like the ASCII indexes of the characters which should be in the output, not the characters themselves!You are writing ubyte[]. What you see is the default output for such a slice. If you are sure that the data is UTF-8, then you can cast before outputting: stdout.write(cast(string)buffer); Ali
Jun 19 2013
Many thanks, Ali I put together your suggestions, and it all works correctly ! Thanks again. On Wednesday, 19 June 2013 at 19:50:55 UTC, Ali Çehreli wrote:On 06/19/2013 12:14 PM, Roger Stokes wrote:and the result compiled and executed with no error signals,but theresulting output of the file-copy was not the same as theinput, itlooked like this: std.concurrency.OwnerTerminated std\concurrency.d(248): Ownerterminated For a clean exit, the owner must tell the worker that there is no more data (see struct Done below). It must then wait for it to exit (see core.thread.thread_joinAll below): import std.stdio; import std.concurrency; import core.thread; struct Done {} void main() { enum bufferSize = 1024 * 100; auto tid = spawn(&fileWriter); // Read loop foreach (ubyte[] buffer; stdin.byChunk(bufferSize)) { send(tid, buffer.idup); } tid.send(Done()); import core.thread; thread_joinAll(); } void fileWriter() { // Write loop bool done = false; while (!done) { receive( (immutable(ubyte)[] buffer) { stdout.write(buffer); }, (Done _) { done = true; }); } }---------------- [47, 47, 32, 101, 120, 97, .... .... The numbers 47, 47, 32, etc look like the ASCII indexes ofthe characterswhich should be in the output, not the characters themselves!You are writing ubyte[]. What you see is the default output for such a slice. If you are sure that the data is UTF-8, then you can cast before outputting: stdout.write(cast(string)buffer); Ali
Jun 20 2013
On Wednesday, 19 June 2013 at 19:14:58 UTC, Roger Stokes wrote:and got this compiler diagnostic:Oh, I thought you were writing to a socket. Yeah, to a different thread, D will complain if you don't make a sharable copy. So you do want to idup it...[47, 47, 32, 101, 120, 97, .... .... The numbers 47, 47, 32, etc look like the ASCII indexes of the characters which should be in the output, not the characters themselves!The reason here is this line:stdout.write(buffer);The write function changes the format based on the type of input. Since the input here is a ubyte[], it doesn't realize it is a printable string and prints the numeric values of a byte array instead. Try stdout.write(cast(string) buffer)) and you should get what you expect. Another potential change would be to use stdin.byLine instead of stdin.byChunk. byLine returns char[], one line at a time, but it cuts off the newline character (if I remember correctly) and can complain if the input isn't valid UTF-8, so it wouldn't work right for a generic file copy function.
Jun 19 2013
Adam, many thanks for your helpful reply. On Wednesday, 19 June 2013 at 19:53:08 UTC, Adam D. Ruppe wrote:On Wednesday, 19 June 2013 at 19:14:58 UTC, Roger Stokes wrote:and got this compiler diagnostic:Oh, I thought you were writing to a socket. Yeah, to a different thread, D will complain if you don't make a sharable copy. So you do want to idup it...[47, 47, 32, 101, 120, 97, .... .... The numbers 47, 47, 32, etc look like the ASCII indexes of the characters which should be in the output, not the characters themselves!The reason here is this line:stdout.write(buffer);The write function changes the format based on the type of input. Since the input here is a ubyte[], it doesn't realize it is a printable string and prints the numeric values of a byte array instead. Try stdout.write(cast(string) buffer)) and you should get what you expect. Another potential change would be to use stdin.byLine instead of stdin.byChunk. byLine returns char[], one line at a time, but it cuts off the newline character (if I remember correctly) and can complain if the input isn't valid UTF-8, so it wouldn't work right for a generic file copy function.
Jun 20 2013