Jump to page: 1 2
Thread overview
How to use globals correctly?
Mar 05, 2018
Robert M. Münch
Mar 05, 2018
Marc
Mar 06, 2018
bauss
Mar 06, 2018
Jonathan M Davis
Mar 06, 2018
H. S. Teoh
Mar 05, 2018
Robert M. Münch
Mar 05, 2018
bauss
Mar 06, 2018
Jonathan M Davis
March 05, 2018
Hi, I'm feeling a bit dumb but anway...


For hacking prototypes I mostly create a class to store all kind of values. Then I create one global instance of this class and use it everywhere. Pseudocode looks like this:

class myClass {
	myMemb1;
	myMembN;
	this(){...}
}

__gshared myClass myObj;

main() {
	myObj = new myClass();
	func1();
	...
}

func1(){
	myObj.myMemb1 = ...
}

If I use VisualD and add a watch on myObj, I don't see anything just a "identifier myObj is undefined". Not sure if this is because of some threads running (using the D RX framework).

So, some questions:

1. Are myMemb1..N TLS or __gshared as well?

2. How to best implement a simple global to keep track of values (with support for threads)?


-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

March 05, 2018
On 3/5/18 1:35 PM, Robert M. Münch wrote:

> If I use VisualD and add a watch on myObj, I don't see anything just a "identifier myObj is undefined". Not sure if this is because of some threads running (using the D RX framework).

Can't answer your visual D questions...

> 
> So, some questions:
> 
> 1. Are myMemb1..N TLS or __gshared as well?

No, they are on the heap. Only the reference is __gshared. But effectively it is __gshared, since you can reach those items via the global `myObj`.

> 2. How to best implement a simple global to keep track of values (with support for threads)?

shared is the best mechanism, and you don't have to make it a class, it can be a struct.

This is only if you are using it as POD (plain old data). If you want to have methods, shared kind of sucks.

But this at least tells the type system that it's shared between threads. __gshared does not, it just sticks it in global space, but pretends it's not shared data.

-Steve
March 05, 2018
On Monday, 5 March 2018 at 18:57:01 UTC, Steven Schveighoffer wrote:
> On 3/5/18 1:35 PM, Robert M. Münch wrote:
>
>> If I use VisualD and add a watch on myObj, I don't see anything just a "identifier myObj is undefined". Not sure if this is because of some threads running (using the D RX framework).
>
> Can't answer your visual D questions...
>
>> 
>> So, some questions:
>> 
>> 1. Are myMemb1..N TLS or __gshared as well?
>
> No, they are on the heap. Only the reference is __gshared. But effectively it is __gshared, since you can reach those items via the global `myObj`.
>
>> 2. How to best implement a simple global to keep track of values (with support for threads)?
>
> shared is the best mechanism, and you don't have to make it a class, it can be a struct.
>
> This is only if you are using it as POD (plain old data). If you want to have methods, shared kind of sucks.
>
> But this at least tells the type system that it's shared between threads. __gshared does not, it just sticks it in global space, but pretends it's not shared data.
>
> -Steve

Can __gshared be used instead of static in the singleton pattern? I, comming from C++, ignorantly, have never used _gshared so I went to static instead of (being static also means thread-safe, as far I know)...
March 05, 2018
On 2018-03-05 18:57:01 +0000, Steven Schveighoffer said:

> On 3/5/18 1:35 PM, Robert M. Münch wrote:
> 
>> 1. Are myMemb1..N TLS or __gshared as well?
> 
> No, they are on the heap. Only the reference is __gshared. But effectively it is __gshared, since you can reach those items via the global `myObj`.

Ok, that was my idea. And am I right, that I don't need any special syntax, just: myObj.myMemb


>> 2. How to best implement a simple global to keep track of values (with support for threads)?
> 
> Shared is the best mechanism, and you don't have to make it a class, it can be a struct. This is only if you are using it as POD (plain old data).

Ok, in my case I have some methods as well (but maybe can be avoided).

> If you want to have methods, shared kind of sucks. But this at least tells the type system that it's shared between threads.

Why does it suck?

> __gshared does not, it just sticks it in global space, but pretends it's not shared data.

Ok, so this is the really hackish solution...

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

March 05, 2018
On 3/5/18 2:39 PM, Robert M. Münch wrote:
> On 2018-03-05 18:57:01 +0000, Steven Schveighoffer said:
> 
>> On 3/5/18 1:35 PM, Robert M. Münch wrote:
>>
>>> 1. Are myMemb1..N TLS or __gshared as well?
>>
>> No, they are on the heap. Only the reference is __gshared. But effectively it is __gshared, since you can reach those items via the global `myObj`.
> 
> Ok, that was my idea. And am I right, that I don't need any special syntax, just: myObj.myMemb

Yes. Like I said, __gshared means it's global, but it's not typed as shared. So the compiler will let you do anything you want.


>> If you want to have methods, shared kind of sucks. But this at least tells the type system that it's shared between threads.
> 
> Why does it suck?

Because you can't call shared methods on a non-shared object, and vice versa. Once you start putting more complex data types inside a class/struct that is shared, you start not being able to use them. If you're just storing strings and integers, it's probably ok.

>> __gshared does not, it just sticks it in global space, but pretends it's not shared data.
> 
> Ok, so this is the really hackish solution...
> 

__gshared is for those who "know what they are doing". There is more exposure to race conditions, and there is a LOT of code that assumes if something isn't typed as shared, it's not shared. __gshared is kind of a lie in that case, and you can potentially run into problems.

If you're doing simple things, it can possibly be OK, especially if it's just for debugging.

-Steve
March 05, 2018
On Monday, 5 March 2018 at 19:39:35 UTC, Robert M. Münch wrote:
> On 2018-03-05 18:57:01 +0000, Steven Schveighoffer said:
>> If you want to have methods, shared kind of sucks. But this at least tells the type system that it's shared between threads.
>
> Why does it suck?

Because your code will become very verbose and you'll end up casting shared away to do stuff.

Basically you won't be able to do anything that isn't in a synchronized context and such your code will either have synchronized everywhere or you'll cast away shared.

Personally I never use shared, because it's just such a bother.
March 05, 2018
On 3/5/18 2:25 PM, Marc wrote:
> 
> Can __gshared be used instead of static in the singleton pattern? I, comming from C++, ignorantly, have never used _gshared so I went to static instead of (being static also means thread-safe, as far I know)...

static in D is thread safe, because it's thread-local. __gshared is shared between threads, so it's not thread safe, but has the exact same type as just static data.

Can you use it for singleton? Sure, classic singleton is shared between threads. But using thread-local data, you can solve the singleton problem in a better way:

https://wiki.dlang.org/Low-Lock_Singleton_Pattern

Note, it still uses __gshared, which means it doesn't protect you from race conditions when you actually USE the singleton object. This means you need some synchronization inside the methods.

-Steve
March 06, 2018
On Monday, 5 March 2018 at 19:51:33 UTC, Steven Schveighoffer wrote:
> On 3/5/18 2:25 PM, Marc wrote:
>> 
>> Can __gshared be used instead of static in the singleton pattern? I, comming from C++, ignorantly, have never used _gshared so I went to static instead of (being static also means thread-safe, as far I know)...
>
> static in D is thread safe, because it's thread-local. __gshared is shared between threads, so it's not thread safe, but has the exact same type as just static data.
>
> Can you use it for singleton? Sure, classic singleton is shared between threads. But using thread-local data, you can solve the singleton problem in a better way:
>
> https://wiki.dlang.org/Low-Lock_Singleton_Pattern
>
> Note, it still uses __gshared, which means it doesn't protect you from race conditions when you actually USE the singleton object. This means you need some synchronization inside the methods.
>
> -Steve

Singletons are always smelly code tbh.

Especially in D with thread-local storage.

I can't think of a situation where you truly need singletons in D.
March 06, 2018
On Tuesday, March 06, 2018 18:34:34 bauss via Digitalmars-d-learn wrote:
> On Monday, 5 March 2018 at 19:51:33 UTC, Steven Schveighoffer
>
> wrote:
> > On 3/5/18 2:25 PM, Marc wrote:
> >> Can __gshared be used instead of static in the singleton pattern? I, comming from C++, ignorantly, have never used _gshared so I went to static instead of (being static also means thread-safe, as far I know)...
> >
> > static in D is thread safe, because it's thread-local. __gshared is shared between threads, so it's not thread safe, but has the exact same type as just static data.
> >
> > Can you use it for singleton? Sure, classic singleton is shared between threads. But using thread-local data, you can solve the singleton problem in a better way:
> >
> > https://wiki.dlang.org/Low-Lock_Singleton_Pattern
> >
> > Note, it still uses __gshared, which means it doesn't protect you from race conditions when you actually USE the singleton object. This means you need some synchronization inside the methods.
> >
> > -Steve
>
> Singletons are always smelly code tbh.
>
> Especially in D with thread-local storage.
>
> I can't think of a situation where you truly need singletons in D.

I confess that I've never really understood why some folks dislike singletons so much, but then again, I've only rarely found cases where I thought that they made sense, and I gather that some folks out there use the singleton pattern way too much (I've heard it suggested that it's because it was one of the few design patterns from the design pattern book that was easy). In fact, one of my coworkers was telling me at one point about how someone had argued to him about how a "doubleton" pattern made sense, which just seems crazy to me, but I've found that a disturbingly large percentage of programmers are not what I would consider competent.

I think that the singleton pattern should be used when it really makes sense to use it, but in most cases, there's no reason to restrict the type to a singleton. And I expect that the dislike for singletons comes from them being used far too often when it clearly made no sense.

The one place that I can think of that I've used singletons in the last decade or so is with the LocalTime and UTC classes for time zones (both in std.datetime and in the C++ version that I wrote for work at one point). Having multiple instances of those classes made no sense and would have been pointlessly inefficient. But at the moment, that's the only case I can think of where I've used singletons. They just don't make sense very often.

- Jonathan M Davis

March 06, 2018
On Tue, Mar 06, 2018 at 11:46:04AM -0700, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Tuesday, March 06, 2018 18:34:34 bauss via Digitalmars-d-learn wrote:
[...]
> > Singletons are always smelly code tbh.
> >
> > Especially in D with thread-local storage.
> >
> > I can't think of a situation where you truly need singletons in D.
> 
> I confess that I've never really understood why some folks dislike singletons so much, but then again, I've only rarely found cases where I thought that they made sense, and I gather that some folks out there use the singleton pattern way too much (I've heard it suggested that it's because it was one of the few design patterns from the design pattern book that was easy).
[...]

To me, a singleton is a symptom of excessive dogmatic adherence to the OO religion where Everything Must Be A Class No Matter What. When there can only be one of something, it's clearly no longer a *class*, but is either a module, a global variable, or a (set of) global function(s).

I'm curious to know what are the few cases where you think a singleton made sense, where it wouldn't be more appropriately implemented as a module, global variable, or global function(s).


T

-- 
Старый друг лучше новых двух.
« First   ‹ Prev
1 2