Re: Can I get a more in-depth guide about the inline assembler?
On Saturday, 4 June 2016 at 01:44:38 UTC, ZILtoid1991 wrote: Problem solved. Current assembly code: //moving the values to their destinations mov EBX, p[EBP]; movdMM0, src; movdMM1, [EBX]; The actual problem was the poor documentation of MMX instructions as it never really caught on, and the disappearance of assembly programming from the mainstream. The end result was a quick alpha-blending algorithm that barely has any extra performance penalty compared to just copying the pixels. I currently have no plans on translating the whole sprite displaying algorithm to assembly, instead I'll work on the editor for the game engine. So... Why did you need to dereference the pointer for p and move it to EBX, but didn't need to do it for src (no [])? Maybe you should explain your experiences with the MMX instruction set, follies and what you succeeded on? Where does the documentation fail? And are we talking about the Intel manuals and instruction sets or another source?
Re: adamdruppe: Drawing scaled image
On Friday, 3 June 2016 at 20:06:50 UTC, Pie? wrote: Thanks! It is working. A few issues with my images being clipped and not throwing when file doesn't exist... That's weird.. I don't know what's going on there. BTW have you seen my documentation site too? http://dpldocs.info/experimental-docs/arsd.gamehelpers.OpenGlTexture.draw.1.html It has a lot of my modules as well as my fork of the official Phobos docs. But the clipping and throwing shouldn't be a problem. Is the display double buffered or will I need to deal with that myself? That's automatic. Also, when the window is resized it goes white. Any ideas how to fix that? It might help to set a window.windowResized handler window.windowResized = (int width, int height) { window.redrawOpenGlSceneNow(); }; though I thought I did that automatically, I might have messed it up (I don't often resize windows when using opengl mode...) Thanks again! Your code has been the easiest to work with! Normally have all kinds of problems. yea, I try to keep it simple - I like minimal dependencies so things just work without a complicated build process, but sometimes I drop balls. If you ever want to do patches btw, I also try to keep the code fairly simple so hacking on it shouldn't be too hard.
Re: Writing adaptor/wrappers with most scalability and least work
On Saturday, 4 June 2016 at 01:04:08 UTC, Pie? wrote: alias this pImage; It is actually `alias pImage this;` That should do what you want right here. Then you can add your own methods or wrap/disable the image ones one by one.
Re: Can I get a more in-depth guide about the inline assembler?
On Wednesday, 1 June 2016 at 23:23:49 UTC, ZILtoid1991 wrote: Here's the assembly code for my alpha-blending routine: ubyte[4] src = *cast(ubyte[4]*)(palette.ptr + 4 * *c); ubyte[4] *p = cast(ubyte[4]*)(workpad + (offsetX + x)*4 + offsetY); asm{//moving the values to their destinations movdMM0, p; movdMM1, src; movqMM5, alpha; movqMM7, alphaMMXmul_const1; movqMM6, alphaMMXmul_const2; punpcklbw MM2, MM0; punpcklbw MM3, MM1; paddw MM6, MM5; //1 + alpha psubw MM7, MM5; //256 - alpha pmulhuw MM2, MM6; //src * (1 + alpha) pmulhuw MM3, MM7; //dest * (256 - alpha) paddw MM3, MM2; //(src * (1 + alpha)) + (dest * (256 - alpha)) psrlw MM3, 8; //(src * (1 + alpha)) + (dest * (256 - alpha)) / 256 //moving the result to its place; packuswbMM4, MM3; movdp, MM4; emms; } The two constants being referred here: static immutable ushort[4] alphaMMXmul_const1 = [256,256,256,256]; static immutable ushort[4] alphaMMXmul_const2 = [1,1,1,1]; alpha is a ushort[4] containing the alpha value four times. After some debugging, I found out that the p pointer becomes null at the end instead of pointing to a value. I have no experience with using in-line assemblers (although I made a few Hello World programs for MS-Dos with a stand-alone assembler), so I don't know when and how the compiler will interpret the types from D. Problem solved. Current assembly code: asm{ //moving the values to their destinations mov EBX, p[EBP]; movdMM0, src; movdMM1, [EBX]; movqMM5, alpha; movqMM7, alphaMMXmul_const256; movqMM6, alphaMMXmul_const1; pxorMM2, MM2; punpcklbw MM0, MM2; punpcklbw MM1, MM2; paddusw MM6, MM5; //1 + alpha psubusw MM7, MM5; //256 - alpha pmullw MM0, MM6; //src * (1 + alpha) pmullw MM1, MM7; //dest * (256 - alpha) paddusw MM0, MM1; //(src * (1 + alpha)) + (dest * (256 - alpha)) psrlw MM0, 8; //(src * (1 + alpha)) + (dest * (256 - alpha)) / 256 //moving the result to its place; //pxor MM2, MM2; packuswbMM0, MM2; movd[EBX], MM0; emms; } The actual problem was the poor documentation of MMX instructions as it never really caught on, and the disappearance of assembly programming from the mainstream. The end result was a quick alpha-blending algorithm that barely has any extra performance penalty compared to just copying the pixels. I currently have no plans on translating the whole sprite displaying algorithm to assembly, instead I'll work on the editor for the game engine.
Writing adaptor/wrappers with most scalability and least work
I would like to temporarily write some adapters or wrappers for various types that allow the most extensibility with the least amount of work. The goal is to get moving quickly as possible and not try to implement all future needs. The wrappers will slowly turn into full their own types and not be wrappers at all. Obviously this requires declaring an interface and such. I curious if I could somehow easily delegate work to the the types I would like to wrap without designing a full fledged oo type. e.g., class Image { alias this pImage; } So, for all purposes Image acts as pImage(except for constructor calls). Of course now I'm bound to pImage's interface which I might not like/want but it gets me pretty far and I can extend it immediately with things I do not want in Image that are in pImage. Any ideas on a good way to approach this? Is there some D tricks that make life easier?
Re: Overriden method not detected ?
On 06/03/2016 10:06 PM, chmike wrote: If I have a static immutable object, I don't have to declare it as shared because it is implicit. Right ? Right. [...] 1. question --- I had a __gshared Info[N] infos_; that I fill in a static this() method. Should be filling it in a `shared static this`, I think. With just `static this`, the fill code is run once per thread. How should I declare this with shared ? Is it enough to write static shared Info[N] infos; ? Since shared is transitive, will the info objects be implicitly shared ? The variable `infos` and its elements are shared then, yes. When you're interested in the type of some expression, you can use pragma(msg, ...) to print it during compilation. For example: pragma(msg, typeof(infos[0])); /* Should print "shared(Info)". */ 2. question --- As I said above, I instantiate my Info objects in a private static this() method. The objects are emplaced in a static shared void array. Since emplace only accept a void[] as argument I had to cast away the shared as you did in your example. The compiler seams happy. As far as I know, that's often the way to treat shared. Cast it away when you know it's safe. However I didn't synchronized that code because I assume it is executed by the main thread before main starts. There is thus no risk of race conditions. Is this assumption correct ? Use `shared static this` as mentioned. 3. error A weird error is that there is apparently no overload for opEquals. Do I have to define one my self ? Is this so that users can synchronize themselves if needed ? source/app.d(9,13): Error: none of the overloads of 'opEquals' are callable using argument types (shared(Info), shared(Info)), candidates are: /usr/include/dmd/druntime/import/object.d(143,6): object.opEquals(Object lhs, Object rhs) /usr/include/dmd/druntime/import/object.d(168,6): object.opEquals(const(Object) lhs, const(Object) rhs) I guess I have to define my own opEqual. Well, there doesn't seem to be an equality function for shared class objects. I'm not sure what the difficulties are in providing one. In the meantime, you can either do your own equality thing without the `==` operator, or assure thread-safety yourself and cast shared away. 4. error Another error is with writeln(info); where info is now a shared(Info). /usr/include/dmd/phobos/std/format.d(2904,5): Error: static assert "unable to format shared objects" /usr/include/dmd/phobos/std/format.d(3477,16): instantiated from here: formatValue!(LockingTextWriter, shared(Info), char) /usr/include/dmd/phobos/std/format.d(467,54):instantiated from here: formatGeneric!(LockingTextWriter, shared(Info), char) /usr/include/dmd/phobos/std/stdio.d(1316,31):instantiated from here: formattedWrite!(LockingTextWriter, char, shared(Info)) /usr/include/dmd/phobos/std/stdio.d(3114,28):instantiated from here: write!(shared(Info), char) source/app.d(12,12):instantiated from here: writeln!(shared(Info)) How can I solve that error ? writeln isn't thread-safe, I guess. Synchronize and cast shared away, I suppose.
Re: Overriden method not detected ?
On Friday, 3 June 2016 at 15:23:16 UTC, Jonathan M Davis wrote: Thank you for your detailed explanation. If I have a static immutable object, I don't have to declare it as shared because it is implicit. Right ? Changing my __gshared into static shared raises some errors which I don't know how to address. Ali's chapter doesn't address shared classes. May I ask for your help ? 1. question --- I had a __gshared Info[N] infos_; that I fill in a static this() method. How should I declare this with shared ? Is it enough to write static shared Info[N] infos; ? Since shared is transitive, will the info objects be implicitly shared ? 2. question --- As I said above, I instantiate my Info objects in a private static this() method. The objects are emplaced in a static shared void array. Since emplace only accept a void[] as argument I had to cast away the shared as you did in your example. The compiler seams happy. However I didn't synchronized that code because I assume it is executed by the main thread before main starts. There is thus no risk of race conditions. Is this assumption correct ? 3. error A weird error is that there is apparently no overload for opEquals. Do I have to define one my self ? Is this so that users can synchronize themselves if needed ? source/app.d(9,13): Error: none of the overloads of 'opEquals' are callable using argument types (shared(Info), shared(Info)), candidates are: /usr/include/dmd/druntime/import/object.d(143,6): object.opEquals(Object lhs, Object rhs) /usr/include/dmd/druntime/import/object.d(168,6): object.opEquals(const(Object) lhs, const(Object) rhs) I guess I have to define my own opEqual. 4. error Another error is with writeln(info); where info is now a shared(Info). /usr/include/dmd/phobos/std/format.d(2904,5): Error: static assert "unable to format shared objects" /usr/include/dmd/phobos/std/format.d(3477,16): instantiated from here: formatValue!(LockingTextWriter, shared(Info), char) /usr/include/dmd/phobos/std/format.d(467,54):instantiated from here: formatGeneric!(LockingTextWriter, shared(Info), char) /usr/include/dmd/phobos/std/stdio.d(1316,31):instantiated from here: formattedWrite!(LockingTextWriter, char, shared(Info)) /usr/include/dmd/phobos/std/stdio.d(3114,28):instantiated from here: write!(shared(Info), char) source/app.d(12,12):instantiated from here: writeln!(shared(Info)) How can I solve that error ?
Re: adamdruppe: Drawing scaled image
On Friday, 3 June 2016 at 15:47:16 UTC, Adam D. Ruppe wrote: On Thursday, 2 June 2016 at 04:01:03 UTC, Pie? wrote: Thanks, I'll look into it. I have tried OpenGL with simpledisplay but I cannot draw to the window. I assume other drawing methods are required? Yeah, you have to use the OpenGL functions instead of my painter functions. If so, I can use gamehelpers.d to do the drawing of the images? Yeah, the OpenGlTexture class can help with it. You can construct it with a TrueColorImage (readPng gives MemoryImage which you can call .getAsTrueColorImage on to get one) Then the OpenGlTexture has a draw method which you can call from inside the redrawOpenGlScene method. OpenGL coordinates are different than desktop, but the `create2dWindow` method in gamehelpers.d will create one with a matrix that matches out. So the function might look like: SimpleWindow window = create2dWindow("your title", width, height); auto image = new OpenGlTexture(readPng(your_png_file).getAsTrueColorImage)); window.redrawOpenGlScene = { image.draw(x, y); }; window.eventLoop(); Use window.redrawOpenGlSceneNow(); in the event loop to make it redraw. Thanks! It is working. A few issues with my images being clipped and not throwing when file doesn't exist... but transparency and such does exist. Is the display double buffered or will I need to deal with that myself? Also, when the window is resized it goes white. Any ideas how to fix that? Thanks again! Your code has been the easiest to work with! Normally have all kinds of problems.
Re: Problem with insertBack
On Friday, 3 June 2016 at 15:03:45 UTC, ag0aep6g wrote: On 06/03/2016 04:34 PM, John Nixon wrote: import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} }; Aside: No semicolon after struct declarations in D. void main(){ Array!CS cs_array = make!(Array!CS)(); cs_array stores its data somewhere on the heap. CS cs; cs is on the stack. cs.t = "bb".dup; But cs.t's data is on the heap, like cs_array's. cs.t contains a pointer to it. cs_array.insertBack(cs); This copies cs to cs_array's heap. The pointer in cs.t is being copied, but the data that it points to is not being copied. So cs.t and cs_array[0].t contain two distinct but equal pointers now. Since they're equal, they refer to the same data. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array! This is expected since cs.t and cs_array[0].t point to the same location. A change to the data through one of them is visible to the other. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does not Here you're not writing through the pointer in cs.t, but rather you're assigning a whole new one. Since the pointers in cs.t and cs_array[0].t are independent of each other, they now point to different locations, with different data. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;} On Friday, 3 June 2016 at 15:03:45 UTC, ag0aep6g wrote: Thanks very much to you and Steve for the detailed explanation. By the way I did try insertBack(cs.dup) but wasn't sure what I was doing. It seems that I just need to add all the .dup 's when needed to make my program work and find out a procedure to make sure I don't miss any. John Nixon
Re: Implicit conversion without alias this?
On Friday, June 03, 2016 16:12:50 maik klein via Digitalmars-d-learn wrote: > Any ideas? Well, alias this is the only way that D supports any kind of implicit conversions for user-defined types. So, if you want to have an implicit conversion for your type, you're going to have to figure out how to do it with alias this. If you can't, then you can't have an implicit version. - Jonathan M Davis
Re: Easier way to add libraries to visual d?
On Thursday, 26 May 2016 at 17:06:03 UTC, Basile B. wrote: colorize works. You meant "serial-port" ? Does Coedit have the possibility to debug?
Implicit conversion without alias this?
I have my own version of Algebraic struct Ok(T){ T value; } struct Err(E){ E value; } auto ok(T)(auto ref T value){ return Ok!T(value); } auto err(E)(auto ref E err){ return Err!E(err); } alias Result(T, E) = Algebraic!(Ok!T, Err!E); I have a constructor and opAssign which allows me to write Result!(int, string) res = ok(5); But it seems strange that I can not do the same thing to function returns Result!(int, string) test(){ return ok(5); // Error: cannot implicitly convert expression (ok(5)) of type Ok!int to Algebraic!(Ok!int, Err!string) } I can not add implicit conversion with alias this from Ok!T to Result!(T, ???) because "Ok" doesn't know about the error type. That is a bit unergonomic because I always seem to need the full type like auto ok(T, E)(auto ref T value){ return Result!(T, E)(Ok!T(value)); } I basically try to mirror http://rustbyexample.com/std/result.html but I don't think that is possible. Any ideas?
Re: adamdruppe: Drawing scaled image
On Thursday, 2 June 2016 at 04:01:03 UTC, Pie? wrote: Thanks, I'll look into it. I have tried OpenGL with simpledisplay but I cannot draw to the window. I assume other drawing methods are required? Yeah, you have to use the OpenGL functions instead of my painter functions. If so, I can use gamehelpers.d to do the drawing of the images? Yeah, the OpenGlTexture class can help with it. You can construct it with a TrueColorImage (readPng gives MemoryImage which you can call .getAsTrueColorImage on to get one) Then the OpenGlTexture has a draw method which you can call from inside the redrawOpenGlScene method. OpenGL coordinates are different than desktop, but the `create2dWindow` method in gamehelpers.d will create one with a matrix that matches out. So the function might look like: SimpleWindow window = create2dWindow("your title", width, height); auto image = new OpenGlTexture(readPng(your_png_file).getAsTrueColorImage)); window.redrawOpenGlScene = { image.draw(x, y); }; window.eventLoop(); Use window.redrawOpenGlSceneNow(); in the event loop to make it redraw.
Re: What would be the best way to work with huge class hierarchies?
On 6/3/16 11:32 AM, O/N/Src wrote: Hi I'm trying to bring a class hierarchy with a lot of classes in D style. The original classes have sometimes identical names like "button" or "control". With the namespaces I've classes like followings ui.core.Button and subclasses like ui.web.mobile.Button ui.web.desktop.Button ui.desktop.Button and more like this. Which would be the best way to bring them in the D world? Apple-Style like UCButton, UWMButton, UWDButton, UDButton MS-style with the use of namespaces (ui.web.mobile.Button, ui.web.desktop.Button) Java like WebMobileButton, DesktopButton ? Regards, Ozan D supports packages and modules. I would recommend using that to reproduce namespaces. When you are porting a library to D, best to use the same names as given in the original, not invent new ones. -Steve
What would be the best way to work with huge class hierarchies?
Hi I'm trying to bring a class hierarchy with a lot of classes in D style. The original classes have sometimes identical names like "button" or "control". With the namespaces I've classes like followings ui.core.Button ...and subclasses like ui.web.mobile.Button ui.web.desktop.Button ui.desktop.Button and more like this. Which would be the best way to bring them in the D world? Apple-Style like UCButton, UWMButton, UWDButton, UDButton MS-style with the use of namespaces (ui.web.mobile.Button, ui.web.desktop.Button) Java like WebMobileButton, DesktopButton ? Regards, Ozan
Re: Overriden method not detected ?
On Friday, June 03, 2016 13:27:41 chmike via Digitalmars-d-learn wrote: > On Friday, 3 June 2016 at 12:41:39 UTC, Jonathan M Davis wrote: > ... > > > On a side note, be warned that you almost certainly shouldn't > > be using __gshared like this. It's intended for interacting > > with C code not for D objects to be marked with D. As far as > > the type system is concerned, __gshared isn't part of the type, > > and the variable will be treated as thread-local by all of the > > code that uses it, which can result in really nasty, subtle > > bugs when the compiler starts doing stuff like optimizations. > > If you want to be sharing D objects across threads, you really > > should be using shared so that the compiler knows that it's > > shared across threads and will treat it that way. > > Thanks to point this out. What does shared really do behind the > scene ? > Does it add synchronization instructions ? shared does not add any synchronization instructions. It makes it so that the object is on the shared heap instead of the thread-local heap; it makes it so that that the compiler treats it as shared across threads (whereas if it's not shared, the compiler assumes that it's on the thread-local heap and that no other thread has access to it); and it makes it so that certain things are illegal without using core.atomic (e.g. directly incrementing a shared int isn't legal, because it's not thread-safe). If a variable is not shared, then the compiler is free to assume that it's thread local and make optimizations based on that fact. So, if you have a shared object, you have to either make it use core.atomic to do anything like incrementing values, or you have to cast away shared to operate on the object (in which case, you need to have protected all access to the object with a mutex or synchronized block just like you'd do with C++). So, you end up with code like shared MyObj myObj = getObjFromSomewhere(); synchronized(lockObj) { // myObj is now protected by a lock; all other accesses to it // should be as well, or this isn't thread-safe. auto threadLocal = cast(MyObj)myObj; // do stuff with the thread-local reference // don't let any thread-local references to myObj escape } // the lock has been released, and the only references to myObj are // shared. It's basically the same thing that you'd do in languages like C++ or Java except that you're forced to cast away shared, whereas in those languages, everything is shared, and you can potentially have thread-related problems pretty much anywhere in your code. You can have also all of the functions on your struct/class be shared and call them without locking, but you risk all of the normal race conditions if you're not either protecting it via locks or using the atomic operations from core.atomic, otherwise a number of operations on built-in types will be considered illegal and result in compilation errors, since if operations aren't atomic, they need to be done with the object being properly locked, or they're not thread-safe. In theory, we're supposed to get synchronized classes, which protect their member variables via a lock for the whole class such that the outer layer of shared can be stripped away within its member functions, but it's never been fully implemented. Rather, right now, the closest we have is synchronized functions, which is basically the same as using synchronized blocks, so it doesn't have any of the properties that would allow the compiler to strip away the outer layer of shared (since it can't guaranteed that there are no other, unprotected references to the same data). So, if we had synchronized classes, you could potentially avoid the ugliness of casting away shared, but we don't have them yet. The concurrency chapter from Andrei's book, "The D Programming Language" is available for free online: http://www.informit.com/articles/article.aspx?p=1609144 So, you can read that for more details, but it does talk like synchronized classes are implemented, and we don't have synchronized functions (since that was the plan when it was written but hasn't happened yet). Another resource to look at would be Ali's book: http://ddili.org/ders/d.en/concurrency_shared.html shared does feel a bit clunky (particularly when you need to cast it away), but it does allow you to segregate the code that involves threads, and it helps protect you against race conditions, whereas if you use __gshared, you're risking serious problems. > In my case I really don't want the compiler to add > synchronization instructions because the objects are immutable > from the user perspective. This is enforced by the interface. Tho > objects are fully instantiated in a private static this() {} > function which shouldn't be affected by multi-threading since it > is executed at startup. If the object is really immutable, then just make it immutable. immutable is implicitly shared across threads, but it doesn't have any of the locking issues, because
Re: Problem with insertBack
On 06/03/2016 04:34 PM, John Nixon wrote: import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} }; Aside: No semicolon after struct declarations in D. void main(){ Array!CS cs_array = make!(Array!CS)(); cs_array stores its data somewhere on the heap. CS cs; cs is on the stack. cs.t = "bb".dup; But cs.t's data is on the heap, like cs_array's. cs.t contains a pointer to it. cs_array.insertBack(cs); This copies cs to cs_array's heap. The pointer in cs.t is being copied, but the data that it points to is not being copied. So cs.t and cs_array[0].t contain two distinct but equal pointers now. Since they're equal, they refer to the same data. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array! This is expected since cs.t and cs_array[0].t point to the same location. A change to the data through one of them is visible to the other. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does not Here you're not writing through the pointer in cs.t, but rather you're assigning a whole new one. Since the pointers in cs.t and cs_array[0].t are independent of each other, they now point to different locations, with different data. write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;}
Re: Problem with insertBack
On 6/3/16 10:34 AM, John Nixon wrote: I recently came across another problem with my program in D, found a minimal program showing it, and experimented a little with it as follows: import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} }; void main(){ Array!CS cs_array = make!(Array!CS)(); CS cs; cs.t = "bb".dup; cs_array.insertBack(cs); write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array! You have inside your CS struct a pointer to a heap array. Then you change the heap array later. The CS element you put into the cs_array still points at the same piece of memory. Perhaps you meant to insert cs.dup? write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does not Right, because the cs stored on the stack is now pointing at a different heap-allocated array write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;} The first assignment to cs.t[0] changes cs_array as indicated, but the second to cs.t does not. Also if these two assignments are reversed, neither affects cs_array. What could be the explanation of this? Right, because if the stack is pointing at a different array than the cs_array[0], then altering won't affect cs_array[0]. -Steve
Problem with insertBack
I recently came across another problem with my program in D, found a minimal program showing it, and experimented a little with it as follows: import std.stdio; import std.container; struct CS{ char[] t; CS dup()const{ CS cs; cs.t = this.t.dup; return cs;} }; void main(){ Array!CS cs_array = make!(Array!CS)(); CS cs; cs.t = "bb".dup; cs_array.insertBack(cs); write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t[0] = ("a".dup)[0];//this changes cs_array! write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); cs.t = "c".dup;//but this does not write("cs_array = ");foreach(i2;cs_array)write(i2);writeln(""); return;} The first assignment to cs.t[0] changes cs_array as indicated, but the second to cs.t does not. Also if these two assignments are reversed, neither affects cs_array. What could be the explanation of this? Kind regards John Nixon
Re: Overriden method not detected ?
On Friday, 3 June 2016 at 12:41:39 UTC, Jonathan M Davis wrote: ... On a side note, be warned that you almost certainly shouldn't be using __gshared like this. It's intended for interacting with C code not for D objects to be marked with D. As far as the type system is concerned, __gshared isn't part of the type, and the variable will be treated as thread-local by all of the code that uses it, which can result in really nasty, subtle bugs when the compiler starts doing stuff like optimizations. If you want to be sharing D objects across threads, you really should be using shared so that the compiler knows that it's shared across threads and will treat it that way. Thanks to point this out. What does shared really do behind the scene ? Does it add synchronization instructions ? In my case I really don't want the compiler to add synchronization instructions because the objects are immutable from the user perspective. This is enforced by the interface. Tho objects are fully instantiated in a private static this() {} function which shouldn't be affected by multi-threading since it is executed at startup. The unpleasant side effect of shared is that I then have to use shared(Info) instead of the shorter type name Info. What are the subtle and nasty bugs you are referring to ?
Re: Overriden method not detected ?
On Friday, June 03, 2016 12:03:29 chmike via Digitalmars-d-learn wrote: > When trying to compile the following code I get a compilation > error > > > import std.stdio; > > class Info > { > final string name() { return nameImpl(); } > protected abstract string nameImpl(); > } > > final class MyInfo : Info > { > this() { assert(__ctfe); } > private __gshared info_ = new MyInfo; // Line 12 > > static string name() { return "MyInfo"; } > protected override string nameImpl() { return name(); } > } > > void main() > { > writeln("Hello world!"); > } > > source/app.d(12,31): Error: cannot create instance of abstract > class MyInfo > source/app.d(12,31):function 'string nameImpl()' is not > implemented > > If I move the info_ static variable declaration after the > nameImpl method declaration, there is no error anymore. > > Is this normal ? What rule is in play here ? Or is this a > compiler bug ? It definitely looks like a compiler bug, though it wouldn't have surprised me if the compiler considered it illegal to declare a static function in a derived class where the base class has a final function with the same name. Still, regardless of the legality of reusing the name like that, the error message is pretty clearly wrong, and the order of declarations shouldn't matter within a class unless you're doing something with static if. On a side note, be warned that you almost certainly shouldn't be using __gshared like this. It's intended for interacting with C code not for D objects to be marked with D. As far as the type system is concerned, __gshared isn't part of the type, and the variable will be treated as thread-local by all of the code that uses it, which can result in really nasty, subtle bugs when the compiler starts doing stuff like optimizations. If you want to be sharing D objects across threads, you really should be using shared so that the compiler knows that it's shared across threads and will treat it that way. - Jonathan M Davis
Re: Overriden method not detected ?
On 6/3/16 8:03 AM, chmike wrote: import std.stdio; class Info { final string name() { return nameImpl(); } protected abstract string nameImpl(); } final class MyInfo : Info { this() { assert(__ctfe); } private __gshared info_ = new MyInfo; // Line 12 static string name() { return "MyInfo"; } protected override string nameImpl() { return name(); } } void main() { writeln("Hello world!"); } Yes, this is a forward reference bug. Move the info_ member to the end of the class and it compiles. Please file https://issues.dlang.org -Steve
Overriden method not detected ?
When trying to compile the following code I get a compilation error import std.stdio; class Info { final string name() { return nameImpl(); } protected abstract string nameImpl(); } final class MyInfo : Info { this() { assert(__ctfe); } private __gshared info_ = new MyInfo; // Line 12 static string name() { return "MyInfo"; } protected override string nameImpl() { return name(); } } void main() { writeln("Hello world!"); } source/app.d(12,31): Error: cannot create instance of abstract class MyInfo source/app.d(12,31):function 'string nameImpl()' is not implemented If I move the info_ static variable declaration after the nameImpl method declaration, there is no error anymore. Is this normal ? What rule is in play here ? Or is this a compiler bug ?
Re: improve concurrent queue
On Tuesday, 27 August 2013 at 17:35:13 UTC, qznc wrote: I can recommand this paper (paywalled though): http://dl.acm.org/citation.cfm?id=248106 The research paper can actually be freely downloaded from http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA309412 . Good article, thanks!