void TntnetImpl::run() { log_debug("worker-process"); _stop = false; if (_listeners.empty()) throwRuntimeError("no listeners defined"); log_debug(_listeners.size() << " listeners"); if (_listeners.size() >= _minthreads) { log_warn("at least one more worker than listeners needed - set MinThreads to " << _listeners.size() + 1); _minthreads = _listeners.size() + 1; } if (_maxthreads < _minthreads) { log_warn("MaxThreads < MinThreads - set MaxThreads = MinThreads = " << _minthreads); _maxthreads = _minthreads; } // initialize worker-process // SIGPIPE must be ignored ::signal(SIGPIPE, SIG_IGN); // create worker-threads log_info("create " << _minthreads << " worker threads"); for (unsigned i = 0; i < _minthreads; ++i) { log_debug("create worker " << i); Worker* s = new Worker(*this); s->create(); } // create poller-thread log_debug("start poller thread"); _pollerthread.start(); log_debug("start timer thread"); cxxtools::AttachedThread timerThread(cxxtools::callable(*this, &TntnetImpl::timerTask)); timerThread.start(); { cxxtools::MutexLock lock(allTntnetInstancesMutex); allRunningTntnetInstances.insert(this); } // mainloop cxxtools::Mutex mutex; while (!_stop) { { cxxtools::MutexLock lock(mutex); _queue.noWaitThreads.wait(lock); } if (_stop) break; if (Worker::getCountThreads() < _maxthreads) { log_info("create workerthread"); Worker* s = new Worker(*this); s->create(); } else log_info("max worker-threadcount " << _maxthreads << " reached"); if (TntConfig::it().threadStartDelay > 0) usleep(TntConfig::it().threadStartDelay.totalUSecs()); } log_info("stopping TntnetImpl"); { cxxtools::MutexLock lock(allTntnetInstancesMutex); allRunningTntnetInstances.erase(this); } log_info("stop listener"); for (listeners_type::iterator it = _listeners.begin(); it != _listeners.end(); ++it) (*it)->terminate(); log_info("stop poller thread"); _poller.doStop(); _pollerthread.join(); log_info("stop timer thread"); timerThread.join(); if (Worker::getCountThreads() > 0) { log_info("wait for " << Worker::getCountThreads() << " worker threads to stop"); while (Worker::getCountThreads() > 0) { log_debug("wait for worker threads to stop; " << Worker::getCountThreads() << " left"); usleep(100); } } log_debug("destroy listener"); for (listeners_type::iterator it = _listeners.begin(); it != _listeners.end(); ++it) delete *it; _listeners.clear(); HttpReply::postRunCleanup(); HttpRequest::postRunCleanup(); log_info("all threads stopped"); }
int main( int argc, const char* argv[]) { int argi = 1; int nofThreads = -1; for (; argi < argc && argv[argi][0] == '-'; ++argi) { if (0==std::strcmp( argv[argi], "--")) { ++argi; break; } else if (0==std::strcmp( argv[argi], "-h") || 0==std::strcmp( argv[argi], "--help")) { std::cerr << "Usage: testRequestTransactionMap [-h,-V] <nofIterations>" << std::endl; return 0; } else if (0==std::strcmp( argv[argi], "-t") || 0==std::strcmp( argv[argi], "--threads")) { const char* optarg_ = argv[++argi]; nofThreads = optarg_ ? atoi( optarg_) : -1; if (nofThreads <= 0) { std::cerr << "argument of option --threads|-t has to be a positive integer: " << (optarg_?optarg_:"NULL") << std::endl; return -1; } } else if (0==std::strcmp( argv[argi], "-V") || 0==std::strcmp( argv[argi], "--verbose")) { g_verbose = true; } else { std::cerr << "unknown option " << argv[argi] << " (only --help|-h or --verbose|-V known)" << std::endl; return -1; } } int nofIterations = (argc == argi) ? 100 : atoi( argv[argi++]); if (nofThreads <= 0) { nofThreads = strus::platform::cores(); if (nofThreads <= 0) { std::cerr << "failed to determine numer of cores, default to 2" << std::endl; nofThreads = 2; } else { std::cerr << "found " << nofThreads << " cores" << std::endl; } } else { std::cerr << "number of threads " << nofThreads << " specified as program option." << std::endl; } if (nofIterations <= 0 || argi < argc) { std::cerr << "Usage: testRequestTransactionMap [-h,-V,-t <threads>] <nofIterations>" << std::endl; return 1; } try { g_timecnt_start = g_random.get( 1, std::numeric_limits<int>::max()); g_timecnt.set( g_timecnt_start); enum {MaxTransactionTimeout=60, MinNofTransactionPerSecond=10}; g_tpool.reset( new strus::TransactionPool( g_timecnt.value(), MaxTransactionTimeout, nofIterations*2*nofThreads + MinNofTransactionPerSecond, NULL/*logger interface*/)); strus::thread timerThread( &runTimerThread); runThreads( nofThreads, nofIterations); timerThread.join(); if (g_errorCounter.value() == 0) { std::cerr << "OK" << std::endl; return 0; } else { std::cerr << "ERR " << g_errorCounter.value() << " errors" << std::endl; return -1; } } catch (const std::exception& err) { std::cerr << "ERROR " << err.what() << std::endl; return -1; } }