excepción de lanzamiento de thread boost “thread_resource_error: resource temporalmente no disponible”

Tengo un código similar al siguiente código

boost::thread myThread unsigned char readbuffer[bignumber]; unsigned char writebuffer[bignumber]; for(int i=0; i<bignumber; ++i){ functiondostuff(); for(int j=0; j<2; ++j){ functiondomorestuff(); myThread = boost::thread(&myClass::myFunction, this, j, i); } } 

myFunction lee de un búfer y escribe en otro. Nunca escribirá en la misma ubicación en el búfer de escritura. ¿Estoy haciendo algo fundamentalmente malo con los hilos aquí? ¿Es malo recorrer una creación de subproceso con el mismo nombre de subproceso? Funciona sin problemas por un tiempo y luego recibo la siguiente excepción.

finalizar llamado después de lanzar una instancia de ‘boost :: exception_detail :: clone_impl>’ what (): boost :: thread_resource_error: Recurso temporalmente no disponible Abortado

¿Qué significa esta excepción? Cualquier idea sería útil.

Hay un límite en la cantidad de hilos que puede crear por proceso.

En Linux, por ejemplo,

 cat /proc/sys/kernel/threads-max 

te dice el máximo actual. El valor predeterminado es el número de páginas de memoria / 4, por lo que en mi sistema es 513785, pero puede ser mucho más bajo en otra caja. Por ejemplo, en mi casilla de servidor de correo (512 mb RAM) es solo 7295.

Usted podría el límite. Pero de hecho eso será inútil porque el sistema operativo no puede progtwigrlos de manera efectiva. Por lo tanto, en su lugar, intente utilizar un grupo de subprocesos.

Oh. PD. detach() -ing he threads ayudará (mucho) con la conservación de recursos. pthreads podría estar bloqueando la creación de subprocesos mucho antes de que se scope el límite del sistema operativo porque necesita asignar un seguimiento general de los subprocesos activos. detach libera (y elimina el error de no unir todos los hilos antes de la salida del progtwig).

ACTUALIZAR Bono de viernes loco: un grupo de subprocesos que escala automáticamente al número de núcleos que tiene su sistema:

 #include  #include  #include  using namespace boost; using namespace boost::phoenix::arg_names; boost::atomic_size_t counter(0ul); class thread_pool { private: mutex mx; condition_variable cv; typedef function job_t; std::deque _queue; thread_group pool; boost::atomic_bool shutdown; static void worker_thread(thread_pool& q) { while (auto job = q.dequeue()) (*job)(); } public: thread_pool() : shutdown(false) { for (unsigned i = 0; i < boost::thread::hardware_concurrency(); ++i) pool.create_thread(bind(worker_thread, ref(*this))); } void enqueue(job_t job) { lock_guard lk(mx); _queue.push_back(std::move(job)); cv.notify_one(); } optional dequeue() { unique_lock lk(mx); namespace phx = boost::phoenix; cv.wait(lk, phx::ref(shutdown) || !phx::empty(phx::ref(_queue))); if (_queue.empty()) return none; auto job = std::move(_queue.front()); _queue.pop_front(); return std::move(job); } ~thread_pool() { shutdown = true; { lock_guard lk(mx); cv.notify_all(); } pool.join_all(); } }; static constexpr size_t bignumber = 1 << 20; class myClass { //unsigned char readbuffer[bignumber]; //unsigned char writebuffer[bignumber]; void functiondostuff() { } void functiondomorestuff() { } thread_pool pool; // uses 1 thread per core public: void wreak_havoc() { std::cout << "enqueuing jobs... " << std::flush; for(size_t i=0; i> 4u) > last) { std::cout << "Progress: " << counter << "/" << (bignumber*2) << "\n"; last = counter >> 4u; } } } 

En primer lugar, no eliminaba explícitamente mis hilos con thread.join () o thread.detach (), por lo que el número total de hilos crecería fuera de control y lanzaría una excepción.

Además, en mi ciclo interno estaba creando dos hilos pero manteniendo solo un mango. Así que perdí el control de 1 hilo en cada iteración del ciclo externo, lo que ocasionó que la cantidad total de hilos creciera más allá del límite prescrito de hilos que causaba la excepción.

Para conservar identificadores únicos para los hilos creados en el ciclo interno, los agregué a un grupo boost :: y usé un myGroup.join_all (). Supongo que también podría haber usado un vector para empujar las manijas y luego abrirlas para unirlas a todas.

 boost::thread_group myThreadGroup unsigned char readbuffer[bignumber]; unsigned char writebuffer[bignumber]; for(int i=0; i