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.

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.
  • xdm
    xdm La Coruña, Spain
    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."
  • 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.
  • xdm
    xdm La Coruña, Spain
    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]
  • xdm wrote: »
    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.
    Right. It definitely make sense. Thank you very much for the good suggestion!

    Regards,
    Andrey.