00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pStatClient.h"
00016
00017 #ifdef DO_PSTATS
00018
00019
00020
00021 #include "pStatClientImpl.h"
00022 #include "pStatClientControlMessage.h"
00023 #include "pStatServerControlMessage.h"
00024 #include "pStatCollector.h"
00025 #include "pStatThread.h"
00026 #include "config_pstats.h"
00027 #include "pStatProperties.h"
00028 #include "thread.h"
00029 #include "clockObject.h"
00030 #include "neverFreeMemory.h"
00031
00032 PStatCollector PStatClient::_heap_total_size_pcollector("System memory:Heap");
00033 PStatCollector PStatClient::_heap_overhead_size_pcollector("System memory:Heap:Overhead");
00034 PStatCollector PStatClient::_heap_single_size_pcollector("System memory:Heap:Single");
00035 PStatCollector PStatClient::_heap_single_other_size_pcollector("System memory:Heap:Single:Other");
00036 PStatCollector PStatClient::_heap_array_size_pcollector("System memory:Heap:Array");
00037 PStatCollector PStatClient::_heap_array_other_size_pcollector("System memory:Heap:Array:Other");
00038 PStatCollector PStatClient::_heap_external_size_pcollector("System memory:Heap:External");
00039 PStatCollector PStatClient::_mmap_size_pcollector("System memory:MMap");
00040
00041 PStatCollector PStatClient::_mmap_nf_unused_size_pcollector("System memory:MMap:NeverFree:Unused");
00042 PStatCollector PStatClient::_mmap_dc_active_other_size_pcollector("System memory:MMap:NeverFree:Active:Other");
00043 PStatCollector PStatClient::_mmap_dc_inactive_other_size_pcollector("System memory:MMap:NeverFree:Inactive:Other");
00044 PStatCollector PStatClient::_pstats_pcollector("*:PStats");
00045 PStatCollector PStatClient::_clock_wait_pcollector("Wait:Clock Wait:Sleep");
00046 PStatCollector PStatClient::_clock_busy_wait_pcollector("Wait:Clock Wait:Spin");
00047 PStatCollector PStatClient::_thread_block_pcollector("Wait:Thread block");
00048
00049 PStatClient *PStatClient::_global_pstats = NULL;
00050
00051
00052
00053
00054 class TypeHandleCollector {
00055 public:
00056 PStatCollector _mem_class[TypeHandle::MC_limit];
00057 };
00058 typedef pvector<TypeHandleCollector> TypeHandleCols;
00059 static TypeHandleCols type_handle_cols;
00060
00061
00062
00063
00064
00065
00066
00067 PStatClient::PerThreadData::
00068 PerThreadData() {
00069 _has_level = false;
00070 _level = 0.0;
00071 _nested_count = 0;
00072 }
00073
00074
00075
00076
00077
00078
00079 PStatClient::
00080 PStatClient() :
00081 _lock("PStatClient::_lock"),
00082 _impl(NULL)
00083 {
00084 _collectors = NULL;
00085 _collectors_size = 0;
00086 _num_collectors = 0;
00087
00088 _threads = NULL;
00089 _threads_size = 0;
00090 _num_threads = 0;
00091
00092
00093
00094
00095 Collector *collector = new Collector(0, "Frame");
00096
00097
00098
00099 add_collector(collector);
00100
00101
00102 make_thread(Thread::get_main_thread());
00103 }
00104
00105
00106
00107
00108
00109
00110 PStatClient::
00111 ~PStatClient() {
00112 disconnect();
00113 }
00114
00115
00116
00117
00118
00119
00120 PStatCollector PStatClient::
00121 get_collector(int index) const {
00122 nassertr(index >= 0 && index < AtomicAdjust::get(_num_collectors), PStatCollector());
00123 return PStatCollector((PStatClient *)this, index);
00124 }
00125
00126
00127
00128
00129
00130
00131 string PStatClient::
00132 get_collector_name(int index) const {
00133 nassertr(index >= 0 && index < AtomicAdjust::get(_num_collectors), string());
00134
00135 return get_collector_ptr(index)->get_name();
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 string PStatClient::
00147 get_collector_fullname(int index) const {
00148 nassertr(index >= 0 && index < AtomicAdjust::get(_num_collectors), string());
00149
00150 Collector *collector = get_collector_ptr(index);
00151 int parent_index = collector->get_parent_index();
00152 if (parent_index == 0) {
00153 return collector->get_name();
00154 } else {
00155 return get_collector_fullname(parent_index) + ":" +
00156 collector->get_name();
00157 }
00158 }
00159
00160
00161
00162
00163
00164
00165 PStatThread PStatClient::
00166 get_thread(int index) const {
00167 ReMutexHolder holder(_lock);
00168 nassertr(index >= 0 && index < _num_threads, PStatThread());
00169 return PStatThread((PStatClient *)this, index);
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 PStatThread PStatClient::
00179 get_main_thread() const {
00180 return PStatThread((PStatClient *)this, 0);
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 PStatThread PStatClient::
00192 get_current_thread() const {
00193 if (!client_is_connected()) {
00194
00195
00196 return get_main_thread();
00197 }
00198 return PStatThread(Thread::get_current_thread(), (PStatClient *)this);
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208 void PStatClient::
00209 main_tick() {
00210
00211
00212
00213
00214
00215 #ifdef DO_MEMORY_USAGE
00216 if (is_connected()) {
00217 _heap_total_size_pcollector.set_level(MemoryUsage::get_total_size());
00218 _heap_overhead_size_pcollector.set_level(MemoryUsage::get_panda_heap_overhead());
00219 _heap_single_size_pcollector.set_level(MemoryUsage::get_panda_heap_single_size());
00220 _heap_array_size_pcollector.set_level(MemoryUsage::get_panda_heap_array_size());
00221 _heap_external_size_pcollector.set_level(MemoryUsage::get_external_size());
00222
00223
00224 _mmap_size_pcollector.set_level(MemoryUsage::get_panda_mmap_size());
00225
00226 TypeRegistry *type_reg = TypeRegistry::ptr();
00227 int num_typehandles = type_reg->get_num_typehandles();
00228
00229 while ((int)type_handle_cols.size() < num_typehandles) {
00230 type_handle_cols.push_back(TypeHandleCollector());
00231 }
00232
00233 size_t single_total_usage = 0;
00234 size_t array_total_usage = 0;
00235 size_t dc_active_total_usage = 0;
00236 size_t dc_inactive_total_usage = 0;
00237 int i;
00238 for (i = 0; i < num_typehandles; ++i) {
00239 TypeHandle type = type_reg->get_typehandle(i);
00240 for (int mi = 0; mi < (int)TypeHandle::MC_limit; ++mi) {
00241 TypeHandle::MemoryClass mc = (TypeHandle::MemoryClass)mi;
00242 size_t usage = type.get_memory_usage(mc);
00243
00244 switch (mc) {
00245 case TypeHandle::MC_singleton:
00246 single_total_usage += usage;
00247 break;
00248
00249 case TypeHandle::MC_array:
00250 array_total_usage += usage;
00251 break;
00252
00253 case TypeHandle::MC_deleted_chain_active:
00254 dc_active_total_usage += usage;
00255 break;
00256
00257 case TypeHandle::MC_deleted_chain_inactive:
00258 dc_inactive_total_usage += usage;
00259 break;
00260
00261 case TypeHandle::MC_limit:
00262
00263 break;
00264 }
00265 }
00266 }
00267 size_t min_usage = (single_total_usage + array_total_usage + dc_active_total_usage + dc_inactive_total_usage) / 1024;
00268 if (!pstats_mem_other) {
00269 min_usage = 0;
00270 }
00271 size_t single_other_usage = single_total_usage;
00272 size_t array_other_usage = array_total_usage;
00273 size_t dc_active_other_usage = dc_active_total_usage;
00274 size_t dc_inactive_other_usage = dc_inactive_total_usage;
00275
00276 for (i = 0; i < num_typehandles; ++i) {
00277 TypeHandle type = type_reg->get_typehandle(i);
00278 for (int mi = 0; mi < (int)TypeHandle::MC_limit; ++mi) {
00279 TypeHandle::MemoryClass mc = (TypeHandle::MemoryClass)mi;
00280 PStatCollector &col = type_handle_cols[i]._mem_class[mi];
00281 size_t usage = type.get_memory_usage(mc);
00282 if (usage > min_usage || col.is_valid()) {
00283
00284
00285 if (!col.is_valid()) {
00286 const char *category = "";
00287 switch (mc) {
00288 case TypeHandle::MC_singleton:
00289 category = "Heap:Single";
00290 break;
00291
00292 case TypeHandle::MC_array:
00293 category = "Heap:Array";
00294 break;
00295
00296 case TypeHandle::MC_deleted_chain_active:
00297 category = "MMap:NeverFree:Active";
00298 break;
00299
00300 case TypeHandle::MC_deleted_chain_inactive:
00301 category = "MMap:NeverFree:Inactive";
00302 break;
00303
00304 case TypeHandle::MC_limit:
00305
00306 break;
00307 }
00308 ostringstream strm;
00309 strm << "System memory:" << category << ":" << type;
00310 col = PStatCollector(strm.str());
00311 }
00312 col.set_level(usage);
00313
00314 switch (mc) {
00315 case TypeHandle::MC_singleton:
00316 single_other_usage -= usage;
00317 break;
00318
00319 case TypeHandle::MC_array:
00320 array_other_usage -= usage;
00321 break;
00322
00323 case TypeHandle::MC_deleted_chain_active:
00324 dc_active_other_usage -= usage;
00325 break;
00326
00327 case TypeHandle::MC_deleted_chain_inactive:
00328 dc_inactive_other_usage -= usage;
00329 break;
00330
00331 case TypeHandle::MC_limit:
00332
00333 break;
00334 }
00335 }
00336 }
00337 }
00338
00339 _mmap_nf_unused_size_pcollector.set_level(NeverFreeMemory::get_total_unused());
00340
00341
00342
00343 _heap_single_other_size_pcollector.set_level(single_other_usage);
00344 _heap_array_other_size_pcollector.set_level(array_other_usage);
00345 _mmap_dc_active_other_size_pcollector.set_level(dc_active_other_usage);
00346 _mmap_dc_inactive_other_size_pcollector.set_level(dc_inactive_other_usage);
00347 }
00348 #endif // DO_MEMORY_USAGE
00349
00350 get_global_pstats()->client_main_tick();
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 void PStatClient::
00360 thread_tick(const string &sync_name) {
00361 get_global_pstats()->client_thread_tick(sync_name);
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371 void PStatClient::
00372 client_main_tick() {
00373 ReMutexHolder holder(_lock);
00374 if (has_impl()) {
00375 if (!_impl->client_is_connected()) {
00376 client_disconnect();
00377 return;
00378 }
00379
00380 _impl->client_main_tick();
00381
00382 MultiThingsByName::const_iterator ni =
00383 _threads_by_sync_name.find("Main");
00384 if (ni != _threads_by_sync_name.end()) {
00385 const vector_int &indices = (*ni).second;
00386 for (vector_int::const_iterator vi = indices.begin();
00387 vi != indices.end();
00388 ++vi) {
00389 _impl->new_frame(*vi);
00390 }
00391 }
00392 }
00393 }
00394
00395
00396
00397
00398
00399
00400
00401 void PStatClient::
00402 client_thread_tick(const string &sync_name) {
00403 ReMutexHolder holder(_lock);
00404
00405 if (has_impl()) {
00406 MultiThingsByName::const_iterator ni =
00407 _threads_by_sync_name.find(sync_name);
00408 if (ni != _threads_by_sync_name.end()) {
00409 const vector_int &indices = (*ni).second;
00410 for (vector_int::const_iterator vi = indices.begin();
00411 vi != indices.end();
00412 ++vi) {
00413 _impl->new_frame(*vi);
00414 }
00415 }
00416 }
00417 }
00418
00419
00420
00421
00422
00423
00424 void PStatClient::
00425 client_disconnect() {
00426 ReMutexHolder holder(_lock);
00427 if (has_impl()) {
00428 _impl->client_disconnect();
00429 delete _impl;
00430 _impl = NULL;
00431 }
00432
00433 ThreadPointer *threads = (ThreadPointer *)_threads;
00434 for (int ti = 0; ti < _num_threads; ++ti) {
00435 InternalThread *thread = threads[ti];
00436 thread->_frame_number = 0;
00437 thread->_is_active = false;
00438 thread->_next_packet = 0.0;
00439 thread->_frame_data.clear();
00440 }
00441
00442 CollectorPointer *collectors = (CollectorPointer *)_collectors;
00443 for (int ci = 0; ci < _num_collectors; ++ci) {
00444 Collector *collector = collectors[ci];
00445 PerThread::iterator ii;
00446 for (ii = collector->_per_thread.begin();
00447 ii != collector->_per_thread.end();
00448 ++ii) {
00449 (*ii)._nested_count = 0;
00450 }
00451 }
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 PStatClient *PStatClient::
00463 get_global_pstats() {
00464 if (_global_pstats == (PStatClient *)NULL) {
00465 _global_pstats = new PStatClient;
00466
00467 ClockObject::_start_clock_wait = start_clock_wait;
00468 ClockObject::_start_clock_busy_wait = start_clock_busy_wait;
00469 ClockObject::_stop_clock_wait = stop_clock_wait;
00470 }
00471 return _global_pstats;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 PStatCollector PStatClient::
00486 make_collector_with_relname(int parent_index, string relname) {
00487 ReMutexHolder holder(_lock);
00488
00489 if (relname.empty()) {
00490 relname = "Unnamed";
00491 }
00492
00493
00494 size_t start = 0;
00495 while (start < relname.size() && relname[start] == ':') {
00496 start++;
00497 }
00498
00499
00500
00501 size_t colon = relname.find(':', start);
00502 while (colon != string::npos) {
00503 string parent_name = relname.substr(start, colon - start);
00504 PStatCollector parent_collector =
00505 make_collector_with_name(parent_index, parent_name);
00506 parent_index = parent_collector._index;
00507 relname = relname.substr(colon + 1);
00508 start = 0;
00509 colon = relname.find(':');
00510 }
00511
00512 string name = relname.substr(start);
00513 return make_collector_with_name(parent_index, name);
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 PStatCollector PStatClient::
00526 make_collector_with_name(int parent_index, const string &name) {
00527 ReMutexHolder holder(_lock);
00528
00529 nassertr(parent_index >= 0 && parent_index < _num_collectors,
00530 PStatCollector());
00531
00532 Collector *parent = get_collector_ptr(parent_index);
00533
00534
00535
00536
00537 if (parent->get_name() == name) {
00538 return PStatCollector(this, parent_index);
00539 }
00540
00541 ThingsByName::const_iterator ni = parent->_children.find(name);
00542
00543 if (ni != parent->_children.end()) {
00544
00545 int index = (*ni).second;
00546 nassertr(index >= 0 && index < _num_collectors, PStatCollector());
00547 return PStatCollector(this, (*ni).second);
00548 }
00549
00550
00551 int new_index = _num_collectors;
00552 parent->_children.insert(ThingsByName::value_type(name, new_index));
00553
00554 Collector *collector = new Collector(parent_index, name);
00555
00556
00557
00558
00559
00560 while ((int)collector->_per_thread.size() < _num_threads) {
00561 collector->_per_thread.push_back(PerThreadData());
00562 }
00563 add_collector(collector);
00564
00565 return PStatCollector(this, new_index);
00566 }
00567
00568
00569
00570
00571
00572
00573
00574 PStatThread PStatClient::
00575 do_get_current_thread() const {
00576 Thread *thread = Thread::get_current_thread();
00577 int thread_index = thread->get_pstats_index();
00578 if (thread_index != -1) {
00579 return PStatThread((PStatClient *)this, thread_index);
00580 }
00581
00582
00583
00584 return ((PStatClient *)this)->do_make_thread(thread);
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594 PStatThread PStatClient::
00595 make_thread(Thread *thread) {
00596 ReMutexHolder holder(_lock);
00597 return do_make_thread(thread);
00598 }
00599
00600
00601
00602
00603
00604
00605 PStatThread PStatClient::
00606 do_make_thread(Thread *thread) {
00607 int thread_index = thread->get_pstats_index();
00608 if (thread_index != -1) {
00609 return PStatThread((PStatClient *)this, thread_index);
00610 }
00611
00612 MultiThingsByName::const_iterator ni =
00613 _threads_by_name.find(thread->get_name());
00614
00615 if (ni != _threads_by_name.end()) {
00616
00617
00618 const vector_int &indices = (*ni).second;
00619 for (vector_int::const_iterator vi = indices.begin();
00620 vi != indices.end();
00621 ++vi) {
00622 int index = (*vi);
00623 nassertr(index >= 0 && index < _num_threads, PStatThread());
00624 ThreadPointer *threads = (ThreadPointer *)_threads;
00625 if (threads[index]->_thread.was_deleted() &&
00626 threads[index]->_sync_name == thread->get_sync_name()) {
00627
00628 threads[index]->_thread = thread;
00629 thread->set_pstats_index(index);
00630 thread->set_pstats_callback(this);
00631 return PStatThread(this, index);
00632 }
00633 }
00634 }
00635
00636
00637 int new_index = _num_threads;
00638 thread->set_pstats_index(new_index);
00639 thread->set_pstats_callback(this);
00640 _threads_by_name[thread->get_name()].push_back(new_index);
00641 _threads_by_sync_name[thread->get_sync_name()].push_back(new_index);
00642
00643 InternalThread *pthread = new InternalThread(thread);
00644 add_thread(pthread);
00645
00646
00647
00648 CollectorPointer *collectors = (CollectorPointer *)_collectors;
00649 for (int ci = 0; ci < _num_collectors; ++ci) {
00650 Collector *collector = collectors[ci];
00651 collector->_per_thread.push_back(PerThreadData());
00652 nassertr((int)collector->_per_thread.size() == _num_threads, PStatThread());
00653 }
00654
00655 return PStatThread(this, new_index);
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 bool PStatClient::
00669 is_active(int collector_index, int thread_index) const {
00670 nassertr(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors), false);
00671 nassertr(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads), false);
00672
00673 return (client_is_connected() &&
00674 get_collector_ptr(collector_index)->is_active() &&
00675 get_thread_ptr(thread_index)->_is_active);
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 bool PStatClient::
00688 is_started(int collector_index, int thread_index) const {
00689 nassertr(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors), false);
00690 nassertr(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads), false);
00691
00692 Collector *collector = get_collector_ptr(collector_index);
00693 InternalThread *thread = get_thread_ptr(thread_index);
00694
00695 if (client_is_connected() && collector->is_active() && thread->_is_active) {
00696 LightMutexHolder holder(thread->_thread_lock);
00697 if (collector->_per_thread[thread_index]._nested_count == 0) {
00698
00699 return false;
00700 }
00701
00702 return true;
00703 }
00704
00705
00706 return false;
00707 }
00708
00709
00710
00711
00712
00713
00714
00715
00716 void PStatClient::
00717 start(int collector_index, int thread_index) {
00718 #ifdef _DEBUG
00719 nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors));
00720 nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads));
00721 #endif
00722
00723 Collector *collector = get_collector_ptr(collector_index);
00724 InternalThread *thread = get_thread_ptr(thread_index);
00725
00726 if (client_is_connected() && collector->is_active() && thread->_is_active) {
00727 LightMutexHolder holder(thread->_thread_lock);
00728 if (collector->_per_thread[thread_index]._nested_count == 0) {
00729
00730
00731 if (thread->_thread_active) {
00732 thread->_frame_data.add_start(collector_index, get_real_time());
00733 }
00734 }
00735 collector->_per_thread[thread_index]._nested_count++;
00736 }
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746 void PStatClient::
00747 start(int collector_index, int thread_index, double as_of) {
00748 #ifdef _DEBUG
00749 nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors));
00750 nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads));
00751 #endif
00752
00753 Collector *collector = get_collector_ptr(collector_index);
00754 InternalThread *thread = get_thread_ptr(thread_index);
00755
00756 if (client_is_connected() && collector->is_active() && thread->_is_active) {
00757 LightMutexHolder holder(thread->_thread_lock);
00758 if (collector->_per_thread[thread_index]._nested_count == 0) {
00759
00760
00761 if (thread->_thread_active) {
00762 thread->_frame_data.add_start(collector_index, as_of);
00763 }
00764 }
00765 collector->_per_thread[thread_index]._nested_count++;
00766 }
00767 }
00768
00769
00770
00771
00772
00773
00774
00775
00776 void PStatClient::
00777 stop(int collector_index, int thread_index) {
00778 #ifdef _DEBUG
00779 nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors));
00780 nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads));
00781 #endif
00782
00783 Collector *collector = get_collector_ptr(collector_index);
00784 InternalThread *thread = get_thread_ptr(thread_index);
00785
00786 if (client_is_connected() && collector->is_active() && thread->_is_active) {
00787 LightMutexHolder holder(thread->_thread_lock);
00788 if (collector->_per_thread[thread_index]._nested_count == 0) {
00789 if (pstats_cat.is_debug()) {
00790 pstats_cat.debug()
00791 << "Collector " << get_collector_fullname(collector_index)
00792 << " was already stopped in thread " << get_thread_name(thread_index)
00793 << "!\n";
00794 }
00795 return;
00796 }
00797
00798 collector->_per_thread[thread_index]._nested_count--;
00799
00800 if (collector->_per_thread[thread_index]._nested_count == 0) {
00801
00802
00803 if (thread->_thread_active) {
00804 thread->_frame_data.add_stop(collector_index, get_real_time());
00805 }
00806 }
00807 }
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817 void PStatClient::
00818 stop(int collector_index, int thread_index, double as_of) {
00819 #ifdef _DEBUG
00820 nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors));
00821 nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads));
00822 #endif
00823
00824 Collector *collector = get_collector_ptr(collector_index);
00825 InternalThread *thread = get_thread_ptr(thread_index);
00826
00827 if (client_is_connected() && collector->is_active() && thread->_is_active) {
00828 LightMutexHolder holder(thread->_thread_lock);
00829 if (collector->_per_thread[thread_index]._nested_count == 0) {
00830 if (pstats_cat.is_debug()) {
00831 pstats_cat.debug()
00832 << "Collector " << get_collector_fullname(collector_index)
00833 << " was already stopped in thread " << get_thread_name(thread_index)
00834 << "!\n";
00835 }
00836 return;
00837 }
00838
00839 collector->_per_thread[thread_index]._nested_count--;
00840
00841 if (collector->_per_thread[thread_index]._nested_count == 0) {
00842
00843
00844 thread->_frame_data.add_stop(collector_index, as_of);
00845 }
00846 }
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 void PStatClient::
00860 clear_level(int collector_index, int thread_index) {
00861 #ifdef _DEBUG
00862 nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors));
00863 nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads));
00864 #endif
00865
00866 Collector *collector = get_collector_ptr(collector_index);
00867 InternalThread *thread = get_thread_ptr(thread_index);
00868 LightMutexHolder holder(thread->_thread_lock);
00869
00870 collector->_per_thread[thread_index]._has_level = true;
00871 collector->_per_thread[thread_index]._level = 0.0;
00872 }
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883 void PStatClient::
00884 set_level(int collector_index, int thread_index, double level) {
00885 #ifdef _DEBUG
00886 nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors));
00887 nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads));
00888 #endif
00889
00890 Collector *collector = get_collector_ptr(collector_index);
00891 InternalThread *thread = get_thread_ptr(thread_index);
00892
00893
00894
00895
00896
00897 LightMutexHolder holder(thread->_thread_lock);
00898
00899 level *= collector->get_def(this, collector_index)->_factor;
00900
00901 collector->_per_thread[thread_index]._has_level = true;
00902 collector->_per_thread[thread_index]._level = level;
00903 }
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 void PStatClient::
00917 add_level(int collector_index, int thread_index, double increment) {
00918 #ifdef _DEBUG
00919 nassertv(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors));
00920 nassertv(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads));
00921 #endif
00922
00923 Collector *collector = get_collector_ptr(collector_index);
00924 InternalThread *thread = get_thread_ptr(thread_index);
00925 LightMutexHolder holder(thread->_thread_lock);
00926
00927 increment *= collector->get_def(this, collector_index)->_factor;
00928
00929 collector->_per_thread[thread_index]._has_level = true;
00930 collector->_per_thread[thread_index]._level += increment;
00931 }
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 double PStatClient::
00942 get_level(int collector_index, int thread_index) const {
00943 #ifdef _DEBUG
00944 nassertr(collector_index >= 0 && collector_index < AtomicAdjust::get(_num_collectors), 0.0f);
00945 nassertr(thread_index >= 0 && thread_index < AtomicAdjust::get(_num_threads), 0.0f);
00946 #endif
00947
00948 Collector *collector = get_collector_ptr(collector_index);
00949 InternalThread *thread = get_thread_ptr(thread_index);
00950 LightMutexHolder holder(thread->_thread_lock);
00951
00952 double factor = collector->get_def(this, collector_index)->_factor;
00953
00954 return collector->_per_thread[thread_index]._level / factor;
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969 void PStatClient::
00970 start_clock_wait() {
00971 _clock_wait_pcollector.start();
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 void PStatClient::
00987 start_clock_busy_wait() {
00988 _clock_wait_pcollector.stop();
00989 _clock_busy_wait_pcollector.start();
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 void PStatClient::
01005 stop_clock_wait() {
01006 _clock_busy_wait_pcollector.stop();
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016 void PStatClient::
01017 add_collector(PStatClient::Collector *collector) {
01018 if (_num_collectors >= _collectors_size) {
01019
01020
01021
01022 int new_collectors_size = (_collectors_size == 0) ? 128 : _collectors_size * 2;
01023 CollectorPointer *new_collectors = new CollectorPointer[new_collectors_size];
01024 memcpy(new_collectors, _collectors, _num_collectors * sizeof(CollectorPointer));
01025 AtomicAdjust::set_ptr(_collectors, new_collectors);
01026 AtomicAdjust::set(_collectors_size, new_collectors_size);
01027
01028
01029
01030
01031
01032
01033
01034
01035 new_collectors[_num_collectors] = collector;
01036 AtomicAdjust::inc(_num_collectors);
01037
01038 } else {
01039 CollectorPointer *collectors = (CollectorPointer *)_collectors;
01040 collectors[_num_collectors] = collector;
01041 AtomicAdjust::inc(_num_collectors);
01042 }
01043 }
01044
01045
01046
01047
01048
01049
01050
01051
01052 void PStatClient::
01053 add_thread(PStatClient::InternalThread *thread) {
01054 if (_num_threads >= _threads_size) {
01055
01056
01057
01058 int new_threads_size = (_threads_size == 0) ? 128 : _threads_size * 2;
01059 ThreadPointer *new_threads = new ThreadPointer[new_threads_size];
01060 memcpy(new_threads, _threads, _num_threads * sizeof(ThreadPointer));
01061
01062
01063 AtomicAdjust::set_ptr(_threads, new_threads);
01064 AtomicAdjust::set(_threads_size, new_threads_size);
01065
01066
01067
01068
01069
01070
01071
01072
01073 new_threads[_num_threads] = thread;
01074 AtomicAdjust::inc(_num_threads);
01075
01076 } else {
01077 ThreadPointer *threads = (ThreadPointer *)_threads;
01078 threads[_num_threads] = thread;
01079 AtomicAdjust::inc(_num_threads);
01080 }
01081 }
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 void PStatClient::
01093 deactivate_hook(Thread *thread) {
01094
01095
01096
01097
01098 if (_impl == NULL) {
01099 return;
01100 }
01101 int thread_index = thread->get_pstats_index();
01102 InternalThread *ithread = get_thread_ptr(thread_index);
01103
01104 if (ithread->_thread_active) {
01105
01106
01107 double now = _impl->get_real_time();
01108 ithread->_frame_data.add_start(_thread_block_pcollector.get_index(), now);
01109 ithread->_thread_active = false;
01110 }
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121 void PStatClient::
01122 activate_hook(Thread *thread) {
01123
01124
01125
01126
01127 if (_impl == NULL) {
01128 return;
01129 }
01130
01131 InternalThread *ithread = get_thread_ptr(thread->get_pstats_index());
01132
01133 if (!ithread->_thread_active) {
01134 double now = _impl->get_real_time();
01135 ithread->_frame_data.add_stop(_thread_block_pcollector.get_index(), now);
01136 ithread->_thread_active = true;
01137 }
01138 }
01139
01140
01141
01142
01143
01144
01145 void PStatClient::Collector::
01146 make_def(const PStatClient *client, int this_index) {
01147 ReMutexHolder holder(client->_lock);
01148 if (_def == (PStatCollectorDef *)NULL) {
01149 _def = new PStatCollectorDef(this_index, _name);
01150 if (_parent_index != this_index) {
01151 const PStatCollectorDef *parent_def =
01152 client->get_collector_def(_parent_index);
01153 _def->set_parent(*parent_def);
01154 }
01155 initialize_collector_def(client, _def);
01156 }
01157 }
01158
01159
01160
01161
01162
01163
01164 PStatClient::InternalThread::
01165 InternalThread(Thread *thread) :
01166 _thread(thread),
01167 _name(thread->get_name()),
01168 _sync_name(thread->get_sync_name()),
01169 _is_active(false),
01170 _frame_number(0),
01171 _next_packet(0.0),
01172 _thread_active(true),
01173 _thread_lock(string("PStatClient::InternalThread ") + thread->get_name())
01174 {
01175 }
01176
01177 #endif // DO_PSTATS