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

tsbockman thomas.bockman at gmail.com
Tue Jan 12 01:49:11 UTC 2021


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.

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.


More information about the Digitalmars-d-learn mailing list