0

Edit: I need to refactor this question, it has too many extraneous components to be clear what my question (which is about C++) is. But anyone who can understand what I am asking please do answer.

I have a class which represents a thread. The threading library I am using, TinyThread++, starts a thread by creating a thread object, however there is no copy constructor for it. Which makes sense.. What would be the meaning of copying a thread anyway?

Previously I had been initializing my thread object E_thread this way:

class E_thread {
    E_threadRoutine m_routine;
    E_thread *m_parent;
    thread m_thread;
public:
    E_thread(void *(void*),void*,E_thread*);
};
E_thread::E_thread(void *func(void*), void *arg, E_thread* parent): 
         m_parent(parent), m_routine(func,arg), 
         m_thread(thread_function_common, &m_routine) 
         {}

Initializing the thread ctor in this fashion works, I am sending the pointer of the E_thread's m_routine member to the thread as its argument. The purpose of m_routine is to keep track of thread specific functionality to pass to the thread itself.

However now I want to make a change where I want to allocate m_routine more carefully. Now m_routine is a pointer and I will need to set it with

m_routine = new E_threadRoutineTypeX(func,arg,etc);

in the E_thread ctor body. But this means I can no longer initialize thread the way I have been. I tried putting

m_thread = thread(thread_function_common,m_routine);

in the body but this copies the thread object which I don't want to do. There's gotta be some syntax for doing this....

Steven Lu
  • 41,389
  • 58
  • 210
  • 364
  • Could I do this? `E_thread::E_thread(void *func(void*), void *arg, E_thread* parent): m_parent(parent), m_routine(new E_threadRoutine(func,arg)), m_thread(thread_function_common, &m_routine) {}` – Steven Lu Jul 09 '11 at 12:40

2 Answers2

1

You can do the following: initialize m_routine using a function, that will return a new E_threadRoutine like so -

m_routine(createThreadRoutine(func, arg))

and have createThreadRoutine return a new E_threadRoutine whichever way you want. Then, you can initialize m_thread with (thread_function_common, m_routine). The use of createThreadRoutine is not mandatory, but it will let you do more than just a new, if that's needed.

For this to work, m_routine must appear before m_thread in the class, otherwise m_thread will be initialize before m_routine is set. See Constructor initialization-list evaluation order.

Community
  • 1
  • 1
Eran
  • 21,632
  • 6
  • 56
  • 89
  • This hadn't occurred to me and it makes sense. Is there no syntax that allows me to initialize in the body itself?? – Steven Lu Jul 09 '11 at 12:57
  • @Steven Lu, I'm not sure I understand your question, but in the initialization list you basically call the constructor of the member variables. If you want to initialize them in the body of E_thread's constructor, just use pointers as your member variables. Then, you could `new` the variables in E_thread's constructor, in whatever order you like, with whatever arguments. – Eran Jul 09 '11 at 13:03
  • Yes, i could do it that way, but I'm bothered by the fact that there doesn't seem to be any provision for allowing initialization of a member variable (by using its constructor) in the body of the constructor. The constructor is, after all, the place where things are meant to be initialized! – Steven Lu Jul 09 '11 at 15:24
1
class E_thread {
    E_threadRoutine* m_routine;
    E_thread *m_parent;
    thread m_thread;
public:
    E_thread(void *(void*),void*,E_thread*);
};
E_thread::E_thread(void *func(void*), void *arg, E_thread* parent) : 
    m_routine(new E_threadRoutineTypeX(func,arg,etc)), 
    m_parent(parent),
    m_thread(thread_function_common, m_routine) 
{}

I also changed your member initialization order, it should always occur in the order the members appear in the class to help avoid errors.

David
  • 27,652
  • 18
  • 89
  • 138