Можно ли создавать потоки Pthread внутри конструктора?

Я хочу создать пул потоков. У меня есть класс ServerThread.cpp, конструктор которого должен делать что-то вроде этого:

ServerThread::ServerThread()
   {
         for( int i=0 ; i<init_thr_num ; i++ )
         {
              //create a pool of threads
              //suspend them, they will wake up when requests arrive for them to process
         }
   }

Мне было интересно, может ли создание pthreads внутри конструктора вызвать какое-либо неопределенное поведение, которого следует избегать.

Спасибо


person cpp_noname    schedule 29.06.2012    source источник


Ответы (2)


Вы, конечно, можете сделать это в конструкторе, но должны знать о проблеме, которая четко объясняется Скоттом Мейерсом в его книгах «Эффективный / более эффективный C ++».

Короче говоря, его точка зрения заключается в том, что если в конструкторе возникает какое-либо исключение, то ваш полуобеспеченный объект не будет уничтожен. Это приводит к утечкам памяти. Поэтому предложение Мейерса состоит в том, чтобы иметь «легкие» конструкторы, а затем выполнять «тяжелую» работу в init методе, вызываемом после того, как объект был полностью создан.

Этот аргумент не имеет прямого отношения к созданию пула потоков pthread внутри конструктора (в связи с чем вы можете возразить, что исключение не возникнет, если вы просто создадите их, а затем немедленно приостановите их), но является общим соображением о том, что делать в конструкторе. (читайте: передовой опыт).

Еще одно соображение, которое следует сделать, это то, что конструктор не имеет возвращаемого значения. Хотя верно то, что (если не генерируются исключения) вы можете оставить объект в согласованном состоянии, даже если создание потока не удается, возможно, было бы лучше управлять возвращаемым значением с помощью своего рода init или start метода.

Вы также можете прочитать эту ветку на SO по этой теме и этот.

person sergio    schedule 29.06.2012
comment
Это не имеет ничего общего с потоками, и предложение Скотта было в значительной степени заменено более продвинутыми методами: такими вещами, как управление ресурсами базовым классом или членом, которые будут полностью построены до входа в тело конструктора. (В этом случае пул потоков должен быть членом, поэтому его деструктор будет вызываться в случае исключения.) - person James Kanze; 29.06.2012
comment
@James Kanze: в своем ответе я уже отмечал следующее: этот аргумент не имеет прямого отношения к созданию пула потоков pthread внутри конструктора, но связан с передовой практикой. Кроме того, вы подтверждаете как в своем комментарии, так и в своем собственном ответе, что рекомендуется использовать какой-то конкретный метод, чтобы правильно с этим справиться. Метод init, каким бы старым или простым он ни был, - лишь один из таких приемов. В любом случае спасибо за комментарий. - person sergio; 29.06.2012

С строго формальной точки зрения конструктор на самом деле является такой же функцией, как и любая другая, и в этом не должно быть никаких проблем. На практике может возникнуть проблема: потоки могут начать работу до того, как конструктор завершит свою работу. Если потокам для работы требуется полностью сконструированный ServerThread, тогда у вас проблемы. Это часто бывает, когда ServerThread является базовым классом, и потокам необходимо взаимодействовать с производным классом. (Это очень сложная проблема, потому что с наиболее часто используемыми алгоритмами планирования потоков новый поток обычно не начинает выполняться немедленно.)

person James Kanze    schedule 29.06.2012