Re: Creating an array of immutable objects

2017-02-14 Thread Jacob Carlborg via Digitalmars-d-learn

On 2017-02-15 01:08, David Zhang wrote:

Thanks for your answers. Out of curiosity though, how could something
like this be done with classes instead?


You mean if FileDesc was a class? It's basically the same. You would need:

Mutable array:

1. Add a constructor which sets all immutable instance variables

For immutable array:

0. Same as above
1. The constructor needs to be declared as "immutable"
2. The instances need to be created with "immutable new"

In the example below, there are two constructors, one for creating 
mutable instances and one for immutable instances. This is only needed 
since I'm creating both a mutable and an immutable array with the same 
type. You only need one kind of constructor if you only need a mutable 
or an immutable array.


module main;

immutable string[] paths = [ "hello", "world" ];

class FileDesc {
immutable string path;
immutable uint index;

this(string path, uint index) immutable
{
this.path = path;
this.index = index;
}

this(string path, uint index)
{
this.path = path;
this.index = index;
}
}

// immutable array created at compile time
immutable _fileDesc = paths
.enumerate!uint
.map!(t => new immutable FileDesc(t.value, t.index))
.array;

// mutable array created at application start using allocators
FileDesc[] _fileDesc2;

auto makeFileDescs(const string[] paths)
{
return paths.enumerate!uint.map!(t => new FileDesc(t.value, t.index));
}

static this()
{
import std.experimental.allocator;
_fileDesc2 = theAllocator.makeArray!(FileDesc)(makeFileDescs(paths));
}


--
/Jacob Carlborg


Re: Creating an array of immutable objects

2017-02-14 Thread David Zhang via Digitalmars-d-learn
Thanks for your answers. Out of curiosity though, how could 
something like this be done with classes instead?


Re: Alias type with different initialiser.

2017-02-14 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, February 13, 2017 22:59:11 John Colvin via Digitalmars-d-learn 
wrote:
> Also, it's
> generally a bad idea to define `.init` for any type as code
> generally expects this to be the compiler-generated property
> (e.g. a value of type Initial!(int, 1) not of type int).

And there's actually a decent chance that at some point, it will become
illegal precisely because of the problems that it causes to allow it.

- Jonathan M Davis



Re: Alias type with different initialiser.

2017-02-14 Thread Bastiaan Veelo via Digitalmars-d-learn

Thanks again.

On Tuesday, 14 February 2017 at 14:08:31 UTC, John Colvin wrote:
I would recommend making `template from(string moduleName)` 
global (maybe in a utils module?), there's no reason for it to 
be a member of Initial.


Yes, I think there is high chance it will be part of Phobos, if 
chosen in favour of DIP 1005.


Re: Mallocator and 'shared'

2017-02-14 Thread Kagamin via Digitalmars-d-learn

On Tuesday, 14 February 2017 at 10:52:37 UTC, Johannes Pfau wrote:
But if the interrupt accesses a variable and a normal function 
accesses the variable as well, the access needs to be 
'volatile' (not cached into a register by the compiler; not 
closely related to this discussion) and atomic, as the 
interrupt might occur in between multiple partial writes. So 
the variable should be shared, although there's no 
multithreading (in the usual sense).


Single publishing (loggers, singletons) doesn't need atomic load: 
https://forum.dlang.org/post/ozssiniwkaghcjvrl...@forum.dlang.org


Re: Policy-based design in D

2017-02-14 Thread TheGag96 via Digitalmars-d-learn
On Tuesday, 14 February 2017 at 10:05:19 UTC, TheFlyingFiddle 
wrote:

(snip)


Oh, I didn't know you could name mixin template instantiations 
like that! Thanks for the tip, that makes things work nicely!


Re: Mallocator and 'shared'

2017-02-14 Thread Moritz Maxeiner via Digitalmars-d-learn

On Tuesday, 14 February 2017 at 14:27:05 UTC, Kagamin wrote:
On Monday, 13 February 2017 at 17:44:10 UTC, Moritz Maxeiner 
wrote:
To be clear: While I might, in general, agree that using 
shared methods only for thread safe methods seems to be a 
sensible restriction, neither language nor compiler require it 
to be so; and absence of evidence of a useful application is 
not evidence of absence.


Right, a private shared method can be a good use case for a 
thread-unsafe shared method.



---
__gshared int f = 0, x = 0;
Object monitor;

// thread 1
synchronized (monitor) while (f == 0);
// Memory barrier required here
synchronized (monitor) writeln(x)

// thread 2
synchronized (monitor) x = 42;
// Memory barrier required here
synchronized (monitor) f = 1;
---


Not sure about this example, it demonstrates a deadlock.


That's beside the point, but I guess I should've clarified the 
"not needed" as "harmful". The point was that memory barriers and 
synchronization are two separate solutions for two separate 
problems and your post scriptum about memory barriers disregards 
that synchronization does not apply to the problem memory 
barriers solve.


On Tuesday, 14 February 2017 at 14:27:05 UTC, Kagamin wrote:


My opinion on the matter of `shared` emitting memory barriers 
is that either the spec and documentation[1] should be updated 
to reflect that sequential consistency is a non-goal of 
`shared` (and if that is decided this should be accompanied by 
an example of how to add memory barriers yourself), or it 
should be implemented.


I'm looking at this in terms of practical consequences and 
useful language features.


So am I.

On Tuesday, 14 February 2017 at 14:27:05 UTC, Kagamin wrote:
What people are supposed to think and do when they see 
"guarantees sequential consistency"? I mean people at large.


That's a documentation issue, however, and is imho not relevant 
to the decision whether one should, or should not emit memory 
barriers. It's only relevant to how the decision is then 
presented to the people at large.


On Tuesday, 14 February 2017 at 14:27:05 UTC, Kagamin wrote:


I agree, message passing is considerably less tricky and 
you're unlikely to shoot yourself in the foot. Nonetheless, 
there are valid use cases where the overhead of MP may not be 
acceptable.


Performance was a reason to not provide barriers. People, who 
are concerned with performance, are even unhappy with virtual 
methods, they won't be happy with barriers on every memory 
access.


You seem to be trying to argue against someone stating memory 
barriers should be emitted automatically, though I don't know why 
you think that's me; You initially stated that
Memory barriers are a bad idea because they don't defend from a 
race condition, but they look like they do
which I rebutted since memory barriers have nothing to do with 
race conditions. Whether memory barriers should automatically 
emitted by the compiler is a separate issue, one on which my 
position btw is that they shouldn't. The current documentation of 
`shared`, however, implies that such an emission (and the related 
sequential consistency) is a goal of `shared` (and just not - 
yet? - implemented) and does not reflect the apparently final 
decision that it's not.




Re: link.exe Error: 'Offset 38C42H Record Type 00C3'

2017-02-14 Thread realNoob via Digitalmars-d-learn

On Tuesday, 14 February 2017 at 14:04:39 UTC, Adam D. Ruppe wrote:

On Tuesday, 14 February 2017 at 09:00:37 UTC, realNoob wrote:
 Error 1: Previous Definition Different : 
_D4xaru8ezFilterFAAyaAyaZAAya


That is saying the function

module xaru;
string[] ezFilter(string[], string);

is defined twice. Could be something weird in your code, but I 
would guess the most likely cause is that there's some old file 
left around from a previous build that is confusing it.


I'd try deleting all the .obj files in the directory then see 
if the build works again.



I don't understand this error. look's like klingon language...


Qapla'


Yes, it is. you're right.
Thank you for your kind reply!


Re: Mallocator and 'shared'

2017-02-14 Thread Johannes Pfau via Digitalmars-d-learn
Am Tue, 14 Feb 2017 14:38:32 +
schrieb Kagamin :

> On Tuesday, 14 February 2017 at 10:52:37 UTC, Johannes Pfau wrote:
> > I remember some discussions about this some years ago and IIRC 
> > the final decision was that the compiler will not magically 
> > insert any barriers for shared variables.  
> 
> It was so some years ago, not sure if it's still so. I suspect 
> automatic barriers come from TDPL book and have roughly the same 
> rationale as autodecoding. They fix something, guess if this 
> something is what you need.

At least this thread is from 2012, so more recent than TDPL:
http://forum.dlang.org/post/k7pn19$bre$1...@digitalmars.com

I'm not sure though if there were any further discussions/decisions
after that discussion.

-- Johannes



Re: Mallocator and 'shared'

2017-02-14 Thread Johannes Pfau via Digitalmars-d-learn
Am Tue, 14 Feb 2017 13:01:44 +
schrieb Moritz Maxeiner :
  
> 
> It's not supposed to. Also, your example does not implement the 
> same semantics as what I posted and yes, in your example, there's 
> no need for memory barriers. In the example I posted, 
> synchronization is not necessary, memory barriers are (and since 
> synchronization is likely to have a significantly higher runtime 
> cost than memory barriers, why would you want to, even if it were 
> possible).
> 

I'll probably have to look up about memory barriers again, I never
really understood when they are necessary ;-)


> >
> > I remember some discussions about this some years ago and IIRC 
> > the final decision was that the compiler will not magically 
> > insert any barriers for shared variables. Instead we have 
> > well-defined intrinsics in std.atomic dealing with this. Of 
> > course most of this stuff isn't implemented (no shared support 
> > in core.sync).
> >
> > -- Johannes  
> 
> Good to know, thanks, I seem to have missed that final decision. 
> If that was indeed the case, then that should be reflected in the 
> documentation of `shared` (including the FAQ).

https://github.com/dlang/dlang.org/pull/1570

I think it's probably somewhere in this thread:

http://forum.dlang.org/post/k7pn19$bre$1...@digitalmars.com

>1. Slapping shared on a type is never going to make algorithms on that
>type work in a concurrent context, regardless of what is done with
>memory barriers. Memory barriers ensure sequential consistency, they
>do nothing for race conditions that are sequentially consistent.
>Remember, single core CPUs are all sequentially consistent, and still
>have major concurrency problems. This also means that having templates
>accept shared(T) as arguments and have them magically generate correct
>concurrent code is a pipe dream.
>
>2. The idea of shared adding memory barriers for access is not going
>to ever work. Adding barriers has to be done by someone who knows what
>they're doing for that particular use case, and the compiler inserting
>them is not going to substitute.
>
>However, and this is a big however, having shared as compiler-enforced
>self-documentation is immensely useful. It flags where and when data
>is being shared.

http://forum.dlang.org/post/mailman.1904.1352922666.5162.digitalmar...@puremagic.com

> Most of the reason for this was that I didn't like the old
> implications of shared, which was that shared methods would at some
> time in the future end up with memory barriers all over the place.
> That's been dropped, [...]


-- Johannes



Re: Mallocator and 'shared'

2017-02-14 Thread Kagamin via Digitalmars-d-learn

On Tuesday, 14 February 2017 at 10:52:37 UTC, Johannes Pfau wrote:
I remember some discussions about this some years ago and IIRC 
the final decision was that the compiler will not magically 
insert any barriers for shared variables.


It was so some years ago, not sure if it's still so. I suspect 
automatic barriers come from TDPL book and have roughly the same 
rationale as autodecoding. They fix something, guess if this 
something is what you need.


Re: Mallocator and 'shared'

2017-02-14 Thread Kagamin via Digitalmars-d-learn
On Monday, 13 February 2017 at 17:44:10 UTC, Moritz Maxeiner 
wrote:
To be clear: While I might, in general, agree that using shared 
methods only for thread safe methods seems to be a sensible 
restriction, neither language nor compiler require it to be so; 
and absence of evidence of a useful application is not evidence 
of absence.


Right, a private shared method can be a good use case for a 
thread-unsafe shared method.



---
__gshared int f = 0, x = 0;
Object monitor;

// thread 1
synchronized (monitor) while (f == 0);
// Memory barrier required here
synchronized (monitor) writeln(x)

// thread 2
synchronized (monitor) x = 42;
// Memory barrier required here
synchronized (monitor) f = 1;
---


Not sure about this example, it demonstrates a deadlock.

My opinion on the matter of `shared` emitting memory barriers 
is that either the spec and documentation[1] should be updated 
to reflect that sequential consistency is a non-goal of 
`shared` (and if that is decided this should be accompanied by 
an example of how to add memory barriers yourself), or it 
should be implemented.


I'm looking at this in terms of practical consequences and useful 
language features. What people are supposed to think and do when 
they see "guarantees sequential consistency"? I mean people at 
large.


I agree, message passing is considerably less tricky and you're 
unlikely to shoot yourself in the foot. Nonetheless, there are 
valid use cases where the overhead of MP may not be acceptable.


Performance was a reason to not provide barriers. People, who are 
concerned with performance, are even unhappy with virtual 
methods, they won't be happy with barriers on every memory access.


Re: Alias type with different initialiser.

2017-02-14 Thread John Colvin via Digitalmars-d-learn
On Tuesday, 14 February 2017 at 11:34:22 UTC, Bastiaan Veelo 
wrote:

On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:

Why not use a constructor instead of static opCall?


I don't know, this comes from 
http://dlang.org/spec/struct.html#dynamic_struct_init. Your 
constructor looks a lot better. Am I missing a test case where 
static opCall would be called, but not the constructor? Why do 
the docs use static opCall?


The docs are just trying to illustrate that opCall is only used 
for initialisation if the initialiser is of a different type. 
Constructors are always used for initialisation if they are 
there, they completely hide static opCall in that context. static 
opCall can return anything of any type, constructors implicitly 
return a reference to `this`. A constructor is the way to 
initialise a type and some code - such as std.conv.emplace - 
actually calls the constructor manually (it's accessible via 
.__ctor) to do so. static opCall doesn't necessarily represent an 
initialiser function, so generic code won't necessarily know to 
use it.


Overall, static opCall is rarely the solution you need.

Also, it's generally a bad idea to define `.init` for any type 
as code generally expects this to be the compiler-generated 
property (e.g. a value of type Initial!(int, 1) not of type 
int).


Thanks. I can't remember what confused me to think that 
typeof(int1.init) had to be int.



enum initial = val;

[...]
static assert(int1.initial == 1); // typeof(int1.initial) 
== int


These lines have no purpose beyond illustration, right?


they check that the implementation does have a member .initial 
and that it is equal to the value we requested as the 
initialiser. It also enforces that it is accessible at 
compile-time.




I now have the following, featuring the novel Scherkl-Nielsen 
self-important lookup:


/**
Creates an type that is mostly $(PARAM T), only with a 
different initial value of $(PARAM val).

*/
struct Initial(T, T val)
{
private T _payload = val;
alias _payload this;

this(T v)
{
_payload = v;
}

// https://dlang.org/blog/2017/02/13/a-new-import-idiom/
private template from(string moduleName)
{
  mixin("import from = " ~ moduleName ~ ";");
}

void toString(scope void delegate(const(char)[]) sink, 
from!"std.format".FormatSpec!char fmt)

{
import std.array : appender;
import std.format : formatValue;
auto w = appender!string();
formatValue(w, _payload, fmt);
sink(w.data);
}
}

unittest
{
alias int1 = Initial!(int, 1);
static assert(int1.init == 1); // typeof(int1.init) == int1

int1 i;
assert(i == 1);
int1 ii = 2;
assert(ii == 2);
assert(ii.init == 1);
assert(int1.init == 1);

void f(int val)
{
assert(val == 1);
}
f(i);

int i0;
assert(i0 == 0);
i = i0;
assert(i == 0);
assert(i.init == 1);
i0 = ii;
assert(i0 == 2);
assert(i0.init == 0);

import std.string;
assert(format("%6d", ii) == " 2");
}


I would recommend making `template from(string moduleName)` 
global (maybe in a utils module?), there's no reason for it to be 
a member of Initial.


Re: link.exe Error: 'Offset 38C42H Record Type 00C3'

2017-02-14 Thread Adam D. Ruppe via Digitalmars-d-learn

On Tuesday, 14 February 2017 at 09:00:37 UTC, realNoob wrote:
 Error 1: Previous Definition Different : 
_D4xaru8ezFilterFAAyaAyaZAAya


That is saying the function

module xaru;
string[] ezFilter(string[], string);

is defined twice. Could be something weird in your code, but I 
would guess the most likely cause is that there's some old file 
left around from a previous build that is confusing it.


I'd try deleting all the .obj files in the directory then see if 
the build works again.



I don't understand this error. look's like klingon language...


Qapla'


Re: Alias type with different initialiser.

2017-02-14 Thread John Colvin via Digitalmars-d-learn
On Tuesday, 14 February 2017 at 10:49:19 UTC, Bastiaan Veelo 
wrote:

On Tuesday, 14 February 2017 at 01:31:10 UTC, John Colvin wrote:

On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:

[ snip ]


sorry, made a typo, that should have been


alias int1 = Initial!(int, 1);
static assert(int1.initial == 1); // typeof(int1.initial) 
== int
static assert(int1.init == 1); // typeof(int1.init) == 
int1


What is the difference between

  alias Initial!(int, 1) int1;

and

  alias int1 = Initial!(int, 1);

? Or was the typo in the comments alone?

Thanks.


just a more modern style. I think the old style would have been 
deprecated if it wasn't for how much old code used it.


Re: Mallocator and 'shared'

2017-02-14 Thread Moritz Maxeiner via Digitalmars-d-learn
On Tuesday, 14 February 2017 at 13:01:44 UTC, Moritz Maxeiner 
wrote:
Of course, I just wanted to point out that Kagamin's post 
scriptum is a simplification I cannot agree with. As a best 
practice? Sure. As a "never do it"? No.


Sorry for the double post, error in the above, please use this 
instead:


Of course, I just wanted to point out that Kagamin's
Thread unsafe methods shouldn't be marked shared, it doesn't 
make sense
is a simplification I cannot agree with. As a best practice? 
Sure. As a "never do it"? No.


Re: Mallocator and 'shared'

2017-02-14 Thread Moritz Maxeiner via Digitalmars-d-learn

On Tuesday, 14 February 2017 at 10:52:37 UTC, Johannes Pfau wrote:
The compiler of course can't require shared methods to be 
thread-safe as it simply can't prove thread-safety in all 
cases. This is like shared/trusted: You are supposed to make 
sure that a function behaves as expected. The compiler will 
catch some easy to detect mistakes (like calling a non-shared 
method from a shared method <=> system method from safe method) 
but you could always use casts, pointers, ... to fool the 
compiler.


You could use the same argument to mark any method as @trusted. 
Yes it's possible, but it's a very bad idea.


Though I do agree that there might be edge cases: In a single 
core, single threaded environment, should an interrupt function 
be marked as shared? Probably not, as no synchronization is 
required when calling the function.


But if the interrupt accesses a variable and a normal function 
accesses the variable as well, the access needs to be 
'volatile' (not cached into a register by the compiler; not 
closely related to this discussion) and atomic, as the 
interrupt might occur in between multiple partial writes. So 
the variable should be shared, although there's no 
multithreading (in the usual sense).


Of course, I just wanted to point out that Kagamin's post 
scriptum is a simplification I cannot agree with. As a best 
practice? Sure. As a "never do it"? No.


On Tuesday, 14 February 2017 at 10:52:37 UTC, Johannes Pfau wrote:

Am Mon, 13 Feb 2017 17:44:10 +
schrieb Moritz Maxeiner :
you'd still need those memory barriers. Also note that the 
synchronization in the above is not needed in terms of 
semantics.


However, if you move you synchronized to the complete sub-code 
blocks barriers are not necessary. Traditional mutex locking is 
basically a superset and is usually implemented using barriers 
AFAIK. I guess your point is we need to define whether shared 
methods guarantee some sort of sequential consistency?


My point in those paragraphs was that synchronization and memory 
barriers solve two different problems that can occur in 
non-sequential programming and because of Kagamin's statement


Memory barriers are a bad idea because they don't defend from a 
race condition
makes no sense (to me). But yes, I do think that the definition 
should have more background /context and not the current "D FAQ 
states `shared` guarantees sequential consistency (not 
implemented)". Considering how many years that has been the state 
I have personally concluded (for myself and how I deal with D) 
that sequential consistency is a non-goal of `shared`, but what's 
a person new to D supposed to think?


On Tuesday, 14 February 2017 at 10:52:37 UTC, Johannes Pfau wrote:


struct Foo
{
shared void doA() {lock{_tmp = "a";}};
shared void doB() {lock{_tmp = "b";}};
shared getA() {lock{return _tmp;}};
shared getB() {lock{return _tmp;}};
}

thread1:
foo.doB();

thread2:
foo.doA();
auto result = foo.getA(); // could return "b"

I'm not sure how a compiler could prevent such 'logic' bugs.


It's not supposed to. Also, your example does not implement the 
same semantics as what I posted and yes, in your example, there's 
no need for memory barriers. In the example I posted, 
synchronization is not necessary, memory barriers are (and since 
synchronization is likely to have a significantly higher runtime 
cost than memory barriers, why would you want to, even if it were 
possible).


On Tuesday, 14 February 2017 at 10:52:37 UTC, Johannes Pfau wrote:
However, I think it should be considered a best practice to 
always make a shared function a self-contained entity so that 
calling any other function in any order does not negatively 
effect the results. Though that might not always be possible.


Yes, that matches what I tried to express.

On Tuesday, 14 February 2017 at 10:52:37 UTC, Johannes Pfau wrote:

Am Mon, 13 Feb 2017 17:44:10 +
schrieb Moritz Maxeiner :
My opinion on the matter of `shared` emitting memory barriers 
is that either the spec and documentation[1] should be updated 
to reflect that sequential consistency is a non-goal of 
`shared` (and if that is decided this should be accompanied by 
an example of how to add memory barriers yourself), or it 
should be implemented. Though leaving it in the current "not 
implemented, no comment / plan on whether/when it will be 
implemented" state seems to have little practical consequence 
- since no one seems to actually work on this level in D - and 
I can thus understand why dealing with that is just not a 
priority.


I remember some discussions about this some years ago and IIRC 
the final decision was that the compiler will not magically 
insert any barriers for shared variables. Instead we have 
well-defined intrinsics in std.atomic dealing with this. Of 
course most of this stuff isn't implemented (no shared support 
in core.sync).


-- Johannes


Good to know, thanks, I seem to have missed 

Re: Alias type with different initialiser.

2017-02-14 Thread Bastiaan Veelo via Digitalmars-d-learn

On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:

Why not use a constructor instead of static opCall?


I don't know, this comes from 
http://dlang.org/spec/struct.html#dynamic_struct_init. Your 
constructor looks a lot better. Am I missing a test case where 
static opCall would be called, but not the constructor? Why do 
the docs use static opCall?


Also, it's generally a bad idea to define `.init` for any type 
as code generally expects this to be the compiler-generated 
property (e.g. a value of type Initial!(int, 1) not of type 
int).


Thanks. I can't remember what confused me to think that 
typeof(int1.init) had to be int.



enum initial = val;

[...]
static assert(int1.initial == 1); // typeof(int1.initial) 
== int


These lines have no purpose beyond illustration, right?


I now have the following, featuring the novel Scherkl-Nielsen 
self-important lookup:


/**
Creates an type that is mostly $(PARAM T), only with a different 
initial value of $(PARAM val).

*/
struct Initial(T, T val)
{
private T _payload = val;
alias _payload this;

this(T v)
{
_payload = v;
}

// https://dlang.org/blog/2017/02/13/a-new-import-idiom/
private template from(string moduleName)
{
  mixin("import from = " ~ moduleName ~ ";");
}

void toString(scope void delegate(const(char)[]) sink, 
from!"std.format".FormatSpec!char fmt)

{
import std.array : appender;
import std.format : formatValue;
auto w = appender!string();
formatValue(w, _payload, fmt);
sink(w.data);
}
}

unittest
{
alias int1 = Initial!(int, 1);
static assert(int1.init == 1); // typeof(int1.init) == int1

int1 i;
assert(i == 1);
int1 ii = 2;
assert(ii == 2);
assert(ii.init == 1);
assert(int1.init == 1);

void f(int val)
{
assert(val == 1);
}
f(i);

int i0;
assert(i0 == 0);
i = i0;
assert(i == 0);
assert(i.init == 1);
i0 = ii;
assert(i0 == 2);
assert(i0.init == 0);

import std.string;
assert(format("%6d", ii) == " 2");
}


Re: Mallocator and 'shared'

2017-02-14 Thread Johannes Pfau via Digitalmars-d-learn
Am Mon, 13 Feb 2017 17:44:10 +
schrieb Moritz Maxeiner :

> > Thread unsafe methods shouldn't be marked shared, it doesn't 
> > make sense. If you don't want to provide thread-safe interface, 
> > don't mark methods as shared, so they will not be callable on a 
> > shared instance and thus the user will be unable to use the 
> > shared object instance and hence will know the object is thread 
> > unsafe and needs manual synchronization.  
> 
> To be clear: While I might, in general, agree that using shared 
> methods only for thread safe methods seems to be a sensible 
> restriction, neither language nor compiler require it to be so; 
> and absence of evidence of a useful application is not evidence 
> of absence.

The compiler of course can't require shared methods to be thread-safe
as it simply can't prove thread-safety in all cases. This is like
shared/trusted: You are supposed to make sure that a function behaves
as expected. The compiler will catch some easy to detect mistakes (like
calling a non-shared method from a shared method <=> system method from
safe method) but you could always use casts, pointers, ... to fool the
compiler.

You could use the same argument to mark any method as @trusted. Yes
it's possible, but it's a very bad idea.

Though I do agree that there might be edge cases: In a single core,
single threaded environment, should an interrupt function be marked as
shared? Probably not, as no synchronization is required when calling
the function.

But if the interrupt accesses a variable and a normal function accesses
the variable as well, the access needs to be 'volatile' (not cached into
a register by the compiler; not closely related to this discussion) and
atomic, as the interrupt might occur in between multiple partial
writes. So the variable should be shared, although there's no
multithreading (in the usual sense).

> you'd still need those memory barriers. Also note that the 
> synchronization in the above is not needed in terms of semantics.

However, if you move you synchronized to the complete sub-code blocks
barriers are not necessary. Traditional mutex locking is basically a
superset and is usually implemented using barriers AFAIK. I guess your
point is we need to define whether shared methods guarantee some sort
of sequential consistency?

struct Foo
{
shared void doA() {lock{_tmp = "a";}};
shared void doB() {lock{_tmp = "b";}};
shared getA() {lock{return _tmp;}};
shared getB() {lock{return _tmp;}};
}

thread1:
foo.doB();

thread2:
foo.doA();
auto result = foo.getA(); // could return "b"

I'm not sure how a compiler could prevent such 'logic' bugs. However, I
think it should be considered a best practice to always make a shared
function a self-contained entity so that calling any other function in
any order does not negatively effect the results. Though that might not
always be possible.

> My opinion on the matter of `shared` emitting memory barriers is 
> that either the spec and documentation[1] should be updated to 
> reflect that sequential consistency is a non-goal of `shared` 
> (and if that is decided this should be accompanied by an example 
> of how to add memory barriers yourself), or it should be 
> implemented. Though leaving it in the current "not implemented, 
> no comment / plan on whether/when it will be implemented" state 
> seems to have little practical consequence - since no one seems 
> to actually work on this level in D - and I can thus understand 
> why dealing with that is just not a priority.

I remember some discussions about this some years ago and IIRC the
final decision was that the compiler will not magically insert any
barriers for shared variables. Instead we have well-defined intrinsics
in std.atomic dealing with this. Of course most of this stuff isn't
implemented (no shared support in core.sync).

-- Johannes



Re: Alias type with different initialiser.

2017-02-14 Thread Bastiaan Veelo via Digitalmars-d-learn

On Tuesday, 14 February 2017 at 01:31:10 UTC, John Colvin wrote:

On Monday, 13 February 2017 at 22:59:11 UTC, John Colvin wrote:

[ snip ]


sorry, made a typo, that should have been


alias int1 = Initial!(int, 1);
static assert(int1.initial == 1); // typeof(int1.initial) 
== int

static assert(int1.init == 1); // typeof(int1.init) == int1


What is the difference between

  alias Initial!(int, 1) int1;

and

  alias int1 = Initial!(int, 1);

? Or was the typo in the comments alone?

Thanks.


Re: Policy-based design in D

2017-02-14 Thread TheFlyingFiddle via Digitalmars-d-learn

On Tuesday, 14 February 2017 at 06:48:33 UTC, TheGag96 wrote:
Tonight I stumbled upon Andrei's concept of policy-based design 
(https://en.wikipedia.org/wiki/Policy-based_design) and tried 
to implement their example in D with the lack of multiple 
inheritance in mind.


https://dpaste.dzfl.pl/adc05892344f (btw, any reason why 
certificate validation on dpaste fails right now?)


The implementation isn't perfect, as I'm not sure how to check 
members of mixin templates so that you  could verify whether 
print() and message() are actually where they should be. How 
would you do that? Is there any use for this kind of thing in 
D, and if so, what would it be? I've hardly dabbled in OOP 
patterns, but the abstraction seems kinda interesting.


Something like this can be used to check if the mixin has a 
specific member:


template hasMixinMember(alias mixin_, string member) {
  enum hasMixinMember = __traits(compiles, () {
  mixin mixin_ mix;
  static assert(__traits(hasMember, mix, member));
  });
}

struct HelloWorld(alias OutputPolicy, alias LanguagePolicy)
  if(hasMixinMember!(OutputPolicy, "print") &&
 hasMixinMember!(LanguagePolicy, "message"))
{
  mixin OutputPolicy;
  mixin LanguagePolicy;

  void run() {
print(message());
  }
}

Note: This method could fail if you do some compile-time 
reflection black magic inside the mixins.




Could also do this:

struct HelloWorld(alias OutputPolicy, alias LanguagePolicy)
{
  mixin OutputPolicy output;
  mixin LanguagePolicy lang;

  void run() {
output.print(lang.message());
  }
}

If "output" / "lang" does not contain a particular member you 
will get a compile time error at the usage point (although it's 
not the best message).




Re: Creating an array of immutable objects

2017-02-14 Thread Jacob Carlborg via Digitalmars-d-learn

On 2017-02-14 01:59, David Zhang wrote:

Hi,

I have a struct with two immutable members, and I want to make an array
of them. How do I to this? I'm using allocators for this.

string[] paths;

struct FileDesc {
immutable string path;
immutable uint index;
}

_fileDesc = /*something*/;

You can't use alloc.makeArray because it requires a range with which to
initialize the array, and while I can produce an array of paths, I don't
know how to merge both a range of paths and indices. Lockstep doesn't work.

I also tried using emplace and an allocated byte array, but it gave me
random values and was (I think) unnecessarily complicated. What am I
missing?


Here are two examples, one creating an immutable array at compile time. 
The other one creating a mutable array at application startup using 
allocators:


import std.algorithm;
import std.range;

immutable string[] paths = [ "hello", "world" ];

struct FileDesc {
immutable string path;
immutable uint index;
}

// immutable array created at compile time
immutable _fileDesc = makeFileDescs(paths).array;

// mutable array created at application start using allocators
FileDesc[] _fileDesc2;

auto makeFileDescs(const string[] paths)
{
return paths.enumerate!uint.map!(t => FileDesc(t.value, t.index));
}

static this()
{
import std.experimental.allocator;
_fileDesc2 = theAllocator.makeArray!FileDesc(makeFileDescs(paths));
}

--
/Jacob Carlborg


link.exe Error: 'Offset 38C42H Record Type 00C3'

2017-02-14 Thread realNoob via Digitalmars-d-learn

Hello.

I got a problem this:

[LDC(ldmd2)] -- Success.

C:\MyFolders\src>ldmd2 --version
LDC - the LLVM D compiler (1.1.0):
  based on DMD v2.071.2 and LLVM 3.9.1
  built with LDC - the LLVM D compiler (1.1.0)
  Default target: x86_64-pc-windows-msvc
  Host CPU: amdfam10
  http://dlang.org - http://wiki.dlang.org/LDC

... skip ...

C:\MyFolders\src>ldmd2 xaru.d -Dddocs
xaru.d(169): Deprecation: module core.stdc.wchar_ is not 
accessible here, perhaps add 'static import core.stdc.wchar_;'
Using Visual C++: C:\Program Files (x86)\Microsoft Visual Studio 
14.0\VC




[DMD] -- Fail!

C:\MyFolders\src>dmd --version
DMD32 D Compiler v2.072.2
Copyright (c) 1999-2016 by Digital Mars written by Walter Bright

C:\MyFolders\src>dmd xaru.d -Dddocs
xaru.d(60): Deprecation: Implicit string concatenation is 
deprecated, use 
"\uc624\ud1a0\ucf54\ub178\ucf54+\uc5d4\uc194\ub85c\uc9c0," ~

"36" instead
xaru.d(169): Deprecation: module core.stdc.wchar_ is not 
accessible here, perhaps add 'static import core.stdc.wchar_;'

OPTLINK (R) for Win32  Release 8.00.17
Copyright (C) Digital Mars 1989-2013  All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
xaru.obj(xaru)  Offset 38C42H Record Type 00C3
 Error 1: Previous Definition Different : 
_D4xaru8ezFilterFAAyaAyaZAAya

Error: linker exited with status 344806024


I don't understand this error. look's like klingon language...