Archived
This forum has been archived. Please start a new discussion on GitHub.
Can not restart thread
Hi,
I just discover the problem which I think is a bug in IceE 1.3.0 (discovered on Linux but I think it is platform independent). Here is the problem description.
I have an instance of my class derived from IceUtil::Thread. In the application I need to start and stop the thread several times during application life cycle. I implemented it with simple bool flag as following:
void MyThread::run()
{
while(!this->shutdown_requested)
// do the job
}
Everything works fine but attempt to start the thread second time (using the same MyThread instance) throws ThreadStartedException.
Looking at the IceUtil::Thread::start(...) function, I can see that this exception throwed if(_started) condition is true. However I did not find the place where _started is set to false if the thread run() function exited. Only _running attribute is changed in _done() function. That is why, second attempt to start the thread throws the exception.
Fortunatelly, _started flag is protected attribute so if I set it to false at the end of my run() function, then everything works fine and I can restart the thread without any problems. I do not see any reasons why the same thread object instance could not be used several times and that is why think that this is a bug. It should be very easy to fix for example by assigning false to _started in _done() function.
Regards,
Andrey.
I just discover the problem which I think is a bug in IceE 1.3.0 (discovered on Linux but I think it is platform independent). Here is the problem description.
I have an instance of my class derived from IceUtil::Thread. In the application I need to start and stop the thread several times during application life cycle. I implemented it with simple bool flag as following:
void MyThread::run()
{
while(!this->shutdown_requested)
// do the job
}
Everything works fine but attempt to start the thread second time (using the same MyThread instance) throws ThreadStartedException.
Looking at the IceUtil::Thread::start(...) function, I can see that this exception throwed if(_started) condition is true. However I did not find the place where _started is set to false if the thread run() function exited. Only _running attribute is changed in _done() function. That is why, second attempt to start the thread throws the exception.
Fortunatelly, _started flag is protected attribute so if I set it to false at the end of my run() function, then everything works fine and I can restart the thread without any problems. I do not see any reasons why the same thread object instance could not be used several times and that is why think that this is a bug. It should be very easy to fix for example by assigning false to _started in _done() function.
Regards,
Andrey.
0
Comments
-
BTW, it looks like Ice (not embedded version) has the similar Thread class implementation and correspondently will behave in the same way as embedded one.0
-
That is by design
See: Threads
"You can start a thread only once; calling start on an already-started thread raises ThreadStartedException."
That is similar to the Java and .NET native thread APIs
Thread (Java 2 Platform SE 5.0)
"It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution. "
Thread.Start Method (System.Threading)
"Once the thread terminates, it cannot be restarted with another call to Start."0 -
Thank you for the explanations! It is probably make sense to introduce consistent thread behaviour across different languages.
Nevertheless, do you think that my workaround by resetting _started flag at the end of run() function has some disadvantages or potential problems in C++?
Thanks,
Andrey.0 -
At first i don't see any problem with your work around, you should lock _stateMutex while assigning _started. And remember to use a new ThreadControl object, as a new thread is still created when you call start.
The Thread class doesn't allow to restart as there isn't such thing on the underlying OS threads, a thread is created, run and exited.
IMO a clear way to do what you want is to separate the work being done from the thread that run it and allow the same work/task to be reused.
Something like:
[PHP]
class Task : public IceUtil::Shared
{
virtual void run() = 0;
};
typedef IceUtil::Handle<Task> TaskPtr;
class MyThread : public IceUtil::Thread
{
MyThread(const TaskPtr& task) : _task(task){}
void run()
{
_task->run()
}
};
TaskPtr t1 = MyCustomTask();
MyThread th1 = MyThread(t1);
th1->start();
...
MyThred th2 = MyThread(t1);
th2->start();
[/PHP]0 -