www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to use globals correctly?

reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
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
Mar 05 2018
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Mar 05 2018
next sibling parent reply Marc <jckj33 gmail.com> writes:
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)...
Mar 05 2018
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Mar 05 2018
parent reply bauss <jj_1337 live.dk> writes:
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.
Mar 06 2018
next sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Mar 06 2018
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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 -- Старый друг лучше новых двух.
Mar 06 2018
prev sibling parent reply =?iso-8859-1?Q?Robert_M._M=FCnch?= <robert.muench saphirion.com> writes:
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
Mar 05 2018
next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Mar 05 2018
prev sibling parent bauss <jj_1337 live.dk> writes:
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.
Mar 05 2018
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, March 06, 2018 11:52:05 H. S. Teoh via Digitalmars-d-learn 
wrote:
 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).
It makes sense whenever it doesn't make sense to have multiple instances of a particular class, and it makes sense to enforce that. As I explained, LocalTime and UTC from std.datetime do that for exactly that reason. Cases like that are rare, but they do exist. However, they also exist rarely enough that it's going to be hard to come up with more examples. I judge whether singletons makes sense on a case-by-case basis. Sometimes, they do make sense, so I wouldn't say that they're necessarily a code smell, but I also completely agree that they rarely make sense. So, I don't disagree that singletons should rarely be used. I just disagree with the idea that they should never be used. And for better or worse, singletons are one of those things that seems to me like it should usually be obvious whether they make sense in a particular case, but that doesn't seem to be true for everyone, otherwise there wouldn't be as much of a dislike of singletons as there seems to be, since they wouldn't come up very often. - Jonathan M Davis
Mar 06 2018