/* * tools.c: Various tools * * See the main source file 'vdr.c' for copyright information and * how to reach the author. * * vdr: Id: tools.c 2.0 2008/03/05 17:23:47 kls Exp */ #include "tools.h" #include #include #include #include #include #include #include #include #include #include int SysLogLevel = 3; #define MAXSYSLOGBUF 256 // --- cTimeMs --------------------------------------------------------------- cTimeMs::cTimeMs(int Ms) { Set(Ms); } uint64_t cTimeMs::Now(void) { #if 0 && _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) #define MIN_RESOLUTION 5 // ms static bool initialized = false; static bool monotonic = false; struct timespec tp; if (!initialized) { // check if monotonic timer is available and provides enough accurate resolution: if (clock_getres(CLOCK_MONOTONIC, &tp) == 0) { long Resolution = tp.tv_nsec; // require a minimum resolution: if (tp.tv_sec == 0 && tp.tv_nsec <= MIN_RESOLUTION * 1000000) { if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) { dsyslog("cTimeMs: using monotonic clock (resolution is %ld ns)", Resolution); monotonic = true; } else esyslog("cTimeMs: clock_gettime(CLOCK_MONOTONIC) failed"); } else dsyslog("cTimeMs: not using monotonic clock - resolution is too bad (%ld s %ld ns)", tp.tv_sec, tp.tv_nsec); } else esyslog("cTimeMs: clock_getres(CLOCK_MONOTONIC) failed"); initialized = true; } if (monotonic) { if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) return (uint64_t(tp.tv_sec)) * 1000 + tp.tv_nsec / 1000000; esyslog("cTimeMs: clock_gettime(CLOCK_MONOTONIC) failed"); monotonic = false; // fall back to gettimeofday() } #else #if 0 # warning Posix monotonic clock not available #endif #endif struct timeval t; if (gettimeofday(&t, NULL) == 0) return (uint64_t(t.tv_sec)) * 1000 + t.tv_usec / 1000; return 0; } void cTimeMs::Set(int Ms) { begin = Now() + Ms; } bool cTimeMs::TimedOut(void) { return Now() >= begin; } uint64_t cTimeMs::Elapsed(void) { return Now() - begin; } // --- cListObject ----------------------------------------------------------- cListObject::cListObject(void) { prev = next = NULL; } cListObject::~cListObject() { } void cListObject::Append(cListObject *Object) { next = Object; Object->prev = this; } void cListObject::Insert(cListObject *Object) { prev = Object; Object->next = this; } void cListObject::Unlink(void) { if (next) next->prev = prev; if (prev) prev->next = next; next = prev = NULL; } int cListObject::Index(void) const { cListObject *p = prev; int i = 0; while (p) { i++; p = p->prev; } return i; } // --- cListBase ------------------------------------------------------------- cListBase::cListBase(void) { objects = lastObject = NULL; count = 0; } cListBase::~cListBase() { Clear(); } void cListBase::Add(cListObject *Object, cListObject *After) { if (After && After != lastObject) { After->Next()->Insert(Object); After->Append(Object); } else { if (lastObject) lastObject->Append(Object); else objects = Object; lastObject = Object; } count++; } void cListBase::Ins(cListObject *Object, cListObject *Before) { if (Before && Before != objects) { Before->Prev()->Append(Object); Before->Insert(Object); } else { if (objects) objects->Insert(Object); else lastObject = Object; objects = Object; } count++; } void cListBase::Del(cListObject *Object, bool DeleteObject) { if (Object == objects) objects = Object->Next(); if (Object == lastObject) lastObject = Object->Prev(); Object->Unlink(); if (DeleteObject) { delete Object; count--; } } void cListBase::Move(int From, int To) { Move(Get(From), Get(To)); } void cListBase::Move(cListObject *From, cListObject *To) { if (From && To) { if (From->Index() < To->Index()) To = To->Next(); if (From == objects) objects = From->Next(); if (From == lastObject) lastObject = From->Prev(); From->Unlink(); if (To) { if (To->Prev()) To->Prev()->Append(From); From->Append(To); } else { lastObject->Append(From); lastObject = From; } if (!From->Prev()) objects = From; } } void cListBase::Clear(void) { while (objects) { cListObject *object = objects->Next(); delete objects; objects = object; } objects = lastObject = NULL; count = 0; } cListObject *cListBase::Get(int Index) const { if (Index < 0) return NULL; cListObject *object = objects; while (object && Index-- > 0) object = object->Next(); return object; } static int CompareListObjects(const void *a, const void *b) { const cListObject *la = *(const cListObject **)a; const cListObject *lb = *(const cListObject **)b; return la->Compare(*lb); } void cListBase::Sort(void) { int n = Count(); cListObject *a[n]; cListObject *object = objects; int i = 0; while (object && i < n) { a[i++] = object; object = object->Next(); } qsort(a, n, sizeof(cListObject *), CompareListObjects); objects = lastObject = NULL; for (i = 0; i < n; i++) { a[i]->Unlink(); count--; Add(a[i]); } }