Local static variables must have unique names within a function's scope.

2018-01-19 Thread tipdbmp via Digitalmars-d-learn

The following seems to work in C++, but errors in D, why is that?

int foo(int* num) {
{
static int x = 10;
x += 1;
*num += x;
}

{
static int x = 20; // error: foo.x is already defined in 
another scope in foo

x += 2;
*num += x;
}

return 0;
}

https://dlang.org/spec/function.html#local-static-variables



Re: Local static variables must have unique names within a function's scope.

2018-01-19 Thread Simen Kjærås via Digitalmars-d-learn

On Friday, 19 January 2018 at 11:02:01 UTC, tipdbmp wrote:
The following seems to work in C++, but errors in D, why is 
that?


int foo(int* num) {
{
static int x = 10;
x += 1;
*num += x;
}

{
static int x = 20; // error: foo.x is already defined 
in another scope in foo

x += 2;
*num += x;
}

return 0;
}

https://dlang.org/spec/function.html#local-static-variables


19.17.1.3 explains the fact that they need to have unique names, 
but doesn't provide a reason. Mostly, it's just a bad idea - it's 
very easy for a person reading the code after you've written it 
to get the two x's mixed up.


--
  Simen


Re: Local static variables must have unique names within a function's scope.

2018-01-19 Thread tipdbmp via Digitalmars-d-learn
Mostly, it's just a bad idea - it's very easy for a person 
reading the code after you've written it to get the two x's 
mixed up.


// example from: 19.17.1.3
void main()
{
{ static int x; }
{ static int x; } // error
{ int i; }
{ int i; } // ok
}

I don't really see how the 'static' storage class would make 2 
variables with the same name in different scopes "easier to mix 
up" compared to 2 variables with the same name in different 
scopes but declared without the 'static' keyword.




Program exiting from thread with infinite loop

2018-01-19 Thread Chris M. via Digitalmars-d-learn
I have the following that is supposed to pull and store info from 
a server every five minutes. It works if I move the body of 
deviceDownloader into main(). However when I try to spawn it in 
another thread it runs the function and then ends once it's done, 
like it's ignoring the while(true). I tried with std.parallelism, 
core.thread, vibe.d's concurrency library, but get the same 
result every time. Any idea how to better accomplish this?



import std.net.curl;
import device;
import std.datetime.systime;
impor std.concurrency;

void deviceDownloader()
{
auto APIServer = HTTP();
APIServer.addRequestHeader("X-Auth-Token:", AuthToken);
APIServer.onProgress = delegate int(size_t dl, size_t dln, 
size_t ul, size_t uln)

{
if (dl != 0)
write("Progress: downloaded ", dln, " of ", dl, "\r");

return 0;
};

while (true)
{
auto currentTime = Clock.currTime;
if (currentTime.minute % 5 == 0 && currentTime.second == 
0)
retrieveDevices(URL, APIServer); // info retrieved 
and stored here

}
}

void main()
{
spawn(&deviceDownloader);
}


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 19 January 2018 at 17:05:44 UTC, Chris M. wrote:
However when I try to spawn it in another thread it runs the 
function and then ends once it's done, like it's ignoring the 
while(true).



It is probably terminating the child threads when the main one 
ends. Might help to have the main wait until the child dies too.


But why are you putting it in a thread anyway? If the main is 
doing nothing than just waiting, might as well just keep the 
logic in there.


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Chris M. via Digitalmars-d-learn

On Friday, 19 January 2018 at 17:17:28 UTC, Adam D. Ruppe wrote:

On Friday, 19 January 2018 at 17:05:44 UTC, Chris M. wrote:
However when I try to spawn it in another thread it runs the 
function and then ends once it's done, like it's ignoring the 
while(true).



It is probably terminating the child threads when the main one 
ends. Might help to have the main wait until the child dies too.


I tried putting an infinite loop inside main() as well, didn't 
seem to help. I'm guessing there's probably a better way to make 
the main thread wait? I'm pretty new to threads and whatnot.


But why are you putting it in a thread anyway? If the main is 
doing nothing than just waiting, might as well just keep the 
logic in there.


It'll be doing other things, this is just the first thing I've 
implemented.


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Ali Çehreli via Digitalmars-d-learn

On 01/19/2018 09:46 AM, Chris M. wrote:

> I tried putting an infinite loop inside main() as well, didn't seem to
> help.

Another reason is an exception thrown in the child thread. If the 
exception is not caught, it will terminate the child thread and the main 
will not know anything about it. I have something about that here:



http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.exception,%20concurrency

> I'm guessing there's probably a better way to make the main thread
> wait?

std.core.thread_joinAll is a way but you would want to tell the other 
thread to terminate first.


  https://dlang.org/phobos/core_thread.html#.thread_joinAll

So, instead of while(true), try while(someCondition). In that case the 
main thread sets the condition e.g. by sending a message and then joins.


Ali



Re: Local static variables must have unique names within a function's scope.

2018-01-19 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Jan 19, 2018 at 02:16:24PM +, tipdbmp via Digitalmars-d-learn wrote:
> > Mostly, it's just a bad idea - it's very easy for a person reading
> > the code after you've written it to get the two x's mixed up.
> 
> // example from: 19.17.1.3
> void main()
> {
> { static int x; }
> { static int x; } // error
> { int i; }
> { int i; } // ok
> }
> 
> I don't really see how the 'static' storage class would make 2
> variables with the same name in different scopes "easier to mix up"
> compared to 2 variables with the same name in different scopes but
> declared without the 'static' keyword.

I think this is more an implementational quirk than any deliberate
decision on variable names being "easier to mix up".  A static variable
currently mangles to a combination of the function name and variable
name, so if there are multiple static variables with the same name,
their mangled names would collide.

OTOH, it would really suck if non-static variable names can't be reused
in nested scopes, because it would mean you have to invent new names
for, say, loop variables for every loop in the same function:

void func(int[100] a, int[100] b) {
foreach (i; 0 .. 100) { a[i] = i; }
foreach (i; 0 .. 100) { b[i] = i; } // this would fail
}

Fortunately this is not the case.  However, the static variable case is
annoying, and it's actually one case of a larger problem:

void main() {
foreach (i; 0 .. 10) {
struct S {
int x;
}
auto s = S(i);
}
foreach (i; 11 .. 20) {
struct S { // < this is line 9
int y;
}
auto s = S(i);
}
}

The compiler says:

test.d(9): Error: declaration S is already defined in another scope in 
main

even though the respective scopes of the declarations are disjoint. IMO,
this is a needless, arbitrary restriction. Worse yet, the compiles ICEs
after this, so I filed a bug:

https://issues.dlang.org/show_bug.cgi?id=18266


T

-- 
Latin's a dead language, as dead as can be; it killed off all the Romans, and 
now it's killing me! -- Schoolboy


Re: Local static variables must have unique names within a function's scope.

2018-01-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/19/18 1:11 PM, H. S. Teoh wrote:


Fortunately this is not the case.  However, the static variable case is
annoying, and it's actually one case of a larger problem:

void main() {
foreach (i; 0 .. 10) {
struct S {
int x;
}
auto s = S(i);
}
foreach (i; 11 .. 20) {
struct S { // < this is line 9
int y;
}
auto s = S(i);
}
}

The compiler says:

test.d(9): Error: declaration S is already defined in another scope in 
main

even though the respective scopes of the declarations are disjoint. IMO,
this is a needless, arbitrary restriction. Worse yet, the compiles ICEs
after this, so I filed a bug:

https://issues.dlang.org/show_bug.cgi?id=18266


Related: https://issues.dlang.org/show_bug.cgi?id=17653

-Steve


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Chris M. via Digitalmars-d-learn

On Friday, 19 January 2018 at 18:18:31 UTC, Ali Çehreli wrote:

On 01/19/2018 09:46 AM, Chris M. wrote:

> I tried putting an infinite loop inside main() as well,
didn't seem to
> help.

Another reason is an exception thrown in the child thread. If 
the exception is not caught, it will terminate the child thread 
and the main will not know anything about it. I have something 
about that here:



http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.exception,%20concurrency

> I'm guessing there's probably a better way to make the main
thread
> wait?

std.core.thread_joinAll is a way but you would want to tell the 
other thread to terminate first.


  https://dlang.org/phobos/core_thread.html#.thread_joinAll

So, instead of while(true), try while(someCondition). In that 
case the main thread sets the condition e.g. by sending a 
message and then joins.


Ali


I'm not sure what's going on. I've tried all sorts of things from 
your link, it just runs the function once and exits every time. 
There aren't any exceptions being thrown from the thread.


That robot example is basically exactly what I'm doing, and yet 
even that doesn't seem to resolve it.


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Chris M. via Digitalmars-d-learn

On Friday, 19 January 2018 at 20:35:14 UTC, Chris M. wrote:

On Friday, 19 January 2018 at 18:18:31 UTC, Ali Çehreli wrote:

On 01/19/2018 09:46 AM, Chris M. wrote:

> I tried putting an infinite loop inside main() as well,
didn't seem to
> help.

Another reason is an exception thrown in the child thread. If 
the exception is not caught, it will terminate the child 
thread and the main will not know anything about it. I have 
something about that here:



http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.exception,%20concurrency

> I'm guessing there's probably a better way to make the main
thread
> wait?

std.core.thread_joinAll is a way but you would want to tell 
the other thread to terminate first.


  https://dlang.org/phobos/core_thread.html#.thread_joinAll

So, instead of while(true), try while(someCondition). In that 
case the main thread sets the condition e.g. by sending a 
message and then joins.


Ali


I'm not sure what's going on. I've tried all sorts of things 
from your link, it just runs the function once and exits every 
time. There aren't any exceptions being thrown from the thread.


That robot example is basically exactly what I'm doing, and yet 
even that doesn't seem to resolve it.


What I tried

import std.net.curl;
import device;
import std.datetime.systime;
impor std.concurrency;

void deviceDownloader()
{
auto APIServer = HTTP();
APIServer.addRequestHeader("X-Auth-Token:", AuthToken);
APIServer.onProgress = delegate int(size_t dl, size_t dln, 
size_t ul, size_t uln)

{
if (dl != 0)
write("Progress: downloaded ", dln, " of ", dl, "\r");

return 0;
};

while (true)
{
auto currentTime = Clock.currTime;
if (currentTime.minute % 5 == 0 && currentTime.second == 
0)
retrieveDevices(URL, APIServer); // info retrieved 
and stored here

ownerTid.send("tmp");
}
}

void main()
{
spawn(&deviceDownloader);

while (true)
{
auto msg = receiveOnly!string();
}
}


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/19/18 12:05 PM, Chris M. wrote:
I have the following that is supposed to pull and store info from a 
server every five minutes. It works if I move the body of 
deviceDownloader into main(). However when I try to spawn it in another 
thread it runs the function and then ends once it's done, like it's 
ignoring the while(true). I tried with std.parallelism, core.thread, 
vibe.d's concurrency library, but get the same result every time. Any 
idea how to better accomplish this?



import std.net.curl;
import device;
import std.datetime.systime;
impor std.concurrency;

void deviceDownloader()
{
     auto APIServer = HTTP();
     APIServer.addRequestHeader("X-Auth-Token:", AuthToken);
     APIServer.onProgress = delegate int(size_t dl, size_t dln, size_t 
ul, size_t uln)

     {
     if (dl != 0)
     write("Progress: downloaded ", dln, " of ", dl, "\r");


What is this call doing? You aren't importing std.stdio, so it can't be 
D's normal write call.


-Steve


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Chris M. via Digitalmars-d-learn
On Friday, 19 January 2018 at 20:43:18 UTC, Steven Schveighoffer 
wrote:

On 1/19/18 12:05 PM, Chris M. wrote:

[...]


What is this call doing? You aren't importing std.stdio, so it 
can't be D's normal write call.


-Steve


It is, left out the import on accident.

I commented out the call to retrieveDevices, and now it's 
working, so at least I'm zoning in a bit. Appreciate all the help 
so far though.


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Steven Schveighoffer via Digitalmars-d-learn

On 1/19/18 3:54 PM, Chris M. wrote:

On Friday, 19 January 2018 at 20:43:18 UTC, Steven Schveighoffer wrote:

On 1/19/18 12:05 PM, Chris M. wrote:

[...]


What is this call doing? You aren't importing std.stdio, so it can't 
be D's normal write call.


-Steve


It is, left out the import on accident.

I commented out the call to retrieveDevices, and now it's working, so at 
least I'm zoning in a bit. Appreciate all the help so far though.


Hm... noticed you missed a 't' here as well:

impor std.concurrency;

It helps if you post actual working (or reproducing in any case) code. 
I've seen so many posts on this forum where people re-type their code in 
the post instead of copy-pasting, and then inadvertently leave out a 
major hint leading to the actual issue :)


-Steve


Re: Program exiting from thread with infinite loop

2018-01-19 Thread Ali Çehreli via Digitalmars-d-learn

On 01/19/2018 12:40 PM, Chris M. wrote:
> it just runs the function once and exits every time.

I would still put the following try+catch block around the whole logic:

void deviceDownloader()
{
try {
// ... existing contents of the function ...
} catch (Exception exc) {
writeln("Error: ", exc.msg);
} catch (Error err) {
writeln("Unrecoverable error: ", err.msg);
}
}

Another thing to use it to start the program under a debugger and look 
at how many threads it has. If the program is called "deneme", on the 
console:


 gdb deneme

Then, inside gdb:

run
Ctrl-C
info threads

That command lists two threads for me.

Ali



Re: Program exiting from thread with infinite loop

2018-01-19 Thread Chris M. via Digitalmars-d-learn
On Friday, 19 January 2018 at 21:01:51 UTC, Steven Schveighoffer 
wrote:

On 1/19/18 3:54 PM, Chris M. wrote:
On Friday, 19 January 2018 at 20:43:18 UTC, Steven 
Schveighoffer wrote:

On 1/19/18 12:05 PM, Chris M. wrote:

[...]


What is this call doing? You aren't importing std.stdio, so 
it can't be D's normal write call.


-Steve


It is, left out the import on accident.

I commented out the call to retrieveDevices, and now it's 
working, so at least I'm zoning in a bit. Appreciate all the 
help so far though.


Hm... noticed you missed a 't' here as well:

impor std.concurrency;

It helps if you post actual working (or reproducing in any 
case) code. I've seen so many posts on this forum where people 
re-type their code in the post instead of copy-pasting, and 
then inadvertently leave out a major hint leading to the actual 
issue :)


-Steve


Might have happened here.

I left out two lines from main() that were for initializing a 
database because I didn't think they were relevant, then I 
realized the database was only being initialized in the main 
thread and not the one I was spawning. retrieveDevices() tried to 
access it and got a segfault (which I was ignoring because I was 
already getting a segfault from something else from before I put 
in threading). Should have been a red flag, but I moved the 
database initialization into the thread and it's working now.


Cannot initialize associative array

2018-01-19 Thread rumbu via Digitalmars-d-learn
According to this 
(https://dlang.org/spec/hash-map.html#static_initialization) this 
is correct static initialization for AA:



immutable RoundingMode[string] ibmRounding =
[
">" : RoundingMode.towardPositive,
"<" : RoundingMode.towardNegative,
"0" : RoundingMode.towardZero,
"=0": RoundingMode.tiesToEven,
"=^": RoundingMode.tiesToAway
];


Error: non-constant expression `[">":cast(RoundingMode)2, 
"<":cast(RoundingMode)3, "0":cast(RoundingMode)4, 
"=0":cast(RoundingMode)0, "=^":cast(RoundingMode)1]`			


RoundingMode is an enum.


Re: Cannot initialize associative array

2018-01-19 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 19 January 2018 at 23:16:19 UTC, rumbu wrote:
According to this 
(https://dlang.org/spec/hash-map.html#static_initialization) 
this is correct static initialization for AA:


That only works inside a function, and, ironically, only if the 
variable is not `static`...


I believe this is technically an implementation shortcoming - it 
is supposed to work in a static context too, but it isn't 
implemented. But regardless, right now, you need to do it in a 
function (or a static constructor) right now.


You can separate declaration from initialization on module-level 
like so:


immutable RoundingMode[string] ibmRounding;
shared static this() {
  ibmRounding =
  [
 ">" : RoundingMode.towardPositive,
 "<" : RoundingMode.towardNegative,
 "0" : RoundingMode.towardZero,
 "=0": RoundingMode.tiesToEven,
 "=^": RoundingMode.tiesToAway
  ];
}


Re: Cannot initialize associative array

2018-01-19 Thread rumbu via Digitalmars-d-learn

On Friday, 19 January 2018 at 23:27:06 UTC, Adam D. Ruppe wrote:

On Friday, 19 January 2018 at 23:16:19 UTC, rumbu wrote:
According to this 
(https://dlang.org/spec/hash-map.html#static_initialization) 
this is correct static initialization for AA:


That only works inside a function, and, ironically, only if the 
variable is not `static`...


I believe this is technically an implementation shortcoming - 
it is supposed to work in a static context too, but it isn't 
implemented. But regardless, right now, you need to do it in a 
function (or a static constructor) right now.


You can separate declaration from initialization on 
module-level like so:


immutable RoundingMode[string] ibmRounding;
shared static this() {
  ibmRounding =
  [
 ">" : RoundingMode.towardPositive,
 "<" : RoundingMode.towardNegative,
 "0" : RoundingMode.towardZero,
 "=0": RoundingMode.tiesToEven,
 "=^": RoundingMode.tiesToAway
  ];
}


Thank you Adam, just figured out myself the same solution, but I 
didn't expect to have a static constructor in main.d. I thought 
static constructors are meant to be used in imported modules. 
Thanks again.




Re: Local static variables must have unique names within a function's scope.

2018-01-19 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, January 19, 2018 10:11:36 H. S. Teoh via Digitalmars-d-learn 
wrote:
> Fortunately this is not the case.  However, the static variable case is
> annoying, and it's actually one case of a larger problem:
>
>   void main() {
>   foreach (i; 0 .. 10) {
>   struct S {
>   int x;
>   }
>   auto s = S(i);
>   }
>   foreach (i; 11 .. 20) {
>   struct S { // < this is line 9
>   int y;
>   }
>   auto s = S(i);
>   }
>   }
>
> The compiler says:
>
>   test.d(9): Error: declaration S is already defined in another scope in
> main
>
> even though the respective scopes of the declarations are disjoint. IMO,
> this is a needless, arbitrary restriction. Worse yet, the compiles ICEs
> after this, so I filed a bug:
>
>   https://issues.dlang.org/show_bug.cgi?id=18266

This limitation gets especially annoying when you start doing stuff like
generating tests using static foreach. In those cases, any helper types or
functions that you have can't be inside the static foreach. To an extent,
you can get around it using a templates outside of the static foreach, but
it's still annoying.

- Jonathan M Davis



Re: Using Postgres connection functions

2018-01-19 Thread Joe via Digitalmars-d-learn

On Saturday, 13 January 2018 at 05:28:17 UTC, Joe wrote:
Going beyond the connection, there are various other libpq 
functions that use a similar pattern of values passed using 
multiple parallel C arrays, e.g.,


   PGresult *PQexecParams(PGconn *conn,
   const char *command,
   int nParams,
   const Oid *paramTypes,
   const char * const *paramValues,
   const int *paramLengths,
   const int *paramFormats,
   int resultFormat);

Each of the `paramXxxxs' arguments are arrays (Oid is an alias 
for uint).

[...]


Focusing on the above function, suppose the first two parameter 
arrays are defined in a C program as:


Oid paramTypes[] = {23, 25};
char *paramValues[] = {"1", "abcde"};

which could be expressed in D as:

Oid [] paramTypes = [23, 25];
string [] paramValues = ["1", "abcde"];

I know the paramTypes could be passed as null, letting PG deduce 
the data types but suppose we have some reason to accumulate 
types, etc., in D slices.  I know the paramValues can be 
manipulated in a manner similar to the one shown in my first 
post, namely something like this:


   extern(C) char * [2] pvs;
   foreach (i, val; paramValues)
   pvs[i] = cast(char *)toStringz(val);

And then use "cast(const char **)pvs" for the paramValues 
argument. The only feedback that I received that was explicit to 
this approach was in response to my initial post, in which Adam 
D. Ruppe said that what I did was "decent".


So I have two lingering doubts:

1. Is malloc() the only way to allocate the arrays, either of 
Oid's, int's or char *'s, for passing to the libpq functions?  
IOW, isn't there a way to take advantage of D's 'new' (and thus 
the GC)?


2. How to convert a slice of Oid's or int's to an array of 
pointers suitable by processing by the libpq C function?  A 
technique similar to the previous one seems to work, e.g.,


extern(C) Oid [2] pts;
foreach (i, typ; paramTypes)
pts[i] = typ;

But I'm not sure if it's really working (when I mistakenly had a 
* in the pts declaration, at one point it also seemed to work).


Re: Using Postgres connection functions

2018-01-19 Thread Adam D. Ruppe via Digitalmars-d-learn

On Saturday, 20 January 2018 at 04:09:01 UTC, Joe wrote:

   extern(C) char * [2] pvs;
   foreach (i, val; paramValues)
   pvs[i] = cast(char *)toStringz(val);

And then use "cast(const char **)pvs" for the paramValues 
argument.


A slight improvement here that removes the need for any casts 
(and the extern(C) is useless here btw) is to just define it as 
const(char)*:


const(char) * [2] pvs;
foreach (i, val; paramValues)
pvs[i] = toStringz(val);

Then you can call the argument with plain `pvs.ptr` instead of 
casting it. Though, make sure you remember the null at the end 
too!


1. Is malloc() the only way to allocate the arrays, either of 
Oid's, int's or char *'s, for passing to the libpq functions?  
IOW, isn't there a way to take advantage of D's 'new' (and thus 
the GC)?


const(char)*[] pvs = new const(char)*[](size_here);
// could also have been `auto pvs = ...;` btw

// then still pass it to pqFunc(pvs.ptr)
// the .ptr gets the char** out of it.


Just double check the documentation of any C function you pass it 
to to make sure it doesn't explicitly say you must malloc it. 
Some C functions will try to free() the pointer you pass it, or 
may hold on to it. D's GC can't see pointers C functions keep, so 
 it might try to free that array any time after the local 
variable `pvs` in D goes out of scope.



2. How to convert a slice of Oid's or int's to an array of 
pointers suitable by processing by the libpq C function?


Same as above. The general pattern is:

C_Type[] name = new C_Type[](requested_size);
// pass as `name.ptr`. This becomes a C_Type*


Just again, remember requested_size needs to include the null 
terminator when C requires it, so a +1 might be helpful.


And also, no need for extern(C). That's more for function 
declarations/pointers or maybe global variables C needs to be 
able to see.


But I'm not sure if it's really working (when I mistakenly had 
a * in the pts declaration, at one point it also seemed to 
work).


Oh yikes, that would have been undefined behavior there. So [x] 
on a pointer will just access memory past it - just like in C - 
and might sometimes work, might sometimes overwrite other memory 
(in your case, it probably overwrote some other local variable on 
the stack), or, best case scenario really, might cause a 
segmentation fault or access violation.