2c2046b527da4384960aaa8d55931462f33ca0b5
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bctrace.h
1 #ifndef __BC_TRACE_H__
2 #define __BC_TRACE_H__
3
4 #include "arraylist.h"
5 #include "linklist.h"
6 #include "bctrace.inc"
7 #include "bcwindowbase.inc"
8 #include "cstrdup.h"
9 #include <pthread.h>
10
11 #ifdef BOOBY
12 #define BT if( top_level->display_lock_owner != pthread_self() ) booby();
13 void booby();
14 #else
15 #define BT
16 #define booby(s) do {} while(0)
17 #endif
18
19 class BC_Trace
20 {
21 public:
22         BC_Trace();
23         ~BC_Trace();
24
25         static BC_Trace *global_trace;
26         static void reset_locks();
27
28         static void delete_temps();
29         static void set_temp(char *string);
30         static void unset_temp(char *string);
31
32         static void enable_locks();
33         static void disable_locks();
34         static int set_lock(const char *title, const char *location, trace_info *info);
35         static void set_lock2(int table_id, trace_info *info);
36         static void unset_lock2(int table_id, trace_info *info);
37         static void unset_lock(trace_info *info);
38 // Used in lock destructors so takes away all references
39         static void unset_all_locks(trace_info *info);
40         static void clear_locks_tid(pthread_t tid);
41
42         static void new_trace(const char *text);
43         static void new_trace(const char *file, const char *function, int line);
44         static void delete_traces();
45
46         static void enable_memory();
47         static void disable_memory();
48         static void set_buffer(int size, void *ptr, const char* location);
49 // This one returns 1 if the buffer wasn't found.
50         static int unset_buffer(void *ptr);
51         static void lock_locks(const char *s);
52         static void unlock_locks();
53
54         static void dump_traces(FILE *fp=stdout);
55         static void dump_locks(FILE *fp=stdout);
56         static void dump_buffers(FILE *fp=stdout);
57         static void dump_threads(FILE *fp=stdout);
58
59         static void dump_shm_stat(const char *fn, FILE *fp=stdout);
60         static void dump_shm_stats(FILE *fp=stdout);
61 };
62
63 class bc_trace_list : public List<trace_item> {
64 public:
65         void clear() { while( last ) remove(last); }
66         bc_trace_list() {}
67         ~bc_trace_list() { clear(); }
68 };
69
70 class bc_trace_t : public bc_trace_list {
71 public:
72         int size;
73         bc_trace_t() : size(0) {}
74         ~bc_trace_t() {}
75 };
76
77 class bc_trace_spin : public bc_trace_t {
78         pthread_spinlock_t spin;
79 public:
80         void *operator new(size_t n) { return (void*) malloc(n); }
81         void operator delete(void *t, size_t n) { free(t); }
82
83         void lock() { pthread_spin_lock(&spin); }
84         void unlock() { pthread_spin_unlock(&spin); }
85         bc_trace_spin() { pthread_spin_init(&spin, PTHREAD_PROCESS_PRIVATE); }
86         ~bc_trace_spin() { pthread_spin_destroy(&spin); }
87 };
88
89 class bc_trace_mutex : public bc_trace_t {
90         pthread_mutex_t mutex;
91 public:
92         void *operator new(size_t n) { return (void*) malloc(n); }
93         void operator delete(void *t, size_t n) { free(t); }
94
95         void lock() { pthread_mutex_lock(&mutex); }
96         void unlock() { pthread_mutex_unlock(&mutex); }
97         bc_trace_mutex() { pthread_mutex_init(&mutex, 0); }
98         ~bc_trace_mutex() { pthread_mutex_destroy(&mutex); }
99 };
100
101 extern bc_trace_mutex execution_table;
102 extern bc_trace_mutex memory_table;
103 extern bc_trace_mutex lock_table;
104 extern bc_trace_mutex file_table;
105 extern "C" void dump();
106
107 class trace_item : public ListItem<trace_item> {
108 public:
109         bc_trace_t &table;
110         trace_item(bc_trace_t &t);
111         ~trace_item();
112 };
113
114 class execution_item : public trace_item {
115 public:
116         void *operator new(size_t n) { return (void*) malloc(n); }
117         void operator delete(void *t, size_t n) { free(t); }
118
119         const char *value;
120         void clear() { delete [] value;  value = 0; }
121         void set(const char *v) { delete [] value;  value = cstrdup(v); }
122
123         execution_item() : trace_item(execution_table) { value = 0; }
124         ~execution_item() { clear(); }
125 };
126
127 class lock_item : public trace_item {
128         static int table_id;
129 public:
130         void *operator new(size_t n) { return (void*) malloc(n); }
131         void operator delete(void *t, size_t n) { free(t); }
132
133         trace_info *info;
134         const char *title;
135         const char *loc;
136         int is_owner;
137         int id;
138         pthread_t tid;
139         void set(trace_info *info, const char *title, const char *loc) {
140                 this->info = info;  this->title = title;
141                 this->loc = loc;  this->is_owner = 0;
142                 this->id = table_id++;  this->tid = pthread_self();
143         }
144         void clear() {
145                 this->info = 0;  this->title = 0; this->loc = 0;
146                 this->is_owner = 0;  this->id = -1;  this->tid = 0;
147         }
148
149         lock_item() : trace_item(lock_table) { clear(); }
150         ~lock_item() {}
151 };
152
153 class memory_item : public trace_item {
154 public:
155         void *operator new(size_t n) { return (void*) malloc(n); }
156         void operator delete(void *t, size_t n) { free(t); }
157
158         int size;
159         void *ptr;
160         const char *loc;
161
162         memory_item(int size, void *ptr, const char *loc)
163          : trace_item(memory_table) {
164                 this->size = size; this->ptr = ptr; this->loc = loc;
165         }
166         ~memory_item() {}
167 };
168
169 class file_item : public trace_item {
170 public:
171         void *operator new(size_t n) { return (void*) malloc(n); }
172         void operator delete(void *t, size_t n) { free(t); }
173
174         const char *value;
175         void clear() { delete [] value;  value = 0; }
176         void set(const char *v) { delete [] value;  value = cstrdup(v); }
177
178         file_item() : trace_item(file_table) { value = 0; }
179         ~file_item() { clear(); }
180 };
181
182 // track unjoined threads at termination
183 #ifdef TRACE_THREADS
184
185 class TheLock {
186 public:
187         pthread_mutex_t the_lock;
188
189         void lock() { pthread_mutex_lock(&the_lock); }
190         void unlock() { pthread_mutex_unlock(&the_lock); }
191
192         void init() {
193                 pthread_mutexattr_t attr;
194                 pthread_mutexattr_init(&attr);
195                 pthread_mutex_init(&the_lock, &attr);
196         }
197         void finit() {
198                 pthread_mutex_destroy(&the_lock);
199         }
200         void reset() { finit();  init(); }
201
202         TheLock()  { init();  }
203         ~TheLock() { finit(); }
204 };
205
206 class TheLocker {
207 public:
208         static TheLock the_lock;
209         static void reset() { the_lock.reset(); }
210
211         TheLocker() { the_lock.lock(); }
212         ~TheLocker() { the_lock.unlock(); }
213 };
214
215 class TheDbg {
216 public:
217         pthread_t tid, owner;  const char *name;
218         TheDbg(pthread_t t, pthread_t o, const char *nm) { tid = t; owner = o; name = nm; }
219         ~TheDbg() {}
220 };
221
222
223 class TheList : public ArrayList<TheDbg *> {
224 public:
225         static TheList the_list;
226         static void dump_threads(FILE *fp);
227         static void dbg_add(pthread_t tid, pthread_t owner, const char *nm);
228         static void dbg_del(pthread_t tid);
229         static void reset() { the_list.remove_all_objects(); TheLocker::reset(); }
230         void check() {
231                 int i = the_list.size();
232                 if( !i ) return;
233                 printf("unjoined tids / owner %d\n", i);
234                 while( --i >= 0 ) printf("  %016lx / %016lx %s\n",
235                         (unsigned long)the_list[i]->tid,
236                         (unsigned long)the_list[i]->owner,
237                         the_list[i]->name);
238         }
239          TheList() {}
240         ~TheList() { check(); reset(); }
241 };
242
243 #endif
244
245 #endif