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