Re: vibe.d + dub dynamic library
On 2015-01-02 19:44, Benjamin Thaut wrote: Is it possible to get dub to build vibe.d into a dynamic library? Or is it at least possible to make dub link against the shared version of phobos? I found this blog post about dynamic linktimes, unfortunately it does not describe how to actually make dub use the dynamic version of phobos. I'm not sure how Dub builds vibe.d but if a shared library is present isn't that usually preferred to static libraries? -- /Jacob Carlborg
Re: Example usage of the core.sync classes
On Friday, 2 January 2015 at 18:52:11 UTC, Benjamin Thaut wrote: Am 02.01.2015 um 19:45 schrieb Vlad Levenfeld: My personal favorite method is to use the primitives in core.atomic with a double or triple buffer. To double buffer, keep two buffers in an array (data[][] or something) and an integer index that points to the active buffer, then use atomicStore to update active buffer index when you want to swap. Triple buffering can improve runtime performance at the cost of more memory, and in this case you will need two indices and two swap methods, one for the producer and another for the consumer. I use cas with a timed sleep to update the indices in this case. Take it with a grain of salt, I'm far from a pro, but this has worked well for me in the past. I can post some example code if you need it. I have to agree with Vlad here. The usual way is to do double buffering. So you have two buffers which hold all the data that the physics simulation passes to the game logic. While the physics simulation is computing the next frame, the game logic can use the results from the last frame. The only point where sinchronisation is neccessary is when swapping the buffers. You have to ensure that both the game logic and the physics thread are done with their current buffer and then sawp them. The only downside of this approach is, that you will get a small delay (usually the time taken for 1 frame) into the data you pass this way. Sometimes this approach is called the exractor pattern. I use it to pass data from the game simulation to the renderer, so the renderer can render in paralell with the game simulation computing the next frame. You can find a example of my double buffered solution here: https://github.com/Ingrater/Spacecraft/blob/master/game/sources/renderer/extractor.d I had tripple buffering up and running at some point, but I went back to double buffering, because tripple buffering can cause micro lags and you don't want that. Kind Regards Benjamin Thaut Right, I've been looking at core.atomic, but it has very little documentation, and it's territory I haven't explored, yet. Any chance of some pointers along the way?
Re: getting all children classes in program
On Saturday, 3 January 2015 at 15:00:53 UTC, Ondra wrote: I'm not sure if there's a way around that other than to add some code in the class to register itself. You could use a static constructor that adds itself to a list. Or, to give each class a shared ID, you could add a static member which returns some variation of its typeinfo. In fact, typeid(any_class) returns a unique identifier for each class (an instance of TypeInfo), maybe you can use it directly. Hi Adam, static this is probably way to go, I wanted to avoid this solution because if it leads to copy-pasting code to every child. I need to have IDs small like 8bits, co I probably can't use typeid... Thank you for answer. Knowing that someting cannot be done is better than spend on this another few hour. Great book btw. Ondra Hello, here is another solution: a class ID is generated lazily, when queried It does not recquire a static constructor. module runnable; static string[] IDs; ptrdiff_t getClassID(ClassType)() if (is(ClassType == class)) { import std.algorithm; auto classTypeString = ClassType.stringof; ptrdiff_t result = countUntil(IDs, classTypeString); if (result == -1) { IDs ~= classTypeString; result = IDs.length -1; } return result; } void main(string[] args) { class A{} class B{} class C{} class D{} assert(getClassID!A == 0); assert(getClassID!B == 1); assert(getClassID!C == 2); assert(getClassID!D == 3); assert(getClassID!C == 2); assert(getClassID!B == 1); assert(getClassID!A == 0); } Hoping it matches to your needs.
Re: Weird UFC and opCall issues
Ooops. Test() wasn't valid. Still working to create a range object that iterates over an internal data struct. But this was may error. On Saturday, 3 January 2015 at 20:26:41 UTC, Darrell wrote: Fails with: t.d(34): Error: need 'this' for 'opCall' of type 'int()' Also opCall seems to be required to create a range. class Test { int opCall() { return 1; } @property int front() { return 2; } void popFront() { } @property bool empty() { return false; } }; void main(){ ubyte [] p1; Test(); }
Re: getting all children classes in program
Off Topic ! But in the same way: --- static string[] IDs; ptrdiff_t getClassID(ClassType, ClassBase)() if ((is(ClassType == class)) (is(ClassBase == class))) { import std.algorithm; if (!is(ClassType : ClassBase)) return -1; else { auto classTypeString = ClassType.stringof; ptrdiff_t result = countUntil(IDs, classTypeString); if (result == -1) { IDs ~= classTypeString; result = IDs.length -1; } return result; } } void main(string[] args) { class Oops {} class A : Oops{} class B : Oops{} class C : Oops{} class D : Oops{} class E {} assert(getClassID!(A,Oops) == 0); assert(getClassID!(B,Oops) == 1); assert(getClassID!(C,Oops) == 2); assert(getClassID!(D,Oops) == 3); assert(getClassID!(C,Oops) == 2); assert(getClassID!(B,Oops) == 1); assert(getClassID!(A,Oops) == 0); assert(getClassID!(E,Oops) == -1); } ---
Re: simple question about using dub to import CyberShadow's aeutils
On Saturday, 3 January 2015 at 12:08:16 UTC, Vladimir Panteleev wrote: On Saturday, 3 January 2015 at 11:58:48 UTC, Laeeth Isharc wrote: import ae.utils; ae.utils is a package, perhaps you meant to import ae.utils.xml? aha. schoolboy error on my part. thank you for your help, and especially for writing such a useful library and sharing it with the world. Laeeth.
Re: What exactly shared means?
On Saturday, 3 January 2015 at 13:53:09 UTC, John Colvin wrote: I think you're talking cross-purposes. thread-local as in TLS v.s. thread-local as in not-shared. I am not talking TLS. TLS is related to object files, not types. You don't have shared vs non-shared. You have many different relevant situations: - no other reader or writer - no other writer - not shared now, but later - unknown - always shared ++
Re: Weird UFC and opCall issues
Seems when creating your own ranges they can't be a class. Must be a struct or Segmentation fault (core dumped) will follow. This works as long as Test is a struct. struct Test { @property int front() { return 2; } void popFront() { } enum bool empty = false; }; static assert(isInputRange!Test); void mainx(){ Test x; writeln(x.take(1)); }
Re: Weird UFC and opCall issues
Fails with: t.d(34): Error: need 'this' for 'opCall' of type 'int()' Also opCall seems to be required to create a range. class Test { int opCall() { return 1; } @property int front() { return 2; } void popFront() { } @property bool empty() { return false; } }; void main(){ ubyte [] p1; Test(); }
Re: getting all children classes in program
Hi Baz jklp, thank you for ideas I will use your approach for this problem.
Re: What exactly shared means?
On Saturday, January 03, 2015 12:14:54 via Digitalmars-d-learn wrote: On Saturday, 3 January 2015 at 00:12:35 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: In D, if a type is not marked as shared, then it is by definition thread-local, and the compiler is free to assume that it's thread-local. I find this to be rather vague. If the compiler exploit this to the maximum wouldn't that lead to lots of bugs? Only if you're declaring shared or __gshared variables and not protecting them properly or interacting with C or C++ code in a way that doesn't take their memory model into account. The vast majority of D code won't care one whit and won't have any problems, because very little of it needs to be shared, and thread communication most typically is done via message passing using std.concurrency, not by declaring shared variables. So, the risk of bugs related to the compiler taking advantage of its knowledge that a variable is thread-local if not mark as shared is pretty low in most cases. Yes, there's definitely a risk of bugs if you're casting away shared or use __gshared and screw it up (which is part of why we'd much rather have a way for the language to safely strip away shared when it can guarantee that a shared variable is properly protected), but for the most part, it's not a problem at all and is _far_ less of a problem than what you get in languages like C or C++ which default to shared rather than thread-local. - Jonathan M Davis
Re: What exactly shared means?
On Saturday, 3 January 2015 at 12:12:47 UTC, Ola Fosheim Grøstad wrote: On Saturday, 3 January 2015 at 10:13:52 UTC, John Colvin wrote: The Java, C11 and C++11 memory model. Well... http://en.cppreference.com/w/cpp/atomic/memory_order Ok, with the exception of relaxed atomics. Yes, I was hoping that perhaps you knew more specifics. AFAIK, when not restricted by any kind of barriers, SC-DRF does not have a particularly significant cost. I think that even with lock free datastructures such as Intel Threaded Building Blocks, you would still gain from using a non-synchronizing API where possible. In real code you have several layers for functioncalls, so doing this by hand will complicate the code. That isn't what I mean. I was talking about the restrictions that the memory model puts on optimising _all_ code, except where memory is provably unshared. Things like never creating a write where one would not have occurred in a sequentially consistent execution of the original source.
Re: What exactly shared means?
On Saturday, 3 January 2015 at 13:33:21 UTC, Ola Fosheim Grøstad wrote: On Saturday, 3 January 2015 at 12:17:52 UTC, ketmar via Digitalmars-d-learn wrote: why should it? thread locals are... well, local for each thread. you can't access local of different thread without resorting to low-level assembly and OS dependent tricks. Of course you can, anything that is reachable through any chain of pointers/references is effectively shared, not only the object you explicitly share. So when you cast away shared then call a function and that is safe in itself, you don't know what happens when someone modifies some function deep down in the call chain later on and access some private pointer chain and possibly retain a pointer to it. The alternative is to put shared on all parameters in libraries or avoid using libraries... I think you're talking cross-purposes. thread-local as in TLS v.s. thread-local as in not-shared.
Re: getting all children classes in program
On Saturday, 3 January 2015 at 14:28:07 UTC, Ondra wrote: class C(T): B {} // missing in ModuleInfo The reason is that's technically not a class and doesn't exist at runtime, it is just a template for one (you can't new that, you'd have to new C!some_actual_type). If you were to add a class D : C!int {} then you'd see class D shows up and has a parent of C!int... however, you're right, C!int doesn't want to show up at all, even if I instantiate it. I'm not sure if there's a way around that other than to add some code in the class to register itself. You could use a static constructor that adds itself to a list. Or, to give each class a shared ID, you could add a static member which returns some variation of its typeinfo. In fact, typeid(any_class) returns a unique identifier for each class (an instance of TypeInfo), maybe you can use it directly.
Re: What exactly shared means?
On Saturday, 3 January 2015 at 12:34:10 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: their memory model into account. The vast majority of D code won't care one whit and won't have any problems, because very little of it needs to be shared, and thread communication most typically is done via message passing using std.concurrency, not by declaring shared variables. I don't agree with this. If you avoid the problem by message passing, then you should do like Go and make it a language feature. And accept that you loose out on efficiency and restrict the application domain. If you make shared a language feature you also need to back it up with semantic analysis and prove that the concept is sound and useful (i.e. no need to break encapsulation, not making most libraries unusable without unsafe casting etc).
Re: getting all children classes in program
I'm not sure if there's a way around that other than to add some code in the class to register itself. You could use a static constructor that adds itself to a list. Or, to give each class a shared ID, you could add a static member which returns some variation of its typeinfo. In fact, typeid(any_class) returns a unique identifier for each class (an instance of TypeInfo), maybe you can use it directly. Hi Adam, static this is probably way to go, I wanted to avoid this solution because if it leads to copy-pasting code to every child. I need to have IDs small like 8bits, co I probably can't use typeid... Thank you for answer. Knowing that someting cannot be done is better than spend on this another few hour. Great book btw. Ondra
Re: What exactly shared means?
On Saturday, 3 January 2015 at 12:17:52 UTC, ketmar via Digitalmars-d-learn wrote: why should it? thread locals are... well, local for each thread. you can't access local of different thread without resorting to low-level assembly and OS dependent tricks. Of course you can, anything that is reachable through any chain of pointers/references is effectively shared, not only the object you explicitly share. So when you cast away shared then call a function and that is safe in itself, you don't know what happens when someone modifies some function deep down in the call chain later on and access some private pointer chain and possibly retain a pointer to it. The alternative is to put shared on all parameters in libraries or avoid using libraries...
Re: What exactly shared means?
On Sat, 03 Jan 2015 12:14:54 + via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Saturday, 3 January 2015 at 00:12:35 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: In D, if a type is not marked as shared, then it is by definition thread-local, and the compiler is free to assume that it's thread-local. I find this to be rather vague. If the compiler exploit this to the maximum wouldn't that lead to lots of bugs? why should it? thread locals are... well, local for each thread. you can't access local of different thread without resorting to low-level assembly and OS dependent tricks. signature.asc Description: PGP signature
getting all children classes in program
Hi, how can I get list of all children classes of class in program? I was trying to use ModuleInfo from D Coockbook but this does not work for template classes? ex.: class A{} class B:A{} // ok in ModuleInfo class C(T): B {} // missing in ModuleInfo I am trying to assign every class its unique ID that is same for all instances. Code: int result[string]; int counter = 0; foreach(mod; ModuleInfo) { foreach(cla; mod.localClasses) { auto base = cla.base; while (base) { if (base is T.classinfo) { result[cla.name] = counter; counter++; } base = base.base; } } }
simple question about using dub to import CyberShadow's aeutils
Hi. I would like to use the XML parser from CyberShadow's ae.utils - I am building a tool to index RSS feeds in elasticsearch (something like rssriver but with more complete functionality). I am using dub to build the code. So far I just have an empty boilerplate app.d with the line import ae.utils; Using the suggestion from code.dlang.org: { ... dependencies: { ae: =1.0.1 } } It cannot find ae/utils.d If I try replacing the = with or just ~master it still does not build. Error text below this message. I suppose this might be because dub is designed to import a single package, and not just part of the hierarchy. But if I change the import to just plain import ae, I still have problems. What am I doing wrong? I could just copy the file over, but I would like to try to do it properly. Do let me know if you do not see this as the right forum to ask about dub. Thanks. Laeeth. Selected package openssl 1.0.0+1.0.0e does not match the dependency specification in package ae (=1.1.3+1.0.1g (optional)). Need to dub upgrade? Target vibe-d 0.7.21 is up to date. Use --force to rebuild. Building rsselastic ~master configuration application, build type debug. Compiling using dmd... source/app.d(1): Error: module utils is in file 'ae/utils.d' which cannot be read import path[0] = source/ import path[1] = ../../../root/.dub/packages/ae-1.0.1 import path[2] = ../../../root/.dub/packages/openssl-1.0.0_1.0.0e import path[3] = ../../../root/.dub/packages/vibe-d-0.7.21/source/ import path[4] = ../../../root/.dub/packages/libevent-2.0.1_2.0.16 import path[5] = /usr/include/dmd/phobos import path[6] = /usr/include/dmd/druntime/import FAIL .dub/build/application-debug-linux.posix-x86_64-dmd_2067-6DD7C73322D93ABC7BBACEAF4B4E0E3D/ rsselastic executable Error executing command run: dmd failed with exit code 1. === Selected package openssl 1.0.0+1.0.0e does not match the dependency specification in package ae (=1.1.3+1.0.1g (optional)). Need to dub upgrade? Target vibe-d 0.7.21 is up to date. Use --force to rebuild. Building rsselastic ~master configuration application, build type debug. Compiling using dmd... source/app.d(1): Error: module ae is in file 'ae.d' which cannot be read import path[0] = source/ import path[1] = ../../../root/.dub/packages/ae-1.0.1 import path[2] = ../../../root/.dub/packages/openssl-1.0.0_1.0.0e import path[3] = ../../../root/.dub/packages/vibe-d-0.7.21/source/ import path[4] = ../../../root/.dub/packages/libevent-2.0.1_2.0.16 import path[5] = /usr/include/dmd/phobos import path[6] = /usr/include/dmd/druntime/import FAIL .dub/build/application-debug-linux.posix-x86_64-dmd_2067-6DD7C73322D93ABC7BBACEAF4B4E0E3D/ rsselastic executable Error executing command run: dmd failed with exit code 1.
Re: What exactly shared means?
On Saturday, 3 January 2015 at 00:12:35 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: In D, if a type is not marked as shared, then it is by definition thread-local, and the compiler is free to assume that it's thread-local. I find this to be rather vague. If the compiler exploit this to the maximum wouldn't that lead to lots of bugs?
Re: What exactly shared means?
On Saturday, 3 January 2015 at 10:13:52 UTC, John Colvin wrote: The Java, C11 and C++11 memory model. Well... http://en.cppreference.com/w/cpp/atomic/memory_order Yes, I was hoping that perhaps you knew more specifics. AFAIK, when not restricted by any kind of barriers, SC-DRF does not have a particularly significant cost. I think that even with lock free datastructures such as Intel Threaded Building Blocks, you would still gain from using a non-synchronizing API where possible. In real code you have several layers for functioncalls, so doing this by hand will complicate the code. If you can propagate knowledge down the call chain about locality and the semantics of object interfaces or clusters of objects, then you can relax restrictions on the optimizer and get better performance on real-world code. This would be a natural direction for D, since it is already encouraging templated code. The alternative is to hand code this where it matters, but that is inconvenient...
Re: What exactly shared means?
On Saturday, 3 January 2015 at 00:48:23 UTC, Peter Alexander wrote: On Friday, 2 January 2015 at 23:51:05 UTC, John Colvin wrote: The rule (in C(++) at least) is that all data is assumed to be visible and mutable from multiple other threads unless proved otherwise. However, given that you do not write a race, the compiler will provide full sequential consistency. If you do write a race though, all bets are off. The memory is visible and mutable, but that's pretty much the only guarantee you get. Without synchronization, there's no guarantee a write made by thread A will ever be seen by thread B, and vice versa. Analogously in D, if a thread modifies a __gshared variable, there's no guarantees another thread will ever see that modification. The variable isn't thread local, but it's almost as if the compiler to treat it that way. These relaxed guarantees allow the compiler to keep variables in registers, and re-order memory writes. These optimizations are crucial to performance. That is exactly how I understood the situation to be, yes. 2 questions I have to absolutely nail this down for good: Does D assume that local variables are truly thread-local? I.e. can the compiler perform optimisations on local references that would break SC-DRF without first proving that it does not? Another way of putting it is: can a D compiler perform optimisations that are normally illegal in modern C(++) and Java? If the answer to the above is yes, does the same apply to explicit use of __gshared variables?
Re: cannot modify struct with immutable members
Ali Çehreli wrote: On 01/02/2015 10:10 PM, ted wrote: I'm now taking the view that const is there for the compiler to optimise code on the basis that nothing can alter it once set (and can only be set on initialisation). Of course, that is true for const values, not for const references. In the latter case it means I will not modify but others may modify, so the optimization that you mention does not apply to const in general. However, immutable can be used for optimization. Ali thats (sort of) where I had started from. My (clearly incorrect) interpretation was that reinitialising 'myTest1' was part of the 'others may modify' category because of the fact that it was in scope of the _someFunc function ...anywaylots to learn. BTW: your book is excellent, and as soon as you have it available for purchase I will certainly be buying a copy.
Re: What exactly shared means?
On Friday, 2 January 2015 at 23:56:44 UTC, Ola Fosheim Grøstad wrote: On Friday, 2 January 2015 at 23:10:46 UTC, John Colvin wrote: What significant optimisations does SC-DRF actually prevent? By SC-DRF I assume you mean the Java memory model. The Java, C11 and C++11 memory model. AFAIK SCDRF just means that if you syncronize correctly (manually) then you will get sequential consistency (restriction on the compiler). That sounds like a correct description of it to me, yes. Getting rid of the restrictions on the compiler and eliding programmer-provided syncronization allows for more optimizations on loads, writes, reordering, syncronization/refcounting...? Yes, I was hoping that perhaps you knew more specifics. AFAIK, when not restricted by any kind of barriers, SC-DRF does not have a particularly significant cost.
Re: cannot modify struct with immutable members
On Sat, 03 Jan 2015 01:00:58 -0800 Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On 01/02/2015 09:07 PM, ketmar via Digitalmars-d-learn wrote: structure instance with const fields can be initialized only once, upon creation. so did `Test myTest1;` -- you initialized `myTest1` with default values. you can't reinitialize it later. in C++ constness on member doesn't impose such restrictions. C++ has the same restriction: const members make objects unassignable: ah, thanks. it's a joy to forgetting C++ to this extent. ;-) signature.asc Description: PGP signature
Re: cannot modify struct with immutable members
On 01/02/2015 09:07 PM, ketmar via Digitalmars-d-learn wrote: structure instance with const fields can be initialized only once, upon creation. so did `Test myTest1;` -- you initialized `myTest1` with default values. you can't reinitialize it later. in C++ constness on member doesn't impose such restrictions. C++ has the same restriction: const members make objects unassignable: struct S { const int i; S() : i() {} }; int main() { S a; S b; a = b; } error: non-static const member ‘const int S::i’, can't use default assignment operator Ali
Re: cannot modify struct with immutable members
On 01/02/2015 10:10 PM, ted wrote: I'm now taking the view that const is there for the compiler to optimise code on the basis that nothing can alter it once set (and can only be set on initialisation). Of course, that is true for const values, not for const references. In the latter case it means I will not modify but others may modify, so the optimization that you mention does not apply to const in general. However, immutable can be used for optimization. Ali
Re: simple question about using dub to import CyberShadow's aeutils
On Saturday, 3 January 2015 at 11:58:48 UTC, Laeeth Isharc wrote: import ae.utils; ae.utils is a package, perhaps you meant to import ae.utils.xml?
Re: Example usage of the core.sync classes
On Saturday, 3 January 2015 at 15:44:16 UTC, Matt wrote: Right, I've been looking at core.atomic, but it has very little documentation, and it's territory I haven't explored, yet. Any chance of some pointers along the way? Could you be more specific about what you need help understanding? You can implement a very simple double buffer like so: synchronized final class DoubleBuffer (T) { T[][2] data; uint write_index; shared void swap () { atomicStore (write_index, (write_index + 1) % 2); (cast()this).buffer[write_index].clear; } shared @property write_buffer () { return (cast()this).buffer[write_index][]; } shared @property read_buffer () { return (cast()this).buffer[(write_index + 1) % 2][]; } } Just append to write_buffer, call swap, then read from read_buffer. Make sure you declare the instance shared. Benjamin's post links to a more robust and realistic implementation.
Re: Weird UFC and opCall issues
Darrell wrote: Seems when creating your own ranges they can't be a class. Must be a struct or Segmentation fault (core dumped) will follow. This works as long as Test is a struct. struct Test { @property int front() { return 2; } void popFront() { } enum bool empty = false; }; static assert(isInputRange!Test); void mainx(){ Test x; writeln(x.take(1)); } With classes, you need to create an instance, so (adjusting some of your previous code) this works: import std.range; import std.stdio; class Test { @property int front() { return 2; } void popFront() { } @property bool empty() { return false; } }; static assert(isInputRange!Test); void main(){ ubyte [] p1; Test myTest = new Test(); writeln(myTest.take(1)); }
Re: Weird UFC and opCall issues
On 01/03/2015 12:26 PM, Darrell wrote: Fails with: t.d(34): Error: need 'this' for 'opCall' of type 'int()' Also opCall seems to be required to create a range. D has a feature that does not exists e.g. in C++: You can call the type itself as a function. The 'Test()' syntax is a call to that type's static opCall(). class Test { int opCall() { return 1; } Not being static, that would require an instance of the Test class. @property int front() { return 2; } You may want to define that member function 'const' as well. void popFront() { } @property bool empty() { return false; } That can be 'const' as well. }; D does not require that semicolon. void main(){ ubyte [] p1; Test(); } I am removing the opCall and assuming that you actually want a ubyte I am returning a ubyte from front(). Also note the almost-mandatory-with-ranges convenience function 'test()' below, which hides the invocation of 'new': class Test { @property ubyte front() { return 2; } void popFront() { } @property bool empty() { return false; } } Test test() { return new Test(); } /* Alternatively, you can move test() inside Test as a static opCall: static Test opCall() { return new Test(); } Then, the syntax in main could be ubyte [] p1 = Test().take(3).array; */ import std.stdio; import std.range; void main(){ ubyte [] p1 = test().take(3).array; assert(p1 == [ 2, 2, 2 ]); } Ali
Re: What exactly shared means?
On Saturday, January 03, 2015 13:39:51 via Digitalmars-d-learn wrote: On Saturday, 3 January 2015 at 12:34:10 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: their memory model into account. The vast majority of D code won't care one whit and won't have any problems, because very little of it needs to be shared, and thread communication most typically is done via message passing using std.concurrency, not by declaring shared variables. I don't agree with this. If you avoid the problem by message passing, then you should do like Go and make it a language feature. And accept that you loose out on efficiency and restrict the application domain. If you make shared a language feature you also need to back it up with semantic analysis and prove that the concept is sound and useful (i.e. no need to break encapsulation, not making most libraries unusable without unsafe casting etc). It is far better in general to use message passing to separate threads, but by no means is it intended that it be the only way to do things in D. It is a systems language after all. We have synchronized blocks and mutexes. We have stuff like std.parallelism. We have fibers. There are quite a few ways to go about having threads communicate and share data. It's just that message passing is by far the cleanest and safest in most cases, so it's what most code should be doing. If that's not what fits a particular program, then there are plenty of other options available. However, that does tend to mean having to deal with shared more. And shared is definitely of benefit regardless of whether you're forced to carefully cast it away some of the time to use it, just like C++'s const is useful even if it's not actually full-on physical const like D's const is. But we pretty much all agree that we want better guarantees than that. Ideally, you would never cast away shared, and it would be cast away for you by the compiler in sections of code where it can guarantee that it's safe to do so (that was part of the idea behind synchronized classes). But that's incredibly difficult to do, particularly in a useful way, so we don't currently have it. And yes, that sucks, and we definitely want to fix it, but I still think that it's far better than having everything be shared by default like you get in languages like C++ and Java. - Jonathan M Davis
Re: Weird UFC and opCall issues
Thanks for the feedback. With classes, you need to create an instance Need to read up classes vs struct. This bit of syntax was very intresting. /* Alternatively, you can move test() inside Test as a static opCall: static Test opCall() { return new Test(); } Then, the syntax in main could be ubyte [] p1 = Test().take(3).array; */ Very impressed with D and starting a new job. Might be able to use it.
Template function type inference with default arguments
Why don't templates take a type from the default argument if nothing else is supplied? It would be useful to be able to use an enum to set a default. enum MAX = 1_000; auto sieve(T)(T max = MAX) { import std.bitmanip : BitArray; BitArray n; n.length = max; T[] primes = [2]; for(T i = 3; i max; i += 2) if(n[i] == 0) { primes ~= i; for(T j = i + i; j max; j += i) n[j] = 1; } return primes; } Changing the type to T = typeof(MAX) works but feels unnecessarily clunky and out of step with how templates normally operate when supplied with an argument.
Re: Example usage of the core.sync classes
On Saturday, 3 January 2015 at 22:10:49 UTC, Vlad Levenfeld wrote: On Saturday, 3 January 2015 at 15:44:16 UTC, Matt wrote: Right, I've been looking at core.atomic, but it has very little documentation, and it's territory I haven't explored, yet. Any chance of some pointers along the way? Could you be more specific about what you need help understanding? You can implement a very simple double buffer like so: synchronized final class DoubleBuffer (T) { T[][2] data; uint write_index; shared void swap () { atomicStore (write_index, (write_index + 1) % 2); (cast()this).buffer[write_index].clear; } shared @property write_buffer () { return (cast()this).buffer[write_index][]; } shared @property read_buffer () { return (cast()this).buffer[(write_index + 1) % 2][]; } } Just append to write_buffer, call swap, then read from read_buffer. Make sure you declare the instance shared. Benjamin's post links to a more robust and realistic implementation. What I mean is that I don't understand what atomicStore, atomicLoad, etc. actually DO, although in the case of the two mentioned, I can hazard a pretty good guess. The documentation doesn't exist to tell me how to use the functions found in the module. I've never used any atomic functions in any language before. However, thank you for the simple double buffered example, I do appreciate it. How would another thread gain access to the instance in use, though? Am I able to pass references to instances of this class via events? 'synchronized' is also something I'm clueless about, and again the D documentation doesn't help, as the section in the class documentation basically says synchronized classes are made of synchronized functions, without explaining what a synchronized function IS. The function section makes no mention of the synchronized keyword, either. Sorry, it feels like there's a load of stuff in the library and language to make multithreading easier, but with little to no explanation, so it feels like you're expected to already know it, unless I'm looking in the wrong places for my explanations. If I am, please do give me a kick, and point me in the right direction.
Re: Template function type inference with default arguments
On Sunday, 4 January 2015 at 00:22:01 UTC, ixid wrote: Why don't templates take a type from the default argument if nothing else is supplied? It would be useful to be able to use an enum to set a default. I doubt anyone's ever thought of that particular use-case. Using your typeof(MAX) workaround is probably as good as it's going to get for the time being.
Re: Example usage of the core.sync classes
On Sunday, 4 January 2015 at 01:02:07 UTC, Matt wrote: What I mean is that I don't understand what atomicStore, atomicLoad, etc. actually DO, although in the case of the two mentioned, I can hazard a pretty good guess. The documentation doesn't exist to tell me how to use the functions found in the module. I've never used any atomic functions in any language before. Atomic operations are guaranteed to happen in one step. For example, x += 1 will load the value of x into a register, increment it by 1, then write the value back to memory, while atomicStore (x, x+1) will cause all three steps to be executed as if they were instantaneous. This prevents a thread writing to an address that another thread just read from, causing that thread's view of the data to be silently outdated (aka a race condition, because the final value of x depends on which thread writes first). However, thank you for the simple double buffered example, I do appreciate it. How would another thread gain access to the instance in use, though? Am I able to pass references to instances of this class via events? You can if they're shared. You can pass the reference via message, or have the reference exist at a location both threads have access to. The two @property functions in the example are meant to be used by the writing and reading thread, respectively. I go about the swap by letting the reader thread message the writer to inform it that it is ready for more data, at which point the writer thread is free to call .swap () once it is done writing (though you can do it the opposite way if you want). 'synchronized' is also something I'm clueless about, and again the D documentation doesn't help, as the section in the class documentation basically says synchronized classes are made of synchronized functions, without explaining what a synchronized function IS. The function section makes no mention of the synchronized keyword, either. A synchronized class has a hidden mutex, and any thread that calls a member method acquires the lock. The synchronized keyword isn't limited to classes, though - you can find a detailed description of synchronized's various uses here: http://ddili.org/ders/d.en/concurrency_shared.html Sorry, it feels like there's a load of stuff in the library and language to make multithreading easier, but with little to no explanation, so it feels like you're expected to already know it, unless I'm looking in the wrong places for my explanations. If I am, please do give me a kick, and point me in the right direction. Yeah, I think the docs are meant to be a reference if you already have in mind what you're looking for, and just need to know how to wire it up. I recommend Ali's book (linked in the previous paragraph) in general as its the most comprehensive and up-to-date explanation of the language as a whole that I've yet seen (and its free).
Need extern (C) interface even though using Derelict GLFW
I've been translating C++, OpenGL, and GLUT code into D, Derelict OpenGL, and Derelict GLFW using: import derelict.opengl3.gl3; import derelict.glfw3.glfw3; auto window = glfwCreateWindow(800, 600, Shaders, null, null); etc. Things have been going well. I then tried to implement window resizing with a callback function and the glfwSetWindowSizeCallback() statement. void windowResizeCallback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } and glfwSetWindowSizeCallback(window, windowResizeCallback); however, I kept getting the following compiler error: Error 1 Error: function pointer glfwSetWindowSizeCallback (GLFWwindow*, extern (C) void function(GLFWwindow*, int, int) nothrow) is not callable using argument types (GLFWwindow*, void function(GLFWwindow* window, int width, int height)) Well, I was able to get it to compile and work by adding the following decoration extern (C) nothrow { void windowResizeCallback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } } Now it resizes the screen successfully, but I feel like I've failed by using extern (C) nothrow. Shouldn't Derelict GLFW be providing a D interface? Maybe GLFW callback functions can't handled through Derelict GLFW?
Re: Need extern (C) interface even though using Derelict GLFW
On 4/01/2015 5:34 p.m., WhatMeWorry wrote: I've been translating C++, OpenGL, and GLUT code into D, Derelict OpenGL, and Derelict GLFW using: import derelict.opengl3.gl3; import derelict.glfw3.glfw3; auto window = glfwCreateWindow(800, 600, Shaders, null, null); etc. Things have been going well. I then tried to implement window resizing with a callback function and the glfwSetWindowSizeCallback() statement. void windowResizeCallback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } and glfwSetWindowSizeCallback(window, windowResizeCallback); however, I kept getting the following compiler error: Error1Error: function pointer glfwSetWindowSizeCallback (GLFWwindow*, extern (C) void function(GLFWwindow*, int, int) nothrow) is not callable using argument types (GLFWwindow*, void function(GLFWwindow* window, int width, int height)) Well, I was able to get it to compile and work by adding the following decoration extern (C) nothrow { void windowResizeCallback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } } Now it resizes the screen successfully, but I feel like I've failed by using extern (C) nothrow. Shouldn't Derelict GLFW be providing a D interface? Maybe GLFW callback functions can't handled through Derelict GLFW? No this is correct code. Derelict projects are just bindings. Which means the c equivalent in D. Nothing more nothing less.
Re: How to create instance of class that get data from 2 another instance?
On 01/02/2015 12:42 PM, Suliman wrote: auto seismodownload = new seismoDownload(emsc_csem, this); then: auto mysql = new MySQL(parseconfig,eqs); So could anybody show me better way? Yes, there is a better way. As I said I did not fully understand how use global class instance... One good thing about D is that globals are better than other languages because they are actually module-global and by default thread-local. Module-global means that there more than one module can use the same name for their respective globals; thread-local means that implicit data-sharing is prevented. However, module-globals can be harmful as well because depending on the design, they prevent functions from being reentrant and prevent having more than one of that resource. For that reason, it is usually better to provide the resource to its consumers e.g. as constructor parameters. Instead of this: string fileName;// -- May be a problem static this() { /* Just to assume that we need a run time value. */ import std.random; import std.string; fileName = format(file_%s, uniform(0, 1000)); } struct S { void foo() { /* Assume that it uses fileName. It would be at least * confusing if there were more than one instance of * S. Which one would be using fileName when? */ } } void main() { auto s = S(); s.foo(); } Prefer this: struct S { string fileName;// -- Takes it as a run-time argument // (Could be constructor parameter as well.) void foo() { /* Now it would be using its own fileName, which might * be provided to more than one object but then it * might be acceptable, presumably because it was * according to design. */ } } void main() { import std.random; import std.string; auto s = S(format(file_%s, uniform(0, 1000))); s.foo(); } Ali