merge hv v6, rework trace methods
[goodguy/history.git] / cinelerra-5.1 / guicast / bctrace.h
diff --git a/cinelerra-5.1/guicast/bctrace.h b/cinelerra-5.1/guicast/bctrace.h
new file mode 100644 (file)
index 0000000..5cbf0f5
--- /dev/null
@@ -0,0 +1,240 @@
+#ifndef __BC_TRACE_H__
+#define __BC_TRACE_H__
+
+#include "arraylist.h"
+#include "linklist.h"
+#include "bctrace.inc"
+#include "bcwindowbase.inc"
+#include "cstrdup.h"
+#include <pthread.h>
+
+
+class BC_Trace
+{
+public:
+       BC_Trace();
+       ~BC_Trace();
+
+       static BC_Trace *global_trace;
+        static void reset_locks();
+
+        static void delete_temps();
+        static void set_temp(char *string);
+        static void unset_temp(char *string);
+
+       static void enable_locks();
+       static void disable_locks();
+       static int set_lock(const char *title, const char *location, trace_info *info);
+       static void set_lock2(int table_id, trace_info *info);
+       static void unset_lock2(int table_id, trace_info *info);
+       static void unset_lock(trace_info *info);
+// Used in lock destructors so takes away all references
+       static void unset_all_locks(trace_info *info);
+       static void clear_locks_tid(pthread_t tid);
+
+       static void new_trace(const char *text);
+       static void new_trace(const char *file, const char *function, int line);
+       static void delete_traces();
+
+       static void enable_memory();
+       static void disable_memory();
+       static void set_buffer(int size, void *ptr, const char* location);
+// This one returns 1 if the buffer wasn't found.
+       static int unset_buffer(void *ptr);
+       static void lock_locks(const char *s);
+       static void unlock_locks();
+
+       static void dump_traces(FILE *fp=stdout);
+       static void dump_locks(FILE *fp=stdout);
+       static void dump_buffers(FILE *fp=stdout);
+       static void dump_threads(FILE *fp=stdout);
+};
+
+class bc_trace_list : public List<trace_item> {
+public:
+       void clear() { while( last ) remove(last); }
+       bc_trace_list() {}
+       ~bc_trace_list() { clear(); }
+};
+
+class bc_trace_t : public bc_trace_list {
+public:
+       int size;
+       bc_trace_t() : size(0) {}
+       ~bc_trace_t() {}
+};
+
+class bc_trace_spin : public bc_trace_t {
+       pthread_spinlock_t spin;
+public:
+       void *operator new(size_t n) { return (void*) malloc(n); }
+       void operator delete(void *t, size_t n) { free(t); }
+
+       void lock() { pthread_spin_lock(&spin); }
+       void unlock() { pthread_spin_unlock(&spin); }
+       bc_trace_spin() { pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE); }
+       ~bc_trace_spin() { pthread_spin_destroy(&spin); }
+};
+
+class bc_trace_mutex : public bc_trace_t {
+       pthread_mutex_t mutex;
+public:
+       void *operator new(size_t n) { return (void*) malloc(n); }
+       void operator delete(void *t, size_t n) { free(t); }
+
+       void lock() { pthread_mutex_lock(&mutex); }
+       void unlock() { pthread_mutex_unlock(&mutex); }
+       bc_trace_mutex() { pthread_mutex_init(&mutex, 0); }
+       ~bc_trace_mutex() { pthread_mutex_destroy(&mutex); }
+};
+
+extern bc_trace_mutex execution_table;
+extern bc_trace_mutex memory_table;
+extern bc_trace_mutex lock_table;
+extern bc_trace_mutex file_table;
+extern "C" void dump();
+
+class trace_item : public ListItem<trace_item> {
+public:
+       bc_trace_t &table;
+       trace_item(bc_trace_t &t);
+       ~trace_item();
+};
+
+class execution_item : public trace_item {
+public:
+       void *operator new(size_t n) { return (void*) malloc(n); }
+       void operator delete(void *t, size_t n) { free(t); }
+
+       const char *value;
+       void clear() { delete [] value;  value = 0; }
+       void set(const char *v) { delete [] value;  value = cstrdup(v); }
+
+       execution_item() : trace_item(execution_table) { value = 0; }
+       ~execution_item() { clear(); }
+};
+
+class lock_item : public trace_item {
+       static int table_id;
+public:
+       void *operator new(size_t n) { return (void*) malloc(n); }
+       void operator delete(void *t, size_t n) { free(t); }
+
+        trace_info *info;
+        const char *title;
+        const char *loc;
+        int is_owner;
+        int id;
+        pthread_t tid;
+       void set(trace_info *info, const char *title, const char *loc) {
+               this->info = info;  this->title = title;
+               this->loc = loc;  this->is_owner = 0;
+               this->id = table_id++;  this->tid = pthread_self();
+       }
+       void clear() { 
+               this->info = 0;  this->title = 0; this->loc = 0;
+               this->is_owner = 0;  this->id = -1;  this->tid = 0;
+       }
+
+       lock_item() : trace_item(lock_table) { clear(); }
+       ~lock_item() {}
+};
+
+class memory_item : public trace_item {
+public:
+       void *operator new(size_t n) { return (void*) malloc(n); }
+       void operator delete(void *t, size_t n) { free(t); }
+
+       int size;
+       void *ptr;
+       const char *loc;
+
+       memory_item(int size, void *ptr, const char *loc)
+        : trace_item(memory_table) {
+               this->size = size; this->ptr = ptr; this->loc = loc;
+       }
+       ~memory_item() {}
+};
+
+class file_item : public trace_item {
+public:
+       void *operator new(size_t n) { return (void*) malloc(n); }
+       void operator delete(void *t, size_t n) { free(t); }
+
+       const char *value;
+       void clear() { delete [] value;  value = 0; }
+       void set(const char *v) { delete [] value;  value = cstrdup(v); }
+
+       file_item() : trace_item(file_table) { value = 0; }
+       ~file_item() { clear(); }
+};
+
+// track unjoined threads at termination
+#ifdef TRACE_THREADS
+
+class TheLock {
+public:
+       pthread_mutex_t the_lock;
+
+       void lock() { pthread_mutex_lock(&the_lock); }
+       void unlock() { pthread_mutex_unlock(&the_lock); }
+
+       TheLock() {
+               pthread_mutexattr_t attr;
+               pthread_mutexattr_init(&attr);
+               pthread_mutex_init(&the_lock, &attr);
+       }
+       ~TheLock() {
+               pthread_mutex_destroy(&the_lock);
+       }
+};
+
+class TheLocker {
+public:
+       static TheLock the_lock;
+
+       TheLocker() { the_lock.lock(); }
+       ~TheLocker() { the_lock.unlock(); }
+};
+
+class TheDbg {
+public:
+       pthread_t tid, owner;  const char *name;
+       TheDbg(pthread_t t, pthread_t o, const char *nm) { tid = t; owner = o; name = nm; }
+       ~TheDbg() {}
+};
+
+
+class TheList : public ArrayList<TheDbg *> {
+public:
+       static TheList the_list;
+       static void dump_threads(FILE *fp);
+       static void dbg_add(pthread_t tid, pthread_t owner, const char *nm);
+       static void dbg_del(pthread_t tid);
+
+        TheList() {}
+       ~TheList() {
+               TheLocker the_locker;
+               remove_all_objects();
+       }
+};
+
+class TheChk {
+public:
+       static TheChk the_chk;
+
+       TheChk() {}
+       ~TheChk() {
+               int i = TheList::the_list.size();
+               if( !i ) return;
+               printf("unjoined tids / owner %d\n", i);
+               while( --i >= 0 ) printf("  %016lx / %016lx %s\n",
+                       (unsigned long)TheList::the_list[i]->tid,
+                       (unsigned long)TheList::the_list[i]->owner,
+                       TheList::the_list[i]->name);
+       }
+};
+
+#endif
+
+#endif