www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - dont understand this

reply collerblade <collerblade gmail.com> writes:
fellow D programmers

I would like to ask a question! I would like to create a class, 
which works in a separated thread, while the class exisit. This 
is important. I want to kill/terminate/stop the third whenn the 
class get cleared. Thas what i got so far. This is what i got so 
far (very easy solution):

class MyClass {
	public:
		this() {
			Thread thread=new Thread(&threadFunc);
			running=true;
			thread.start();
		}
		
		~this() {
			writeln(someVariable);
			running=false;
		}
		
	private:
		bool running=false;
		int someVariable=1;
		
		void threadFunc() {
			while(running) {
				someVariable++;
			}
		}
}

Becouse core.thread.Thread doesnt have any stop,pause,therminate 
method i have to stop the thread by myself (with the help of the 
running variable). The problem is: this ISNT WORKING. The reason 
is: the destructor never gets called, so the thread runs forever 
(application didnt exit). So the GC finds somewhere a pointer to 
the class's instance memory (which is ok i think, becouse i use 
delegate to create the thread).
But imagagine this: when i change the running variable to static, 
everything works as expected, and the app frees and closes 
normally. Why is the running variable is different from the other 
someVariable??
Before u ask:
- "shared bool running" doesnt works, only static.
- Tried to keep a reference of the Thread as a local variable, 
result is the same
- i tried 1000 times the code on 2 different PC, result is the 
same (no random pointer somewhere)
- i use latest LDC

Obviously, i want to avoid a static running variable, my class 
can have multiple instances.

Ty Collerblade
Sep 24 2016
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 25/09/2016 10:24 AM, collerblade wrote:
 fellow D programmers

 I would like to ask a question! I would like to create a class, which
 works in a separated thread, while the class exisit. This is important.
 I want to kill/terminate/stop the third whenn the class get cleared.
 Thas what i got so far. This is what i got so far (very easy solution):

 class MyClass {
     public:
         this() {
             Thread thread=new Thread(&threadFunc);
             running=true;
             thread.start();
         }

         ~this() {
             writeln(someVariable);
             running=false;
         }

     private:
         bool running=false;
         int someVariable=1;

         void threadFunc() {
             while(running) {
                 someVariable++;
             }
         }
 }

 Becouse core.thread.Thread doesnt have any stop,pause,therminate method
 i have to stop the thread by myself (with the help of the running
 variable). The problem is: this ISNT WORKING. The reason is: the
 destructor never gets called, so the thread runs forever (application
 didnt exit). So the GC finds somewhere a pointer to the class's instance
 memory (which is ok i think, becouse i use delegate to create the thread).
 But imagagine this: when i change the running variable to static,
 everything works as expected, and the app frees and closes normally. Why
 is the running variable is different from the other someVariable??
 Before u ask:
 - "shared bool running" doesnt works, only static.
 - Tried to keep a reference of the Thread as a local variable, result is
 the same
 - i tried 1000 times the code on 2 different PC, result is the same (no
 random pointer somewhere)
 - i use latest LDC

 Obviously, i want to avoid a static running variable, my class can have
 multiple instances.

 Ty Collerblade
threadFunc contains a reference to MyClass in the form of the 'this' pointer and so the GC sees this and never deallocates the MyClass instance to begin with.
Sep 24 2016
next sibling parent reply Meta <jared771 gmail.com> writes:
On Saturday, 24 September 2016 at 21:56:38 UTC, rikki cattermole 
wrote:
 threadFunc contains a reference to MyClass in the form of the 
 'this' pointer and so the GC sees this and never deallocates 
 the MyClass instance to begin with.
Not to mention that destructors are not guaranteed to ever be called for classes and heap-allocated structs.
Sep 24 2016
parent reply collerblade <collerblade gmail.com> writes:
On Sunday, 25 September 2016 at 04:25:59 UTC, Meta wrote:
 On Saturday, 24 September 2016 at 21:56:38 UTC, rikki 
 cattermole wrote:
 threadFunc contains a reference to MyClass in the form of the 
 'this' pointer and so the GC sees this and never deallocates 
 the MyClass instance to begin with.
Not to mention that destructors are not guaranteed to ever be called for classes and heap-allocated structs.
Do i have to do a stop() function myself?
Sep 24 2016
parent collerblade <collerblade gmail.com> writes:
 Do i have to do a stop() function myself?
Ok i did a stop() function and i called when my class is not needed any more. But guess what: It doesnt stops the thread. My head is starts to blow up. class ReplicatorServer: Replicator { public: this() { Thread thread=new Thread(&threadFunc); running=true; thread.start(); } void stop() { running=false; writeln("STOPPED"); } private: bool running=false; int someVariable=1; void threadFunc() { while(running) { someVariable++; //Thread.yield(); } } } Is threre something i dont understand with the concept here?? Becouse when i call Thread.yield() (in the threadFunc) repeatly, the class exists as normal. Is running a thread local variable (their address is the same..)
Sep 24 2016
prev sibling parent reply collerblade <collerblade gmail.com> writes:
 threadFunc contains a reference to MyClass in the form of the 
 'this' pointer and so the GC sees this and never deallocates 
 the MyClass instance to begin with.
Yes i am a ware about that fact, but when i set "running" to static, the solution WORKS. That is what the question is.
Sep 24 2016
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/25/16 1:48 AM, collerblade wrote:
 threadFunc contains a reference to MyClass in the form of the 'this'
 pointer and so the GC sees this and never deallocates the MyClass
 instance to begin with.
Yes i am a ware about that fact, but when i set "running" to static, the solution WORKS. That is what the question is.
There is a misunderstanding here. It works because a static variable is *NOT* shared between threads. i.e., make running static, then remove the set to false in the destructor, and you still will have the thread exit. You cannot make a thread function that uses a delegate of a thread, which contains a pointer to that thread, and then expect the GC to kill the thread. I know what you are trying to do, but I don't think you can do it with D's Thread objects. What you want to do is use a reference counter, and run the thread as long as the reference count is greater than 1. Then store your state in that object. You can probably learn how to do this by reading the code for std.typecons.RefCounted. -Steve
Sep 27 2016