question about the implementation of Variant
Following function will return the reference to a object Foo embedded in a Variant. class Foo {} Variant fun() { Variant v; v = new Foo(); return v; } According to the source code of VariantN.opAssign, the assignment is done by: memcpy(&store, &rhs, rhs.sizeof); fptr = &handler!(T); where rhs is new Foo(), store is embedded storage in Variant, and fptr is accessor function also work as data tag. Very efficient implementation. But wait, how does GC detect there still be a live reference to the object Foo? Because store is just a fix sized array of bytes. ubyte[size] store; GC cannot be aware of the reference, right? Thanks, aki
Re: question about the implementation of Variant
Thank you, Jonathan. Now I understand. On Monday, 4 January 2016 at 17:34:47 UTC, Kapps wrote: union { ubyte[size] store; // conservatively mark the region as pointers static if (size >= (void*).sizeof) void*[size / (void*).sizeof] p; } Interesting to know the way to make GC detect the presence of the potential pointer. Regards, aki.
efficient and safe way to iterate on associative array?
Is it okay to modify associative array while iterating it? import std.stdio; void main() { string[string] hash = [ "k1":"v1", "k2":"v2" ]; auto r = hash.byKeyValue(); while(!r.empty) { auto key = r.front.key; auto value = r.front.value; r.popFront(); writefln("key=%s, value=%s", key, value); // may not modify 'hash' here ? hash = null; } } I guess probably it's not. Then, my question is are there an efficient and safe way to iterate on an associative array even if there are possibility to be modified while iterating? I'm writing interpreter and want to make my language to be safe; even malicious script cannot fall it in 'core dump' state. It is okay if it causes undefined behavior like throw or instant exit from loop, but not crash. Thanks, Aki.
Re: efficient and safe way to iterate on associative array?
On Friday, 4 March 2016 at 16:46:35 UTC, Steven Schveighoffer wrote: You cannot add or remove keys. You can modify values for existing keys. Note, in your code, this would not cause a problem, since setting hash to null just removes the reference from the local variable 'hash', it does not alter the AA in any way. In dcollections, all containers support "purging", or iterating through elements, removing the current element if desired before moving to the next. But I haven't touched this library in ages, I don't know if it still compiles even. -Steve Thank you for it. Now I know. I will copy and modify AA source to customize. (src/rt/aaA.d) I wonder what if D support safe variant like safeByKeyValue. Actually it seems easy (in aaA.d): bool _aaRangeEmpty(Range r) { return r.impl is null || r.idx == r.dim; } can be changed to: bool _aaRangeEmptySafe(Range r) { if(r.impl is null || r.idx >= r.dim) return true; if (!r.buckets[r.idx].filled) throw xxxException(); return false; } It can become safe by a cost of small overhead. -- Aki.
how to declare C's static function?
Hello, When I porting legacy app. written in C to D, I have a problem. file a.d: extern (C) private void foo() {} file b.d: extern (C) private void foo() {} Error 1: Previous Definition Different : _foo In C language, "static void foo(){}" does not export the symbol out side the compilation unit. In D, the function foo() above conflicts even if it is private. How can I declare C's static function? Regards, Aki.
Re: how to declare C's static function?
On Monday, 28 March 2016 at 04:12:56 UTC, Rikki Cattermole wrote: Do you need it to use extern(C)? Because if you don't, just drop that. D's mangling will fix it. Yes, I do need extern(C) for some reason like: alias Hook = extern(C) void function(); void sethook(Hook func) { ... } ... sethook(&foo) ... Some function expects such a function as an argument. Aki.
Re: how to declare C's static function?
On Monday, 28 March 2016 at 04:33:06 UTC, Rikki Cattermole wrote: You have two choices. Change the name in code (so manual mangling) or use pragma(mangle, ...) to change it instead. So... You mean there are no way to declare functions without exporting the symbol? There are so many instances to change.. But thanks any way. Aki.
Re: how to declare C's static function?
On Monday, 28 March 2016 at 14:40:40 UTC, Adam D. Ruppe wrote: On Monday, 28 March 2016 at 04:53:19 UTC, aki wrote: So... You mean there are no way to declare functions without exporting the symbol? alas, no, even if it is private it can conflict on the outside (so stupid btw). Is it all the same function being referenced? Just importing from there would be ok. Thank you for clarify. Now I know I have to change the name as a result. Thanks, aki.
Re: how to declare C's static function?
On Tuesday, 29 March 2016 at 01:04:50 UTC, Mike Parker wrote: On Monday, 28 March 2016 at 14:40:40 UTC, Adam D. Ruppe wrote: On Monday, 28 March 2016 at 04:53:19 UTC, aki wrote: So... You mean there are no way to declare functions without exporting the symbol? alas, no, even if it is private it can conflict on the outside (so stupid btw). Seems to be fixed in the latest beta (finally): http://dlang.org/changelog/2.071.0.html#dip22 Good news!
what's the right way to get char* from string?
Hello, When I need to call C function, often need to have char* pointer from string. "Interfacing to C++" page: https://dlang.org/spec/cpp_interface.html have following example. extern (C) int strcmp(char* string1, char* string2); import std.string; int myDfunction(char[] s) { return strcmp(std.string.toStringz(s), "foo"); } but this is incorrect because toStringz() returns immutable pointer. One way is to write mutable version of toStringz() char* toStringzMutable(string s) @trusted pure nothrow { auto copy = new char[s.length + 1]; copy[0..s.length] = s[]; copy[s.length] = 0; return copy.ptr; } But I think this is common needs, why it is not provided by Phobos? (or tell me if it has) Thanks, aki
Re: what's the right way to get char* from string?
On Thursday, 5 May 2016 at 11:35:09 UTC, Jonathan M Davis wrote: If you want a different mutability, then use the more general function std.utf.toUTFz. e.g. from the documentation: auto p1 = toUTFz!(char*)("hello world"); auto p2 = toUTFz!(const(char)*)("hello world"); auto p3 = toUTFz!(immutable(char)*)("hello world"); auto p4 = toUTFz!(char*)("hello world"d); auto p5 = toUTFz!(const(wchar)*)("hello world"); auto p6 = toUTFz!(immutable(dchar)*)("hello world"w); - Jonathan M Davis Ah! This can be a solution. Thanks Jonathan. -- aki.
how to define a struct without padding
Hi, This is a code ported from some windows C program. It is the Windows WAVE file header definition. The field layout is the same with C, but it has extra 2 bytes at the end, sizeof(WAVEHEADER) in C is 46 while WAVEHEADER.sizeof in D is 48. Why it still have padding in spite of "align(1)" ? How can I remove extra padding bytes? module main; import std.stdio; alias ushort WORD; alias uint DWORD; align(1) struct WAVEFORMATEX { WORDwFormatTag; /* format type */ WORDnChannels; /* number of channels (i.e. mono, stereo...) */ DWORD nSamplesPerSec; /* sample rate */ DWORD nAvgBytesPerSec;/* for buffer estimation */ WORDnBlockAlign;/* block size of data */ WORDwBitsPerSample; /* number of bits per sample of mono data */ WORDcbSize; /* the count in bytes of the size of */ /* extra information (after cbSize) */ }; align(1) struct WAVEHEADER { char[4] szRIFF; int lRIFFSize; char[4] szWave; char[4] szFmt; int lFmtSize; WAVEFORMATEXwfex; char[4] szData; int lDataSize; }; void main() { writeln(WAVEHEADER.sizeof); // 48; but it must be 46 } Thanks, Aki
Re: how to define a struct without padding
On Thursday, 25 May 2017 at 01:34:35 UTC, Adam D. Ruppe wrote: align(1) struct NAME { align(1): members } My problem is resolved. Thank you for the quick reply. Thanks, Aki
convert string to ubyte[]
Hello, This will be trivial question but I cannot figure out what's wrong. I want to convert string to an array of ubyte. import std.conv; void main() { auto s = "hello"; ubyte[] b = to!(ubyte[])(s); } It compiles but cause run time error: std.conv.ConvException@C:\APP\D\dmd2\windows\bin\..\..\src\phobos\std\conv.d(3530): Can't parse string: "[" is missing I cannot understand the meaning of this message. Replacing s with s.dup to remove immutable doesn't help. Do I need to use cast? Regards, Aki
Re: convert string to ubyte[]
On Saturday, 11 November 2017 at 15:48:59 UTC, Mike Parker wrote: auto s = "hello"; auto bytes = s.representation; https://dlang.org/phobos/std_string.html#.representation Thank you for the replay. Now I know. aki
how to iterate on Array?
I want to print the contents of Array!int import std.stdio; import std.container; void pr(Array!int a) { foreach(i, v; a[]) { writeln("%4s: %s\n", i, v); } } But when I compile it by DMD 2.062 on Windows it says: testArray.d(5): Error: cannot infer argument types (line 5 is at "foreach(i, v; a[]) {" ) What's wrong? how can I iterate the array? Thanks, aki.
Re: how to iterate on Array?
On Saturday, 27 June 2015 at 18:32:10 UTC, Ali Çehreli wrote: On 06/27/2015 10:43 AM, aki wrote: You are rightly assuming that the loop counter is available for all container types. Unfortunately, it is the case only for arrays. Now I know. Thanks for it. aki.
Re: how to iterate on Array?
On Sunday, 28 June 2015 at 10:16:47 UTC, Marc Schütz wrote: On Saturday, 27 June 2015 at 17:43:13 UTC, aki wrote: But when I compile it by DMD 2.062 on Windows it says: testArray.d(5): Error: cannot infer argument types (line 5 is at "foreach(i, v; a[]) {" ) 2.062 is really ancient, we're about to release 2.068 soon. Consider upgrading, because there have been tons of bugfixes since your version. On current DMD, the error message is slightly clearer: "Error: cannot infer argument types, expected 1 argument, not 2" Ah, you answered my another question. Even if I put all the types like foreach(size_t i, int v; a[]) he still said "cannot infer." I wonder why he need to infer? Now I got it. I'm looking forward 2.068. Aki.
proper way to calculate toHash() for string
I would like to know proper way to calculate hash for given member fields. class Foo { int value; string str; override nothrow @safe size_t toHash() { // calculate hash based on field value. // value and str in this example. } } boost::hash provides easy and systematic way to calculate hash. I found std.digest.crc is useful. override nothrow @safe size_t toHash() { if (str is null) return value; ubyte[4] hash = crc32Of(str); return value^((hash[0]<<24)|(hash[1]<<16)|(hash[2]<<8)|hash[3]); } Please suggest me if anyone have an idea. Regards, aki.
Re: proper way to calculate toHash() for string
On Tuesday, 30 June 2015 at 19:36:24 UTC, Jacob Carlborg wrote: On 30/06/15 16:19, aki wrote: Please suggest me if anyone have an idea. You can use TypeInfo.getHash [1] to get the hash of a given value. Something like: string a = "foo"; typeid(a).getHash(&a) [1] http://dlang.org/phobos/object.html#.TypeInfo.getHash Wow, this is what I was looking for. It's generic way. Thank you for good suggestion. Your 2 lines code is also a good explanation for the manual of getHash. Because it's not obvious what is the argument for the getHash.
how to avoid "cycle detected"?
Following code causes run-time error. How can I use static this() without causing error? It's difficult to avoid this situation because actual code is more complex. file main.d: void main() { } file a.d: import b; class A { static this() {} }; file b.d: import a; class B { static this() {} }; object.Exception@src\rt\minfo.d(162): Aborting: Cycle detected between modules w ith ctors/dtors: a -> b -> a
Re: how to avoid "cycle detected"?
On Wednesday, 1 July 2015 at 22:25:48 UTC, Jonathan M Davis wrote: On Wednesday, July 01, 2015 08:52:38 Steven Schveighoffer via Digitalmars-d-learn wrote: The runtime cannot introspect the code to detect the circular dependency, so it makes a conservative decision. I'm waiting on an introduction of RTInfo for modules [1] to allow us to mark static ctors as standalone, then we can probably fix this problem through a sort of "trust the programmer" mechanism. I wouldn't mind that, but Walter shot that idea down previously when I was arguing for adding a way to the language to tell the compiler that a static constructor didn't depend on anything else. He didn't want a "trust the programmer" mechanism in this case. I don't remember what his arguments were though. - Jonathan M Davis Thanks for the discussion, now I understand there are technical difficulties. I have to give it a name like void staticInit(); and call it manually from main(). aki.
Re: how to avoid "cycle detected"?
On Thursday, 2 July 2015 at 17:21:03 UTC, Kapps wrote: An ugly solution, but the approach used in Phobos is to create something like a_init.d which a.d imports, provided that the static ctors don't actually rely on things from the static ctor of b. How about this idea? Allowing to define sub module in a module. file foo.d: module foo; // nameless module, automatically imported by outer module foo module { int[] needInitialize; static this() { needInitialize = ...; } } // use statically initialized variable needInitialize... Basically, d-lang's module has one-to-one correspondence with file. This new feature breaks this rule, but it's safe because this one is private to module foo. There are no way to import this nameless module by other modules. The purpose is just the alternative to making foo_init.d file. aki.
how to manage the list of immutable objects
I like to create immutable object which is identified by name as it's key. And also need get() to look up named object which is already created. class Foo { static immutable(Foo)[string] map; string name; // and other attributes here... this(string name) immutable { this.name = name; map[name] = this; } static immutable(Foo) get(string name) { return map[name]; } } But this code causes error: test.d(8): Error: cannot modify immutable expression map[name] How can I declare the map so that it contains immutable object Foo, but the reference to Foo is mutable? Anyway the goal is to provide get() function. Tell me how to implement get(). Aki.
Re: how to manage the list of immutable objects
On Tuesday, 14 July 2015 at 10:46:42 UTC, Andrea Fontana wrote: Trying on http://dpaste.dzfl.pl/ I don't see that error. Maybe you mean "const" and not "immutable" ? Andrea I used: DMD32 D Compiler v2.067.1 on Windows8 I believe there are no typo because it is copy-pasted. I noticed I can use cast. cast()(map[name]) = cast()this; Are there any better solution? Aki.
Re: how to manage the list of immutable objects
On Tuesday, 14 July 2015 at 11:44:34 UTC, Steven Schveighoffer wrote: static Rebindable!(immutable(Foo))[string] map -Steve It all works. And I learned something from the source code of Rebindable. Thank you. Aki.
question about the semantics of unshared variables
I want to make sure about the semantics of unshared variables. import std.concurrency; import core.thread; ubyte[1024 * 1024] buf1MB; void fun() { Thread.sleep(5000.msecs); } void testThread() { foreach(i; 0..2000) { spawn(&fun); } } Are instances of buf1MB created for every threads? Even if it is never accessed by the threads? If some static variable is defined in other module or in some library, all of them also instantiated for every threads? BTW, calling testThread() above causes following run time error. Is this an expected result? core.thread.ThreadError@src\core\thread.d(2903): Error creating thread 0x0047B1A7 0x0042ABD4 0x0042AB3B 0x0042AB27 0x0042ADF9 0x00474C22 0x00474BF7 0x00474B0F 0x0042AE13 0x757A7C04 in BaseThreadInitThunk 0x7735AD1F in RtlInitializeExceptionChain 0x7735ACEA in RtlInitializeExceptionChain
Re: question about the semantics of unshared variables
I noticed just making many threads cause an error. Are there any limit for the number of threads? import std.concurrency; import core.thread; void fun() { Thread.sleep(5000.msecs); } void testThread() { foreach(i; 0..2000) { spawn(&fun); } } core.thread.ThreadError@src\core\thread.d(2903): Error creating thread Aki.
How to use core.thread.Thread
I can't resolve the compile errors: import core.thread; class DerivedThread : Thread { int count = 0; this() { super(&run); } private void run() { inc(); //testThread.d(8): Error: shared method testThread.DerivedThread.inc is not callable using a non-shared object } synchronized void inc() { ++count; //testThread.d(11): Deprecation: read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(this.count, 1) instead. } } void main() { auto thr = new DerivedThread(); thr.start(); thr.inc(); //testThread.d(17): Error: shared method testThread.DerivedThread.inc is not callable using a non-shared object thr.join(); } 1. Should I declare thr as shared? But auto thr = new shared DerivedThread(); does not resolve it. 2. Why "++count" cause an error? I think it is safe because it is marked as synchronized. If it is forced to use atomicOp all the time, it's painful. 3. Are there any tutorials about using Thread class? Aki.
Re: question about the semantics of unshared variables
On Thursday, 16 July 2015 at 07:36:39 UTC, Jonathan M Davis wrote: Yes. Every thread gets a copy of the non-shared static variables, and all of the non-shared static constructors get run for each thread. - Jonathan M Davis Thank you for reply. Now i know. I did some test using C++ as you said, then there are some different problem occurred. Anyway no need to make so many threads. Please just forget it. Aki.
Re: How to use core.thread.Thread
On Thursday, 16 July 2015 at 08:21:26 UTC, maarten van damme wrote: Have you checked out std.parallelism and std.concurrency? I know std.concurrency to use spawn. If I cannot use Thread, I'll implement by spawn. But want to try Thread class because it seems similar to Java's Thread class. I don't know std.parallelism. It seems for the different case. Aki.
Re: How to use core.thread.Thread
On Thursday, 16 July 2015 at 09:17:47 UTC, Daniel Kozák wrote: class DerivedThread : Thread { shared int count = 0; } I thought shared is only for whole of the object. auto thr = new DerivedThread(); Here, "thr" is not shared but it's member thr.count is shared? But if it's not shared, thr object referred by main thread and "this" reference of DerivedThread.run() are different? What happen if there are both shared and unshared member exists? class DerivedThread : Thread { shared int count = 0; int foo = 0; } Umm. I can't imagine what's the memory layout of this object.
Re: How to use core.thread.Thread
On Friday, 17 July 2015 at 14:14:41 UTC, byron wrote: Since I have yet to use or see anyone use shared in a useful way I avoid it. It's one way to avoid it. So, you mean you always use send/receive when you need threading? I did small test to know the memory layout. import core.atomic; int foo; shared int sfoo; class DerivedThread : Thread { int count; shared int scount; this() { super(&run); } private void run() { inc(); writefln("at thread: foo=%s, &foo=%s, sfoo=%s, &sfoo=%s", foo, &foo, sfoo, &sfoo); writefln("at thread: count=%s, &count=%s, scount=%s, &scount=%s", count, &count, scount, &scount); } void inc() { ++foo; atomicOp!"+="(sfoo, 1); ++count; atomicOp!"+="(scount, 1); } } void main() { auto thr = new DerivedThread(); thr.start(); thr.inc(); thr.join(); writefln(" at main: foo=%s, &foo=%s, sfoo=%s, &sfoo=%s", foo, &foo, sfoo, &sfoo); writefln(" at main: count=%s, &count=%s, scount=%s, &scount=%s", thr.count, &thr.count, thr.scount, &thr.scount); } at thread: foo=1, &foo=A33580, sfoo=2, &sfoo=5541E4 at thread: count=2, &count=240178, scount=2, &scount=24017C at main: foo=1, &foo=984B28, sfoo=2, &sfoo=5541E4 at main: count=2, &count=240178, scount=2, &scount=24017C That means Thread object "thr" is always shared while global foo is not shared because it has different memory location. In my understanding, shared is not only checking something at compile time, but also it affects on the memory layout. Aki.