/** * Executes a processes database. * * If XPSPL_EXHAUSTION_PURGE is true processes will be purged once they * reach exhaustion. * * @param object $sig \XPSPL\SIG * @param object $db \XPSPL\database\Processes * * @return void */ private function _processes_execute(SIG $signal, Processes $db) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('%s Process DB Executing %s processes', $db, $db->count())); } $db->reset(); foreach ($db as $_process) { # Always check state first if ($signal->get_state() === STATE_HALTED) { break; } # n+1 constant if ($_process instanceof Processes) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug('Descending into a sub-database executing ' . $_process->count() . ' processes'); } $this->_processes_execute($signal, $_process); } else { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('Executing Process %s', get_class($_process) . ' : ' . $_process)); } $_process->decrement_exhaust(); if (XPSPL_THREAD_SUPPORT && $_process->threads_enabled()) { // DO NOT EXECUTE THE SAME PROCESS WHILE ANOTHER IS RUNNING $_running = False; foreach ($this->active_threads as $_key => $_thread) { if ($_thread[0] === $_process) { $_running = True; } } if ($_running) { continue; } $thread = $_process->get_thread($signal); $this->active_threads[] = [$_process, $thread]; $thread->start(); if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('Starting thread %s %s', end($this->active_threads)[1], get_class($_process) . ' : ' . $_process)); } } else { if (false === $this->_process_exec($signal, $_process->get_function())) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('Halting Signal %s due to false return from %s', $signal, get_class($_process) . ' : ' . $_process)); } $signal->halt(); } } if ($_process->is_exhausted()) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('Process %s Exhausted', get_class($_process) . ' : ' . $_process)); } $db->delete($_process); } } } }