unsigned int ObjVector::assign(ObjList& list, bool move, unsigned int maxLen) { if (!maxLen) maxLen = list.count(); clear(); if (maxLen) { m_objects = new GenObject*[maxLen]; ObjList* l = list.skipNull(); for (unsigned int i = 0; i < maxLen; i++) { if (l) { if (move) { m_objects[i] = l->remove(false); l = l->skipNull(); } else { m_objects[i] = l->get(); l = l->skipNext(); } } else m_objects[i] = 0; } m_length = maxLen; } return maxLen; }
// Utility: print the result of dns query // Return the code static int printResult(int type, int code, const char* dname, ObjList& result, String* error) { #ifdef DEBUG if (!code) { String s; int crt = 0; for (ObjList* o = result.skipNull(); o; o = o->skipNext()) { DnsRecord* rec = static_cast<DnsRecord*>(o->get()); if (!s) s << "\r\n-----"; s << "\r\n" << ++crt << ":"; rec->dump(s); } if (s) s << "\r\n-----"; Debug(DebugAll,"%s query for '%s' got %d records%s", lookup(type,Resolver::s_types),dname,result.count(),s.safe()); } else { String dummy; if (!error) { error = &dummy; #ifdef _WINDOWS Thread::errorString(dummy,code); #elif defined(__NAMESER) dummy = hstrerror(code); #endif } Debug(DebugNote,"%s query for '%s' failed with code %d error=%s", lookup(type,Resolver::s_types),dname,code,TelEngine::c_safe(error)); } #endif return code; }
void ListIterator::assign(ObjList& list, int offset) { clear(); m_objList = &list; m_length = list.count(); if (!m_length) return; m_objects = new GenObject* [m_length]; offset = (m_length - offset) % m_length; unsigned int i = 0; for (ObjList* l = list.skipNull(); i < m_length; l = l->skipNext()) { if (!l) break; m_objects[((i++) + offset) % m_length] = l->get(); } while (i < m_length) m_objects[((i++) + offset) % m_length] = 0; }
int Thread::count() { Lock lock(s_tmutex); return s_threads.count(); }
void ThreadPrivate::killall() { Debugger debug("ThreadPrivate::killall()"); ThreadPrivate *t; bool sledgehammer = false; s_tmutex.lock(); ThreadPrivate* crt = ThreadPrivate::current(); int c = s_threads.count(); if (crt) Debug(DebugNote,"Thread '%s' is soft cancelling other %d running threads",crt->m_name,c-1); else Debug(DebugNote,"Soft cancelling %d running threads",c); ObjList* l = &s_threads; while (l && (t = static_cast<ThreadPrivate *>(l->get())) != 0) { if (t != crt) { Debug(DebugInfo,"Stopping ThreadPrivate '%s' [%p]",t->m_name,t); t->cancel(false); } l = l->next(); } for (int w = 0; w < SOFT_WAITS; w++) { s_tmutex.unlock(); Thread::idle(); s_tmutex.lock(); c = s_threads.count(); // ignore the current thread if we have one if (crt && c) c--; if (!c) { s_tmutex.unlock(); return; } } Debug(DebugMild,"Hard cancelling %d remaining threads",c); l = &s_threads; c = 1; while (l && (t = static_cast<ThreadPrivate *>(l->get())) != 0) { if (t == crt) { l = l->next(); continue; } Debug(DebugInfo,"Trying to kill ThreadPrivate '%s' [%p], attempt %d",t->m_name,t,c); bool ok = t->cancel(true); if (ok) { int d = 0; // delay a little (exponentially) so threads have a chance to clean up for (int i=1; i<=KILL_WAIT; i<<=1) { s_tmutex.unlock(); Thread::msleep(i-d); d = i; s_tmutex.lock(); if (t != l->get()) break; } } if (t != l->get()) c = 1; else { if (ok) { #ifdef _WINDOWS Debug(DebugGoOn,"Could not kill %p but seems OK to delete it (library bug?)",t); s_tmutex.unlock(); t->destroy(); s_tmutex.lock(); if (t != l->get()) c = 1; #else Debug(DebugGoOn,"Could not kill cancelled %p so we'll abandon it (library bug?)",t); l->remove(t,false); c = 1; #endif continue; } Thread::msleep(1); if (++c >= HARD_KILLS) { Debug(DebugGoOn,"Could not kill %p, will use sledgehammer later.",t); sledgehammer = true; t->m_thread = 0; l = l->next(); c = 1; } } } s_tmutex.unlock(); // last solution - a REALLY BIG tool! // usually too big since many libraries have threads of their own... if (sledgehammer) { #ifdef THREAD_KILL Debug(DebugGoOn,"Brutally killing remaining threads!"); ::pthread_kill_other_threads_np(); #else Debug(DebugGoOn,"Aargh! I cannot kill remaining threads on this platform!"); #endif } }