Thread overview
How to use core.thread.Thread
Jul 16, 2015
aki
Jul 16, 2015
maarten van damme
Jul 16, 2015
aki
Jul 16, 2015
maarten van damme
Jul 16, 2015
Daniel Kozák
Jul 17, 2015
aki
Jul 17, 2015
byron
Jul 17, 2015
aki
Jul 16, 2015
byron
Jul 16, 2015
byron
July 16, 2015
I can't resolve the compile errors:

import core.thread;
class DerivedThread : Thread {
	int count = 0;
	this() {
		super(&run);
	}
	private void run() {
		inc();	//testThread.d(8): Error: shared method testThread.DerivedThread.inc is not callable using a non-shared object
	}
	synchronized void inc() {
		++count;	//testThread.d(11): Deprecation: read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(this.count, 1) instead.
	}
}
void main() {
	auto thr = new DerivedThread();
	thr.start();
	thr.inc();	//testThread.d(17): Error: shared method testThread.DerivedThread.inc is not callable using a non-shared object
	thr.join();
}


1. Should I declare thr as shared? But
	auto thr = new shared DerivedThread();
does not resolve it.

2. Why "++count" cause an error? I think it is safe because
it is marked as synchronized. If it is forced to use atomicOp
all the time, it's painful.

3. Are there any tutorials about using Thread class?

Aki.

July 16, 2015
Have you checked out std.parallelism and std.concurrency?

2015-07-16 9:57 GMT+02:00 aki via Digitalmars-d-learn < digitalmars-d-learn@puremagic.com>:

> I can't resolve the compile errors:
>
> import core.thread;
> class DerivedThread : Thread {
>         int count = 0;
>         this() {
>                 super(&run);
>         }
>         private void run() {
>                 inc();  //testThread.d(8): Error: shared method
> testThread.DerivedThread.inc is not callable using a non-shared object
>         }
>         synchronized void inc() {
>                 ++count;        //testThread.d(11): Deprecation:
> read-modify-write operations are not allowed for shared variables. Use
> core.atomic.atomicOp!"+="(this.count, 1) instead.
>         }
> }
> void main() {
>         auto thr = new DerivedThread();
>         thr.start();
>         thr.inc();      //testThread.d(17): Error: shared method
> testThread.DerivedThread.inc is not callable using a non-shared object
>         thr.join();
> }
>
>
> 1. Should I declare thr as shared? But
>         auto thr = new shared DerivedThread();
> does not resolve it.
>
> 2. Why "++count" cause an error? I think it is safe because it is marked as synchronized. If it is forced to use atomicOp all the time, it's painful.
>
> 3. Are there any tutorials about using Thread class?
>
> Aki.
>
>


July 16, 2015
On Thu, 16 Jul 2015 07:57:10 +0000
aki via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:

> I can't resolve the compile errors:
> 
> import core.thread;
> class DerivedThread : Thread {
> 	int count = 0;
> 	this() {
> 		super(&run);
> 	}
> 	private void run() {
> 		inc();	//testThread.d(8): Error: shared method
> testThread.DerivedThread.inc is not callable using a non-shared
> object
> 	}
> 	synchronized void inc() {
> 		++count;	//testThread.d(11): Deprecation:
> read-modify-write operations are not allowed for shared variables.
> Use core.atomic.atomicOp!"+="(this.count, 1) instead.
> 	}
> }
> void main() {
> 	auto thr = new DerivedThread();
> 	thr.start();
> 	thr.inc();	//testThread.d(17): Error: shared method
> testThread.DerivedThread.inc is not callable using a non-shared
> object
> 	thr.join();
> }
> 
> 
> 1. Should I declare thr as shared? But
> 	auto thr = new shared DerivedThread();
> does not resolve it.
> 
> 2. Why "++count" cause an error? I think it is safe because it is marked as synchronized. If it is forced to use atomicOp all the time, it's painful.
> 
> 3. Are there any tutorials about using Thread class?
> 
> Aki.
> 

import core.thread;
class DerivedThread : Thread {
    shared int count = 0;
    __gshared int count2 = 0;
    this() {
        super(&run);
    }
    private void run() {
        inc();
        inc2();
    }
    void inc() {
        import core.atomic;
        atomicOp!"+="(this.count, 1);
    }

    void inc2() {
        synchronized {
            ++count2;
        }
    }
}
void main() {
    auto thr = new DerivedThread();
    thr.start();
    thr.inc();
    thr.inc2();
    thr.join();
}
July 16, 2015
On Thursday, 16 July 2015 at 08:21:26 UTC, maarten van damme wrote:
> Have you checked out std.parallelism and std.concurrency?

I know std.concurrency to use spawn. If I cannot use Thread,
I'll implement by spawn. But want to try Thread class because
it seems similar to Java's Thread class.
I don't know std.parallelism. It seems for the different case.

Aki.

July 16, 2015
You can certainly use thread but in most use cases, concurrency or
parallelism will accomplish the same in a much saner/safer way. (they're
wrappers around core.thread anyway).
Don't know of any tutorials about core.thread, about the other two you can
find help here : http://ddili.org/ders/d.en/

2015-07-16 11:24 GMT+02:00 aki via Digitalmars-d-learn < digitalmars-d-learn@puremagic.com>:

> On Thursday, 16 July 2015 at 08:21:26 UTC, maarten van damme wrote:
>
>> Have you checked out std.parallelism and std.concurrency?
>>
>
> I know std.concurrency to use spawn. If I cannot use Thread,
> I'll implement by spawn. But want to try Thread class because
> it seems similar to Java's Thread class.
> I don't know std.parallelism. It seems for the different case.
>
> Aki.
>
>


July 16, 2015
On Thursday, 16 July 2015 at 07:57:13 UTC, aki wrote:
> I can't resolve the compile errors:
>
> import core.thread;
> class DerivedThread : Thread {
> 	int count = 0;
> 	this() {
> 		super(&run);
> 	}
> 	private void run() {
> 		inc();	//testThread.d(8): Error: shared method testThread.DerivedThread.inc is not callable using a non-shared object
> 	}
> 	synchronized void inc() {
> 		++count;	//testThread.d(11): Deprecation: read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!"+="(this.count, 1) instead.
> 	}
> }
> void main() {
> 	auto thr = new DerivedThread();
> 	thr.start();
> 	thr.inc();	//testThread.d(17): Error: shared method testThread.DerivedThread.inc is not callable using a non-shared object
> 	thr.join();
> }
>
>
> 1. Should I declare thr as shared? But
> 	auto thr = new shared DerivedThread();
> does not resolve it.
>
> 2. Why "++count" cause an error? I think it is safe because
> it is marked as synchronized. If it is forced to use atomicOp
> all the time, it's painful.
>
> 3. Are there any tutorials about using Thread class?
>
> Aki.



If I remember a synchronized method requires "this" to be shared, you should be fine using a synchronized block in the method for non-shared instances.  But using atomicOp will avoid a lock.

void inc() {
  synchronized {
		++count;
  }
}

You are locking on this object instance by default
July 16, 2015
On Thursday, 16 July 2015 at 21:48:06 UTC, byron wrote:
> On Thursday, 16 July 2015 at 07:57:13 UTC, aki wrote:
>> [...]
>
>
>
> If I remember a synchronized method requires "this" to be shared, you should be fine using a synchronized block in the method for non-shared instances.  But using atomicOp will avoid a lock.
>
> void inc() {
>   synchronized {
> 		++count;
>   }
> }
>
> You are locking on this object instance by default

Also this is from Andrie's book
http://www.informit.com/articles/article.aspx?p=1609144
July 17, 2015
On Thursday, 16 July 2015 at 09:17:47 UTC, Daniel Kozák wrote:
> class DerivedThread : Thread {
>     shared int count = 0;
> }

I thought shared is only for whole of the object.
    auto thr = new DerivedThread();
Here, "thr" is not shared but it's member thr.count is shared?
But if it's not shared, thr object referred by main thread and
"this" reference of DerivedThread.run() are different?
What happen if there are both shared and unshared member exists?

class DerivedThread : Thread {
    shared int count = 0;
    int foo = 0;
}

Umm. I can't imagine what's the memory layout of this object.

July 17, 2015
On Friday, 17 July 2015 at 07:56:48 UTC, aki wrote:
> On Thursday, 16 July 2015 at 09:17:47 UTC, Daniel Kozák wrote:
>> class DerivedThread : Thread {
>>     shared int count = 0;
>> }
>
> I thought shared is only for whole of the object.
>     auto thr = new DerivedThread();
> Here, "thr" is not shared but it's member thr.count is shared?
> But if it's not shared, thr object referred by main thread and
> "this" reference of DerivedThread.run() are different?
> What happen if there are both shared and unshared member exists?
>
> class DerivedThread : Thread {
>     shared int count = 0;
>     int foo = 0;
> }
>
> Umm. I can't imagine what's the memory layout of this object.

Since I have yet to use or see anyone use shared in a useful way I avoid it.  But I normally think of it like const (not immutable).  Shared wont change the memory layout (last time I checked) its purpose is meant to help you write correct threaded code, ie make sure you synchronize access to it, its not synced for you.  You should read the chapter from Andrie's book.

There is also a lot of good stuff in the std lib the helps avoid doing things manually.
July 17, 2015
On Friday, 17 July 2015 at 14:14:41 UTC, byron wrote:
> Since I have yet to use or see anyone use shared in a useful way I avoid it.
It's one way to avoid it. So, you mean you always use send/receive
when you need threading?

I did small test to know the memory layout.

import core.atomic;
int foo;
shared int sfoo;
class DerivedThread : Thread {
    int count;
    shared int scount;
    this() {
        super(&run);
    }
    private void run() {
        inc();
        writefln("at thread: foo=%s, &foo=%s, sfoo=%s, &sfoo=%s", foo, &foo, sfoo, &sfoo);
        writefln("at thread: count=%s, &count=%s, scount=%s, &scount=%s", count, &count, scount, &scount);
    }
    void inc() {
        ++foo;
        atomicOp!"+="(sfoo, 1);
        ++count;
        atomicOp!"+="(scount, 1);
    }
}
void main() {
    auto thr = new DerivedThread();
    thr.start();
    thr.inc();
    thr.join();
    writefln("  at main: foo=%s, &foo=%s, sfoo=%s, &sfoo=%s", foo, &foo, sfoo, &sfoo);
    writefln("  at main: count=%s, &count=%s, scount=%s, &scount=%s", thr.count, &thr.count, thr.scount, &thr.scount);
}

at thread: foo=1, &foo=A33580, sfoo=2, &sfoo=5541E4
at thread: count=2, &count=240178, scount=2, &scount=24017C
  at main: foo=1, &foo=984B28, sfoo=2, &sfoo=5541E4
  at main: count=2, &count=240178, scount=2, &scount=24017C

That means Thread object "thr" is always shared while
global foo is not shared because it has different memory location.
In my understanding, shared is not only checking something at compile time,
but also it affects on the memory layout.

Aki.