Re: Member variables in method are null when called as delegate from thread

2021-01-12 Thread tsbockman via Digitalmars-d-learn

On Wednesday, 13 January 2021 at 02:15:49 UTC, Tim wrote:
Basically, the program calls a function which modifies a 
document in the database. If it is called form it's own class' 
constructor, it works fine. If it is called by a thread, it 
never returns.

...
class Caller : Thread{
void delegate() mFunc;

this(void delegate() func){
mFunc = func;
super(&loop);
start();
}

void loop(){
while(true){
mFunc();
}
}
}

class Callable{
MongoClient db;
Caller caller;

this(){
db = connectMongoDB("127.0.0.1");
foo();
caller = new Caller(&foo);
}

~this(){
db.cleanupConnections();
}

void foo(){
writeln("Started");
auto result = 
db.getCollection("test.collection").findAndModify([

"state": "running"],
["$set": ["state": "stopped"]
]);
writeln(result);
writeln("Finished");
}
}


Note that if you are trying to debug a crash or hang of a program 
by printing messages to the console, you need to flush stdout 
multiple times in the vicinity of the problem, otherwise stdio's 
buffering may make it appear as though the program crashed or 
hung significantly earlier than it really did. (This is not a 
merely theoretical problem; I trip over it frequently myself.)


Anyway, I think your real problem is that MongoClient is not 
thread-safe. From the official vibe.d documentation 
(https://vibed.org/api/vibe.db.mongo.mongo/connectMongoDB):


Note that the returned MongoClient uses a 
vibe.core.connectionpool.ConnectionPool internally to create 
and reuse connections as necessary. Thus, the MongoClient 
instance can - and should - be shared among all fibers in a 
thread by storing in in a thread local variable.


Note the "in a thread" part; you may only use a connection from 
the same thread that opened it.


(Why? I'm not familiar with vibe.d's API or code base, so I don't 
really know. But, I'd guess that the connection reuse mechanism 
mentioned in the docs requires some of the information that you 
might expect to be stored in the MongoClient instance itself to 
instead end up in thread-local storage (whether native or 
emulated). Or, there may simply be a manual "same thread" check 
built into the DB operations to prevent data races, and the error 
message isn't reaching you for some reason. `assert` messages 
don't print in release mode, and I've found the gdb debugger for 
D quite unreliable when trying to inspect multi-threaded code.)


Try moving the calls to `connectMongoDB` and `cleanupConnections` 
into the same thread as `foo`. (I can't think of a good reason to 
be doing these in the original thread, other than convenience.) 
If you want to loop in multiple threads simultaneously, just open 
a separate connection per thread, like the vibe.d docs suggest.


Re: Anything in D to avoid check for null everywhere?

2021-01-12 Thread Jack via Digitalmars-d-learn

Currently I'm with this:

auto ref ifNotNull(T, T2)(T lhs, lazy T2 rhs)
{
if(lhs) {
rhs();
}
return lhs;
}


far from good. I wish there was a way to create a new operator so 
I would make .? similar to C#'s but would evaluate the 
left-handed side only if it's null and do nothing otherwise (C#'s 
evaluate to null, probably due to lack of control of flow 
structure, which isn't possible within a source code, only from 
compiler's side, as far i know)


Re: Member variables in method are null when called as delegate from thread

2021-01-12 Thread Tim via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 01:49:11 UTC, tsbockman wrote:
The compiler and the physical CPU are both allowed to change 
the order in which instructions are executed to something 
different from what your code specifies, as long as the 
visible, "official" results and effects of the chosen order of 
execution are the same as those of your specified code, FROM 
THE PERSPECTIVE OF THE EXECUTING THREAD.


This is allowed so that the compiler can optimize to minimize 
negative "unofficial" effects such as the passage of time and 
memory consumption.


However, this re-ordering IS permitted to freely alter the 
behavior of your code from the perspective of OTHER threads. A 
likely cause of your bug is that the write to db by the 
constructor's thread is being committed to memory after the 
read of db by the MessageService thread.


In order to RELIABLY fix this kind of problem, you must 
correctly use the only commands which the compiler and CPU are 
NOT allowed to reorder with respect to other threads, namely 
atomic operations, memory barriers and synchronization 
primitives. A wide selection of these tools may be found in 
these D runtime library modules:


core.sync: 
http://dpldocs.info/experimental-docs/core.sync.html
core.atomic: 
http://dpldocs.info/experimental-docs/core.atomic.html
core.thread: 
http://dpldocs.info/experimental-docs/core.thread.html


(I recommend using Adam D. Ruppe's unofficial but superior 
rendering of the D runtime documentation at dpldocs.info rather 
than the official dlang.org rendering, as I found some 
necessary pieces of the documentation are just mysteriously 
missing from the offical version.)


Be warned that most models of multi-threaded programming are 
difficult to implement correctly, as opposed to ALMOST 
correctly with subtle heisen-bugs. You should either stick to 
one of the known simple models like immutable message passing 
with GC, or do some studying before writing too much code.


Here are some resources which I have found very helpful in 
learning to understand this topic, and to avoid its pitfalls:


Short educational game: https://deadlockempire.github.io/
Tech talk by C++ expert Herb Sutter (D's core.atomic uses 
the C++ memory model):

https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2

https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2


If you want to seriously dig into this, I suggest reviewing 
some or all of the content at the links above. If you're still 
confused about how to apply it in D, feel free to come back and 
ask for examples or code reviews. I'd rather not start with 
examples, though, because if you don't understand the rules and 
principles behind them, it's really easy to unknowingly 
introduce bugs into otherwise correct examples with seemingly 
innocent changes.


Fantastic response, thank you! I did some more digging and 
properly narrowed down where the issue is and created a test 
script that demonstrates the problem. Let me know what you think 
and if it could still be a similar problem to what you have 
stated above. I'll still read that info you sent to sharpen up on 
these concepts.


Basically, the program calls a function which modifies a document 
in the database. If it is called form it's own class' 
constructor, it works fine. If it is called by a thread, it never 
returns. I don't think that a member variable is going null or 
anything. But a strange problem that I can't seem to debug. The 
output is at the bottom.




import vibe.db.mongo.mongo;
import core.thread;
import std.stdio;

void main(){
auto callable = new Callable();

while(true){}
}

class Caller : Thread{
void delegate() mFunc;

this(void delegate() func){
mFunc = func;
super(&loop);
start();
}

void loop(){
while(true){
mFunc();
}
}
}

class Callable{
MongoClient db;
Caller caller;

this(){
db = connectMongoDB("127.0.0.1");
foo();
caller = new Caller(&foo);
}

~this(){
db.cleanupConnections();
}

void foo(){
writeln("Started");
auto result = 
db.getCollection("test.collection").findAndModify([

"state": "running"],
["$set": ["state": "stopped"]
]);
writeln(result);
writeln("Finished");
}
}



Output:
Started

{"_id":"5ff6705e21e91678c737533f","state":"running","knowledge":true}

Finished
Started


Re: Developing and running D GUI app on Android

2021-01-12 Thread H. S. Teoh via Digitalmars-d-learn
On Sun, Jan 10, 2021 at 06:58:13PM +, aberba via Digitalmars-d-learn wrote:
> I'm looking to explore running a D application on Android based on
> Adams previous foundation work. However, I'm not familiar with the
> Android + D integration so I need some help.
> 
> Has any of you successfully done that? Could use a sample code or
> anything I can use to figure out how to start.

First, you need a way to build an APK, and then transfer that to your
Android device for testing.  Building an APK *can* be done manually
(well, scripted), but I don't recommend it.  The simplest way is
probably to install Android Studio and the Android SDK, and use Gradle
to build your project.  Gradle takes care of the finicky details of how
to build an APK, and the Android dev tools let you install to Android in
debug mode without having to find your own way of transferring APKs.

For compiling D, you'll need LDC configured to cross-compile to Android:

https://wiki.dlang.org/Build_D_for_Android

Talk to Adam for more details -- he has done some work to remove some of
the manual munging described on that page, but I don't remember how
much.  For maximum convenience, you probably want to figure out how to
integrate your build process with Gradle so that it can be done with a
single command.  (I opted not to use Gradle, but an SCons-based system
that's actually very fast at cross-compiling D and building APKs. But
most people will probably want to use Gradle.)

Most of the hard work is the setup; once you have a working environment
writing D for Android is pretty smooth.  Esp. with Adam's jni.d,
interacting with Android's Java APIs ought to be a lot easier than ever.

If you have more specific questions I can try to answer them.


T

-- 
If it's green, it's biology, If it stinks, it's chemistry, If it has numbers 
it's math, If it doesn't work, it's technology.


Re: Problem with templated alias as delegate parameter type

2021-01-12 Thread cc via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 21:32:14 UTC, Ali Çehreli wrote:

On 1/12/21 12:58 PM, cc wrote:

>  void send(T query, void delegate(T.RESPONSE) callback) {

That wants a delegate that takes a T.RESPONSE (PingResponse in 
this case). However, the following lambda is in fact a template:


>  send(PingQuery("helo"), (resp) {

You specify the type there and it works:

send(PingQuery("helo"), (PingResponse resp) {

Ali


That seems to work, thanks.  I ended up having to define a second 
template parameter:


template send(T,TR) if (is(TR == T.RESPONSE)) {
void send(T query, void delegate(TR) callback) {
...




Re: I want to create my own Tuple type

2021-01-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 21:38:59 UTC, sighoya wrote:

What about this?
No magic, but I don't know the performance impact.

```
import std.meta;
import std.conv;

template same(Types...)
{
static if (Types.length >= 2)
{
static if (is(Types[0] == Types[$ - 1]))
{
const same = same!(Types[1 .. $]);
}
else
{
enum bool same = false;
}
}
else
{
enum bool same = true;
}
}


I also like the recursive version better. I borrowed the core 
concept from Phobos. I assume they don't use recursion because 
they are afraid of running out of stack space? Or maybe it is 
because of performance?




struct Tuple(Types...)
{

static if (same!Types)
{
public Types[0][Types.length] elements;


Yes, this is what I also felt was the right approach. But then I 
realized that AliasSeq (which is what you get if you use "Types 
expand") is hardwired in the compiler in a hackish way so that 
you get various features from it, like implicit splatting 
(expanding the sequence into arguments)?  That kinda makes it 
difficult to get the right semantics as I know of no way to do it 
without AliasSeq, but maybe there is some way, perhaps one can 
convert it into an AliasSeq somehow.


I kinda don't like this kind of compiler-magic for one specific 
type as it limits what you can do, but I guess it was done for 
easy-of-implementation.



static foreach (int i, T; Types)
{
mixin("public " ~ T.stringof ~ " " ~ "elem" ~ 
i.stringof ~ ";");

}


Yep, I had this version at some point :-)

I think the way you approached it is the intuitive way, but the 
problem is really that AliasSeq get special treatment by the 
compiler so it is currently difficult to work around it?


One should probably look closer at the language semantics and try 
to come up with a more generic mechanism as that would make for 
more powerful meta programming.






Re: Member variables in method are null when called as delegate from thread

2021-01-12 Thread tsbockman via Digitalmars-d-learn
On Tuesday, 12 January 2021 at 14:00:11 UTC, Steven Schveighoffer 
wrote:

On 1/11/21 8:49 PM, tsbockman wrote:
However, this re-ordering IS permitted to freely alter the 
behavior of your code from the perspective of OTHER threads. A 
likely cause of your bug is that the write to db by the 
constructor's thread is being committed to memory after the 
read of db by the MessageService thread.


I don't think this is valid.


You might be right, but your analysis below assumes the answers 
to a number of questions which aren't answered in the source code 
provided by the OP. Perhaps you are familiar with the 
implementations of the APIs in question, but I'm not and thought 
it unwise to assume too much, given that the whole reason we're 
having this discussion is that the code doesn't actually work...


Regardless, the simple way to find out if I'm on the right track 
or not is just to protect access to Foo's fields with a mutex and 
see if that fixes the problem. If it does, then either it's a 
memory ordering issue like I suggested (or a code gen bug), and 
the mutex can be replaced with something more efficient if 
necessary.


1. the compiler MUST NOT reorder the storage of db to after you 
pass a delegate into an opaque function (array allocation).


Is the function actually opaque, though? If the source code is 
available to the compiler for inlining (or maybe if it's marked 
`pure`?) then reordering is still allowed.


2. The CPU is not going to reorder, because the memory 
allocation is going to take a global lock anyway (mutex locks 
should ensure memory consistency).


This is not a safe assumption. It is quite easy to design a 
thread-safe allocator that does not take a global lock for every 
allocation, and indeed *necessary* if you want it to scale well 
to heavy loads on high core count systems.


Even if that's how it works today, I wouldn't write code that 
depends on this behavior, unless the language standard formally 
guaranteed it, because someone will change it sooner or later as 
core counts continue to climb.


I can't ever imagine creating a thread (which is likely what 
MessageService ctor is doing) to not have a consistent memory 
with the creating thread on construction.


It seems reasonable to assume that thread creation includes a 
write barrier somewhere, but what if MessageService is using an 
existing thread pool?



The CPU would have to go out of its way to make it inconsistent.


No, there are many levels of caching involved in the system, most 
of which are not shared by all cores. The CPU has to go out of 
its way to make memory appear consistent between cores, and this 
is expensive enough that it doesn't do so by default. That's why 
atomics and memory barriers exist, to tell the CPU to go out of 
its way to make things consistent.


You often don't have to deal with these issues directly when 
using higher-level multi-threading APIs, but that's because they 
try to include the appropriate atomics/barriers internally, not 
because the CPU has to "go out of its way" to make things 
inconsistent.


Re: I want to create my own Tuple type

2021-01-12 Thread sighoya via Digitalmars-d-learn

What about this?
No magic, but I don't know the performance impact.

```
import std.meta;
import std.conv;

template same(Types...)
{
static if (Types.length >= 2)
{
static if (is(Types[0] == Types[$ - 1]))
{
const same = same!(Types[1 .. $]);
}
else
{
enum bool same = false;
}
}
else
{
enum bool same = true;
}
}

struct Tuple(Types...)
{

static if (same!Types)
{
public Types[0][Types.length] elements;
public this(Types[0][Types.length] elements...)
{
this.elements = elements;
}
}

else
{
static foreach (int i, T; Types)
{
mixin("public " ~ T.stringof ~ " " ~ "elem" ~ 
i.stringof ~ ";");

}
public this(Types elements)
{
static foreach (int i, T; Types)
{
mixin("this.elem" ~ i.stringof ~ "=" ~ 
"elements[i]" ~ ";");

}
}
}
}

int main()
{
import std.stdio;

auto homogenousTuple = Tuple!(int, int)(2, 3);
writeln("homogenous tuple ", homogenousTuple.elements[0], ":",
typeid(homogenousTuple.elements[0]), ":", 
homogenousTuple.elements[1],

":", typeid(homogenousTuple.elements[1]));
auto heterogenousTuple = Tuple!(int, float)(2, 3);
writeln("heterogenous tuple ", heterogenousTuple.elem0, ":", 
typeid(heterogenousTuple.elem0),
":", heterogenousTuple.elem1, ":", 
typeid(heterogenousTuple.elem1));

return 0;
}
```

Problem is, the type arguments getn't inferred.


Anything in D to avoid check for null everywhere?

2021-01-12 Thread Jack via Digitalmars-d-learn
I was looking for a way to avoid null checks everywhere. I was 
checking the Null object pattern, or use something like enforce 
pattern, or even if I could make a new operator and implement 
something like C#'s .? operator, that Java was going to have one 
but they refused[1] (doesn't behave exactly as C#'s actually), 
Kotlin also got something in this area[2]


What some D ways to avoid those checks?

[1]: 
https://mail.openjdk.java.net/pipermail/coin-dev/2009-March/47.html
[2]: 
https://kotlinlang.org/docs/reference/null-safety.html#safe-calls


Re: Problem with templated alias as delegate parameter type

2021-01-12 Thread Ali Çehreli via Digitalmars-d-learn

On 1/12/21 12:58 PM, cc wrote:

>  void send(T query, void delegate(T.RESPONSE) callback) {

That wants a delegate that takes a T.RESPONSE (PingResponse in this 
case). However, the following lambda is in fact a template:


>  send(PingQuery("helo"), (resp) {

You specify the type there and it works:

send(PingQuery("helo"), (PingResponse resp) {

Ali



Re: properly passing strings to functions? (C++ vs D)

2021-01-12 Thread IGotD- via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 18:12:14 UTC, Q. Schroll wrote:


Did you consider `in`? It will do that in some time and do it 
now with -preview=in.
If you're using `const`, in almost all cases, `in` will work, 
too, and be better (and shorter).


Has the redesignation of "in" like in the preview been formally 
accepted as a part of language? I know that it was suggested to 
make "in" the optimized parameter passing for const which I like. 
However, if I'm going to use it I need to know if this going to 
be accepted as I don't want go around and change all the 
parameters back again if it was not accepted.


Problem with templated alias as delegate parameter type

2021-01-12 Thread cc via Digitalmars-d-learn

Given the following program:

struct PingQuery {
string msg;
}
struct PingResponse {
string msg;
}
template send(T) {
void send(T query, void delegate(PingResponse) callback) {
writefln("Sending: %s", query);
if (callback) {
PingResponse resp;
resp.msg = query.msg;
callback(resp);
}
}
}
void main() {
send(PingQuery("helo"), (resp) {
writefln("Got response: %s", resp);
});
}

This works, but as you can see the PingResponse struct is 
hardcoded in the send function.  If I try to make it a part of 
the template in a way such as this:


struct PingQuery {
alias RESPONSE = PingResponse;
string msg;
}
struct PingResponse {
string msg;
}
template send(T) {
	static assert(is(T.RESPONSE == PingQuery.RESPONSE)); // this 
succeeds at least


void send(T query, void delegate(T.RESPONSE) callback) {
writefln("Sending: %s", query);
if (callback) {
T.RESPONSE resp;
resp.msg = query.msg;
callback(resp);
}
}
}
void main() {
send(PingQuery("helo"), (resp) {
writefln("Got response: %s", resp);
});
}
I get:
delegatetest.d(48): Error: template `delegatetest.send` cannot 
deduce function from argument types `!()(PingQuery, void)`, 
candidates are:
delegatetest.d(35):`send(T)(T query, void 
delegate(T.RESPONSE) callback)`


Same error if I use a nested struct (e.g. struct PingQuery { 
struct RESPONSE {} }) instead of an alias.  Currently using DMD32 
D Compiler v2.095.0-dirty (win64).





Re: Variadic Struct Parameter

2021-01-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/12/21 2:49 PM, ryuukk_ wrote:

On Tuesday, 12 January 2021 at 18:44:53 UTC, Jonathan Levi wrote:

On Tuesday, 12 January 2021 at 17:46:14 UTC, Q. Schroll wrote:
It's obvious why arrays work, it's the primary use case. I have no 
idea why classes are allowed. That classes are allowed, but structs 
are not, makes no sense to me.


I like the variadic feature for classes, but I wish it worked for 
structs as well, given that structs are value types on the stack 
anyway, the same assembly could have either signature (assuming 
matching argument/struct ordering).


But why does this compile?

```
struct S {/*...*/}

void fun(S s...) {/*...*/}
```
If structs do not work as variadic parameters, why does `fun` still 
compile?



you can do this:

```
import std.stdio;
import core.internal.moving;
import core.memory;

void main()
{
     auto a = Data(1);
     auto b = Data(2);
     auto c = Data(3);

     hello(a, b, c);
}

void hello(Data...)(Data args)


this is a template parameter named 'Data' that supersedes the 
module-level type named 'Data'. Not the same thing.


-Steve


Re: Renamed but non-selective import?

2021-01-12 Thread cc via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 20:19:20 UTC, ag0aep6g wrote:

On 12.01.21 21:09, cc wrote:

import core.sys.windows.windows;
import mymodule; // contains a struct named MSG
Error: `core.sys.windows.winuser.MSG` ... conflicts with 
`mymodule.MSG`


vs

import core.sys.windows.windows : winMSG = MSG; // this leaves 
out other symbols

Error: undefined identifier `HWND`
Error: undefined identifier `LPCSTR`


import core.sys.windows.windows;
import mymodule;
alias MSG = mymodule.MSG;
alias winMSG = core.sys.windows.windows.MSG;


Ahh simple enough, thanks.


Re: Variadic Struct Parameter

2021-01-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/12/21 12:46 PM, Q. Schroll wrote:

On Tuesday, 12 January 2021 at 17:26:15 UTC, Jonathan Levi wrote:

Why is this not working?

```
struct S {
    int x;
    string y;
}

void fun(S s ...) {


This is intended for arrays and classes, not structs. Using ... for 
something other than arrays and c



    fun(S(5,"hi"));


That one should compile...


    fun(5,"hi");


and the second one not.

It's obvious why arrays work, it's the primary use case. I have no idea 
why classes are allowed. That classes are allowed, but structs are not, 
makes no sense to me.


Originally, structs did not allow a constructor. I'm thinking probably 
when they got constructors, the (almost never-used) variadic form of 
class parameter passing did not get ported to structs.


-Steve


Re: Variadic Struct Parameter

2021-01-12 Thread Q. Schroll via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 18:44:53 UTC, Jonathan Levi wrote:

On Tuesday, 12 January 2021 at 17:46:14 UTC, Q. Schroll wrote:
It's obvious why arrays work, it's the primary use case. I 
have no idea why classes are allowed. That classes are 
allowed, but structs are not, makes no sense to me.


I like the variadic feature for classes, but I wish it worked 
for structs as well, given that structs are value types on the 
stack anyway, the same assembly could have either signature 
(assuming matching argument/struct ordering).


But why does this compile?

```
struct S {/*...*/}

void fun(S s...) {/*...*/}
```
If structs do not work as variadic parameters, why does `fun` 
still compile?


Because D does allow you to specify things that have no effect. 
People sometimes complain about this as nonsense, but it has its 
merits in meta-programming:


void fun(T)(T t...) { }

Here, if T is a class or array type (including static arrays, 
btw), the dots have an effect, otherwise not. It would be 
unnecessary to require a split on the basis what T is.


Re: Renamed but non-selective import?

2021-01-12 Thread ag0aep6g via Digitalmars-d-learn

On 12.01.21 21:09, cc wrote:

import core.sys.windows.windows;
import mymodule; // contains a struct named MSG
Error: `core.sys.windows.winuser.MSG` ... conflicts with `mymodule.MSG`

vs

import core.sys.windows.windows : winMSG = MSG; // this leaves out other 
symbols

Error: undefined identifier `HWND`
Error: undefined identifier `LPCSTR`


import core.sys.windows.windows;
import mymodule;
alias MSG = mymodule.MSG;
alias winMSG = core.sys.windows.windows.MSG;


Renamed but non-selective import?

2021-01-12 Thread cc via Digitalmars-d-learn
Is it possible to import all symbols of a module, while renaming 
just one of them?  It seems like doing an import with renaming 
automatically makes it selective.
In the example below, I'd prefer not to have to use the fully 
qualified name for mymodule.MSG every time e.g.:


import core.sys.windows.windows;
import mymodule; // contains a struct named MSG
Error: `core.sys.windows.winuser.MSG` ... conflicts with 
`mymodule.MSG`


vs

import core.sys.windows.windows : winMSG = MSG; // this leaves 
out other symbols

Error: undefined identifier `HWND`
Error: undefined identifier `LPCSTR`



Re: Variadic Struct Parameter

2021-01-12 Thread ryuukk_ via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 18:44:53 UTC, Jonathan Levi wrote:

On Tuesday, 12 January 2021 at 17:46:14 UTC, Q. Schroll wrote:
It's obvious why arrays work, it's the primary use case. I 
have no idea why classes are allowed. That classes are 
allowed, but structs are not, makes no sense to me.


I like the variadic feature for classes, but I wish it worked 
for structs as well, given that structs are value types on the 
stack anyway, the same assembly could have either signature 
(assuming matching argument/struct ordering).


But why does this compile?

```
struct S {/*...*/}

void fun(S s...) {/*...*/}
```
If structs do not work as variadic parameters, why does `fun` 
still compile?



you can do this:

```
import std.stdio;
import core.internal.moving;
import core.memory;

void main()
{
auto a = Data(1);
auto b = Data(2);
auto c = Data(3);

hello(a, b, c);
}

void hello(Data...)(Data args)
{
writeln("n: ", args.length);
foreach (data; args)
writeln(data);
}

struct Data
{
int a = 5;
}
```

this works fine: https://run.dlang.io/is/YA9syo


Re: Variadic Struct Parameter

2021-01-12 Thread Ali Çehreli via Digitalmars-d-learn

On 1/12/21 10:44 AM, Jonathan Levi wrote:

> why does `fun` still compile?

I'm not familiar with that particular syntax, I don't know why it 
compiles, and I don't know why structs are different. :) However, it 
looks very much like the following *slice* syntax:


void fun(S[] s...) {
writeln(s);
}

In that case, the function receives a slice (to an array on the stack; 
so, do not keep a reference to it). Is that what you want?


Ali



Re: Variadic Struct Parameter

2021-01-12 Thread Jonathan Levi via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 17:46:14 UTC, Q. Schroll wrote:
It's obvious why arrays work, it's the primary use case. I have 
no idea why classes are allowed. That classes are allowed, but 
structs are not, makes no sense to me.


I like the variadic feature for classes, but I wish it worked for 
structs as well, given that structs are value types on the stack 
anyway, the same assembly could have either signature (assuming 
matching argument/struct ordering).


But why does this compile?

```
struct S {/*...*/}

void fun(S s...) {/*...*/}
```
If structs do not work as variadic parameters, why does `fun` 
still compile?


Re: properly passing strings to functions? (C++ vs D)

2021-01-12 Thread Q. Schroll via Digitalmars-d-learn

On Monday, 11 January 2021 at 16:53:50 UTC, IGotD- wrote:
I usually use "const string text" because D has no implicit 
declaration of variables. So using "ref" will not create a 
variable. This is contrary to C++ where passing as "const 
std::string &text" has a performance benefit and also C++ 
creates a unnamed variable for you.


Did you consider `in`? It will do that in some time and do it now 
with -preview=in.
If you're using `const`, in almost all cases, `in` will work, 
too, and be better (and shorter).


Re: properly passing strings to functions? (C++ vs D)

2021-01-12 Thread Q. Schroll via Digitalmars-d-learn

On Monday, 11 January 2021 at 14:12:57 UTC, zack wrote:
A beginner question: How to pass strings properly to functions 
in D?
Is there any allocation going on if just use a function as 
"myPrint"? In C++ I have often seen calls where one just passes 
a reference/const reference to a string to avoid allocation.


C++:
void myPrintCPP(const std::string& input){ ... }

D:
void myPrint(string text){ ... }
void myPrintRef(ref string text) { ... }


In D, `string` is an abbreviation for the type immutable(char)[], 
i.e. slice of immutable char. The slice type is a pointer+length 
pair, a (T*, size_t) tuple, it is very lightweight. Using `ref 
T[]` (that includes `ref string` aka `ref immutable(char)[]` is 
the way if you want reassignments or expanding/shrinking of the 
array to be visible to the caller. Since the cost of copying a 
pointer and a length is very low, I'd just use this:


  void myPrint(string text) { ... }

It'll be probably what you want. Since you cannot write the 
immutable characters, if you don't intend to reassign, expand, or 
shrink the string locally, you can use `in string text`.
You can basically only read `in` parameters for information. What 
`in` buys you is that the compiler will figure out the best way 
to pass the object. C++'s const T& will reference always, which 
is worse than a copy for small types. D's `in` will copy if the 
compiler thinks it's cheaper than referencing. Give 
https://dlang.org/changelog/2.094.0.html#preview-in a read, if 
you want details about `in`. Use it when it applies. It also 
documents intent.


Re: Variadic Struct Parameter

2021-01-12 Thread Q. Schroll via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 17:26:15 UTC, Jonathan Levi wrote:

Why is this not working?

```
struct S {
int x;
string y;
}

void fun(S s ...) {


This is intended for arrays and classes, not structs. Using ... 
for something other than arrays and c



fun(S(5,"hi"));


That one should compile...


fun(5,"hi");


and the second one not.

It's obvious why arrays work, it's the primary use case. I have 
no idea why classes are allowed. That classes are allowed, but 
structs are not, makes no sense to me.


Variadic Struct Parameter

2021-01-12 Thread Jonathan Levi via Digitalmars-d-learn

Why is this not working?

```
struct S {
int x;
string y;
}

void fun(S s ...) {
writeln(s);
}

void main() {
fun(S(5,"hi"));
fun(5,"hi");
}
```

Why does `fun` compile if calling it does not?


Re: any chance to get it working on windows xp?

2021-01-12 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 13:51:16 UTC, Imperatorn wrote:

On Tuesday, 12 January 2021 at 12:40:28 UTC, Mike Parker wrote:




Are you asking if anyone patched the binaries and made them 
available as a third-party download?


Yes, or if there are any plans for those changes to go upstream.


I'm unaware of anyone who has done that. And I wouldn't expect 
that sort of thing to make it upstream.


Re: Member variables in method are null when called as delegate from thread

2021-01-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/11/21 8:49 PM, tsbockman wrote:

On Monday, 11 January 2021 at 00:43:00 UTC, Tim wrote:
When MessageService calls the delegate for start, db is null. If I 
call start() in the Foo constructor it works just fine. Am I missing 
something here? Do delegates get called outside of their class 
context? I know I could just pass the db into start but I want to work 
out exactly why this is happening


The compiler and the physical CPU are both allowed to change the order 
in which instructions are executed to something different from what your 
code specifies, as long as the visible, "official" results and effects 
of the chosen order of execution are the same as those of your specified 
code, FROM THE PERSPECTIVE OF THE EXECUTING THREAD.


This is allowed so that the compiler can optimize to minimize negative 
"unofficial" effects such as the passage of time and memory consumption.


However, this re-ordering IS permitted to freely alter the behavior of 
your code from the perspective of OTHER threads. A likely cause of your 
bug is that the write to db by the constructor's thread is being 
committed to memory after the read of db by the MessageService thread.


I don't think this is valid.

1. the compiler MUST NOT reorder the storage of db to after you pass a 
delegate into an opaque function (array allocation).
2. The CPU is not going to reorder, because the memory allocation is 
going to take a global lock anyway (mutex locks should ensure memory 
consistency).


I think something weird is going on, but I don't know what.

In order to RELIABLY fix this kind of problem, you must correctly use 
the only commands which the compiler and CPU are NOT allowed to reorder 
with respect to other threads, namely atomic operations, memory barriers 
and synchronization primitives.


I can't ever imagine creating a thread (which is likely what 
MessageService ctor is doing) to not have a consistent memory with the 
creating thread on construction. Why would the other thread not see the 
same memory when it didn't exist before? The CPU would have to go out of 
its way to make it inconsistent.


-Steve


Re: Member variables in method are null when called as delegate from thread

2021-01-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/11/21 12:26 PM, Arafel wrote:
Thanks for the detailed explanation! I think this mixing of types and 
storage classes makes a very unfortunate combination:


```
import std;

int i = 0;
shared int j = 0;

struct S {
     int i = 0;
     shared int j = 0;
}

S s;

void main() {
     i = 1;
     j = 1;
     s.i = 1;
     s.j = 1;
     spawn(&f);

}

void f() {
     assert(i == 0); // Expected
     assert(j == 1); // Expected
     assert(s.i == 0); // Expected
     assert(s.j == 0); // Wait, what?
}
```

I agree that once you know the inner workings it makes sense, but a 
naïve approach might suggest that `s.j` would be... well, shared, just 
like `j`.


It's definitely confusing, if you don't know what shared means in all 
contexts.


shared as storage -> put in the shared globals
shared as type -> the thing can be shared between threads.

The second meaning does not mean it's automatically shared, just that 
it's shareable.


-Steve


Re: any chance to get it working on windows xp?

2021-01-12 Thread Imperatorn via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 12:40:28 UTC, Mike Parker wrote:

On Tuesday, 12 January 2021 at 10:25:42 UTC, Imperatorn wrote:

https://forum.dlang.org/post/qsgtohsykwldipgng...@forum.dlang.org

On Saturday, 3 October 2020 at 23:14:57 UTC, Drone1h wrote:

On Monday, 18 May 2020 at 05:36:01 UTC, Mike Parker wrote:

[...]


This is not exactly a reply to the original thread, but maybe 
it helps someone who has searched for "Windows XP" in the 
forum and found this discussion.


[...]


Anyone knows if these changes where ever made?



Are you asking if anyone patched the binaries and made them 
available as a third-party download?


Yes, or if there are any plans for those changes to go upstream.


Re: Member variables in method are null when called as delegate from thread

2021-01-12 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/11/21 6:52 PM, Paul Backus wrote:

On Monday, 11 January 2021 at 16:10:49 UTC, Steven Schveighoffer wrote:

There are some... odd rules.

struct S
{

[...]

   immutable int e = 5; // stored in data segment, not per instance!


Are you sure?

struct S
{
     immutable int n = 123;
     this(int n) { this.n = n; }
}

void main()
{
     S s1;
     S s2 = 456;
     assert(s1.n == 123);
     assert(s2.n == 456);
}


Yes, I was sure, but clearly wrong ;)

Hm... I guess it was changed! Deprecated in 2.065 [1] and finally 
changed in 2.067 [2]


Now you need static immutable to make it not part of the instance. Which 
makes sense (score 1 for consistency!)


-Steve

[1] https://dlang.org/changelog/2.065.0.html#staticfields2
[2] https://issues.dlang.org/show_bug.cgi?id=3449


Re: any chance to get it working on windows xp?

2021-01-12 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 10:25:42 UTC, Imperatorn wrote:

https://forum.dlang.org/post/qsgtohsykwldipgng...@forum.dlang.org

On Saturday, 3 October 2020 at 23:14:57 UTC, Drone1h wrote:

On Monday, 18 May 2020 at 05:36:01 UTC, Mike Parker wrote:

[...]


This is not exactly a reply to the original thread, but maybe 
it helps someone who has searched for "Windows XP" in the 
forum and found this discussion.


[...]


Anyone knows if these changes where ever made?



Are you asking if anyone patched the binaries and made them 
available as a third-party download?


Re: I want to create my own Tuple type

2021-01-12 Thread Ola Fosheim Grøstad via Digitalmars-d-learn
Ok, so I now have this, but I think maybe the switch could be 
turned into a static array by an reinterpret cast of 
"&expand[0]"? I would assume the layout would typically be 
"expand_field_0, expand_field_1 etc...



template Tuple(Types...){
template same(){
static foreach (i, dummy; Types) {
static if (i + 1 < Types.length && !is(typeof(same) 
== bool)

   && !is(Types[i] == Types[i + 1])) {
enum bool same = false;
}
}
static if (!is(typeof(same) == bool)) {
enum bool same = true;
}
}

struct Tuple {
Types expand;
alias expand this;

static if (same!()) {
auto opIndex(size_t i) {
switch (i) {
static foreach (j; 0 .. Types.length) {
case j: return this.expand[j];
}
default: assert(0);
}
}
}
}
}




Re: Static constructor

2021-01-12 Thread ludo via Digitalmars-d-learn



NOTE : the entire code we are talking about is in the tiny url in 
my previous post.


On Thursday, 7 January 2021 at 01:55:07 UTC, SealabJaster wrote:

On Wednesday, 6 January 2021 at 17:05:02 UTC, ludo wrote:

...


Using a static class like this seems to mostly be a design 
decision.
So in otherwords, this class is essentially being used as a 
unique namespace for all of the other functions. Another way to 
look at it is just a singleton without a `.instance` getter.


Ok, I agree that ends up being a kind of strange singleton. But 
yes it was D v1 code. Do we agree that the following 
multi-threaded singleton pattern is the proper way as of today, 
instead of this static functions in a non static class (in 
multithreaded environment)?


shared(T) singleton()
{
 static shared T instance;

 if(!instance)
 {
   synchronized
   {
 if(!instance)
 instance = new shared(T)();
   }
 }

 return instance;
}
---



As for some of the other stuff, Associative Array literals in D 
can't actually be used at compile-time (at least, last time I 
tried), so they have to be created inside of the static 
constructor.


OK, I found 
https://dlang.org/spec/hash-map.html#static_initialization

Quote from that doc:
"Static Initialization of AAs
 NOTE: Not yet implemented. "
If I understand, as of today an AA init depends on a runtime 
function for historical reasons. A bit weird for an array indeed 
perfectly known at compile time, but someday some  core language 
contributor will have a look at it, I guess.




Next is the mutex. `Object` is the base class that every class 
in D will implicitly inherit from, like in C# for example. 
Object has a `.monitor` field which is basically just a mutex, 
so is used with multi-threading synchronisation. I find it a 
bit odd that they're just returning an object instead of a 
Mutex (module core.sync.mutex), but I'm sure there's a reason 
why.


If we consider the class from my first post, the comment coming 
with the getMutex func is following in the original code that I 
am "cleaning-up":
"Get an OpenAL mutex to ensure that no two threads ever execute 
OpenAL functionality simultaneously."


But the OpenAL class only has one function (anotherFunc), and as 
you say SealabJaster, it looks odd to use this Object mutex. I 
see two options to replace this mutex thing:
* make the entire class synchronized (writing "synchronized class 
OpenAL")
* make the anotherFunc function synchronized. So just one keyword 
to add!
If I understand well, this will accomplish the goal quoted with 
no further comestics needed! Only one keyword over explicitely 
using object mutex. Am I right?


Thanks



any chance to get it working on windows xp?

2021-01-12 Thread Imperatorn via Digitalmars-d-learn

https://forum.dlang.org/post/qsgtohsykwldipgng...@forum.dlang.org

On Saturday, 3 October 2020 at 23:14:57 UTC, Drone1h wrote:

On Monday, 18 May 2020 at 05:36:01 UTC, Mike Parker wrote:

[...]


This is not exactly a reply to the original thread, but maybe 
it helps someone who has searched for "Windows XP" in the forum 
and found this discussion.


[...]


Anyone knows if these changes where ever made?

Thanks!


Re: Linux shared library loading/linking from C does not invoke (shared) static this

2021-01-12 Thread ichneumwn via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 09:49:46 UTC, Mike Parker wrote:

On Tuesday, 12 January 2021 at 09:31:08 UTC, ichneumwn wrote:



Follow on to my own question: on Linux, with gcc, I have 
created the following file "starter.c" that I inject into my D 
shared library:


  int rt_init(void);
  int rt_term(void);

  // should really check for errors!
  static void __attribute__((constructor)) Dstarter(void) {
rt_init();
  }

  static void __attribute__((destructor)) Dterminator(void) {
rt_term();
  }

That seems to do the trick. Not sure how clean this is?


You should be able to do the same in D with 
`pragma(crt_constructor)` and `pragma(crt_destructor)`:


https://dlang.org/spec/pragma.html#crtctor
https://dlang.org/spec/pragma.html#crtdtor
https://dlang.org/changelog/2.078.0.html#crt-constructor


Perfect, thanks! Interestingly, as I removed the C stub and tried 
the D route, I noticed that just calling rt_init() is enough to 
also get static ~this() to run on exit. In fact then adding 
writeln in a pragma(crt_destructor) function shows that it gets 
called after static ~this().


For anyone stumbling across this thread and looking for the 
import for rt_init/term:


import core.runtime : rt_init, rt_term;



Re: Linux shared library loading/linking from C does not invoke (shared) static this

2021-01-12 Thread ichneumwn via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 09:02:38 UTC, Imperatorn wrote:

On Tuesday, 12 January 2021 at 08:19:45 UTC, ichneumwn wrote:
Where could one file a suggestion for an update to the 
documentation?


In the top right section of the page you can click the "Improve 
this page"-link.


Thanks, I will leave it though. I do not want to mess about and 
write about something I have just learnt in the last hour. That 
could do more damage than good.




Re: Linux shared library loading/linking from C does not invoke (shared) static this

2021-01-12 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 09:31:08 UTC, ichneumwn wrote:



Follow on to my own question: on Linux, with gcc, I have 
created the following file "starter.c" that I inject into my D 
shared library:


  int rt_init(void);
  int rt_term(void);

  // should really check for errors!
  static void __attribute__((constructor)) Dstarter(void) {
rt_init();
  }

  static void __attribute__((destructor)) Dterminator(void) {
rt_term();
  }

That seems to do the trick. Not sure how clean this is?


You should be able to do the same in D with 
`pragma(crt_constructor)` and `pragma(crt_destructor)`:


https://dlang.org/spec/pragma.html#crtctor
https://dlang.org/spec/pragma.html#crtdtor
https://dlang.org/changelog/2.078.0.html#crt-constructor




Re: Linux shared library loading/linking from C does not invoke (shared) static this

2021-01-12 Thread ichneumwn via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 08:19:45 UTC, ichneumwn wrote:

Dear all,

I was trying to invoke some D code from Python and ran into 
issues which I eventually traced back to a simple example on 
the D website itself :


https://dlang.org/articles/dll-linux.html

Particularly the section "Dynamically Loading a D DLL From a C 
Program"


In my case, and indeed already in 2013 
(https://forum.dlang.org/post/yeqyqaaguhngczlnv...@forum.dlang.org), shared static this does not get invoked


I normally use:
LDC - the LLVM D compiler (1.21.0):
  based on DMD v2.091.1 and LLVM 10.0.0   (under Linux)

but I also tried
DMD64 D Compiler v2.095.0

Is the solution suggested in the linked post the "canonical 
way"?


Where could one file a suggestion for an update to the 
documentation?


Cheers!

PS Enjoying my project in D especially how easy it is to get 
the same code to run under windows too


Follow on to my own question: on Linux, with gcc, I have created 
the following file "starter.c" that I inject into my D shared 
library:


  int rt_init(void);
  int rt_term(void);

  // should really check for errors!
  static void __attribute__((constructor)) Dstarter(void) {
rt_init();
  }

  static void __attribute__((destructor)) Dterminator(void) {
rt_term();
  }

That seems to do the trick. Not sure how clean this is?





Re: Member variables in method are null when called as delegate from thread

2021-01-12 Thread Imperatorn via Digitalmars-d-learn

On Monday, 11 January 2021 at 17:26:00 UTC, Arafel wrote:


void f() {
assert(i == 0); // Expected
assert(j == 1); // Expected
assert(s.i == 0); // Expected
assert(s.j == 0); // Wait, what?
}


At first sight this looks unexpected. But I think if you have a 
shared variable inside a struct it will not be TLS.


Re: How build DCD on Windows?

2021-01-12 Thread Imperatorn via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 06:25:09 UTC, evilrat wrote:

On Tuesday, 12 January 2021 at 00:35:41 UTC, Marcone wrote:
Hi, Someone can Help me build exe dcd server and client on 
WIndows? Step by step? Becouse the informations disponible is 
very hard to undestand.


Are you serious?
It's on the first page of their repo under the Setup section
https://code.dlang.org/packages/dcd

just clone the repo, open it up in terminal and run the 
following. it will produce two separate binaries for client and 
server. Yes, that's all.


dub build --build=release --config=client
dub build --build=release --config=server


I agree, the information may not hard to find, but please be 
respectful when answering anyway.


Re: Linux shared library loading/linking from C does not invoke (shared) static this

2021-01-12 Thread Imperatorn via Digitalmars-d-learn

On Tuesday, 12 January 2021 at 08:19:45 UTC, ichneumwn wrote:
Where could one file a suggestion for an update to the 
documentation?


In the top right section of the page you can click the "Improve 
this page"-link.




Linux shared library loading/linking from C does not invoke (shared) static this

2021-01-12 Thread ichneumwn via Digitalmars-d-learn

Dear all,

I was trying to invoke some D code from Python and ran into 
issues which I eventually traced back to a simple example on the 
D website itself :


https://dlang.org/articles/dll-linux.html

Particularly the section "Dynamically Loading a D DLL From a C 
Program"


In my case, and indeed already in 2013 
(https://forum.dlang.org/post/yeqyqaaguhngczlnv...@forum.dlang.org), shared static this does not get invoked


I normally use:
LDC - the LLVM D compiler (1.21.0):
  based on DMD v2.091.1 and LLVM 10.0.0   (under Linux)

but I also tried
DMD64 D Compiler v2.095.0

Is the solution suggested in the linked post the "canonical way"?

Where could one file a suggestion for an update to the 
documentation?


Cheers!

PS Enjoying my project in D especially how easy it is to get the 
same code to run under windows too