Merge branch 'release/1.10.x'

This commit is contained in:
rdb 2022-12-12 17:19:10 +01:00
commit e1b4083d6d
15 changed files with 211 additions and 81 deletions

View File

@ -8,9 +8,8 @@ from direct.showbase.PythonUtil import itype, deeptype, fastRepr
from direct.showbase.Job import Job
from direct.showbase.JobManagerGlobal import jobMgr
from direct.showbase.MessengerGlobal import messenger
import direct.showbase.DConfig as config
from panda3d.core import ConfigVariableBool
import gc
import types
GarbageCycleCountAnnounceEvent = 'announceGarbageCycleDesc2num'
@ -213,7 +212,7 @@ class GarbageReport(Job):
startIndex = 0
# + 1 to include a reference back to the first object
endIndex = numObjs + 1
if type(objs[-1]) is types.InstanceType and type(objs[0]) is dict:
if type(objs[0]) is dict and hasattr(objs[-1], '__dict__'):
startIndex -= 1
endIndex -= 1
@ -222,7 +221,7 @@ class GarbageReport(Job):
numToSkip -= 1
continue
obj = objs[index]
if type(obj) is types.InstanceType:
if hasattr(obj, '__dict__'):
if not objAlreadyRepresented:
cycleBySyntax += '%s' % obj.__class__.__name__
cycleBySyntax += '.'
@ -307,7 +306,7 @@ class GarbageReport(Job):
while n > 0:
yield None
digits += 1
n /= 10
n = n // 10
digits = digits
format = '%0' + '%s' % digits + 'i:%s \t%s'
@ -562,7 +561,7 @@ class _CFGLGlobals:
def checkForGarbageLeaks():
gc.collect()
numGarbage = len(gc.garbage)
if numGarbage > 0 and config.GetBool('auto-garbage-logging', 0):
if numGarbage > 0 and ConfigVariableBool('auto-garbage-logging', False):
if numGarbage != _CFGLGlobals.LastNumGarbage:
print("")
gr = GarbageReport('found garbage', threaded=False, collect=False)
@ -572,7 +571,7 @@ def checkForGarbageLeaks():
messenger.send(GarbageCycleCountAnnounceEvent, [gr.getDesc2numDict()])
gr.destroy()
notify = directNotify.newCategory("GarbageDetect")
if config.GetBool('allow-garbage-cycles', 1):
if ConfigVariableBool('allow-garbage-cycles', True):
func = notify.warning
else:
func = notify.error

View File

@ -76,6 +76,8 @@ endif()
set(P3PRC_IGATEEXT
configVariable_ext.cxx
configVariable_ext.h
notify_ext.cxx
notify_ext.h
streamReader_ext.cxx
streamReader_ext.h
streamWriter_ext.cxx

View File

@ -0,0 +1,48 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file notify_ext.cxx
* @author rdb
* @date 2022-12-09
*/
#include "notify_ext.h"
#ifdef HAVE_PYTHON
/**
* Changes the ostream that all subsequent Notify messages will be written to.
* If the previous ostream was set with delete_later = true, this will delete
* the previous ostream. If ostream_ptr is None, this resets the default to
* cerr.
*/
void Extension<Notify>::
set_ostream_ptr(PyObject *ostream_ptr, bool delete_later) {
extern struct Dtool_PyTypedObject Dtool_std_ostream;
if (ostream_ptr == Py_None) {
_this->set_ostream_ptr(nullptr, false);
return;
}
std::ostream *ptr = (std::ostream *)DTOOL_Call_GetPointerThisClass(ostream_ptr, &Dtool_std_ostream, 1, "Notify.set_ostream_ptr", false, true);
if (ptr == nullptr) {
return;
}
// Since we now have a reference to this class on the C++ end, make sure
// that the ostream isn't being destructed when its Python wrapper expires.
// Note that this may cause a memory leak if delete_later is not set, but
// since these pointers are usually set once for the rest of time, this is
// considered less of a problem than having the Python object destroy the
// object while C++ is still using it. See GitHub #1371.
((Dtool_PyInstDef *)ostream_ptr)->_memory_rules = false;
_this->set_ostream_ptr(ptr, delete_later);
}
#endif // HAVE_PYTHON

View File

@ -0,0 +1,37 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file notify_ext.h
* @author rdb
* @date 2022-12-09
*/
#ifndef NOTIFY_EXT_H
#define NOTIFY_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "pnotify.h"
#include "py_panda.h"
/**
* This class defines the extension methods for Notify, which are called
* instead of any C++ methods with the same prototype.
*/
template<>
class Extension<Notify> : public ExtensionBase<Notify> {
public:
void set_ostream_ptr(PyObject *ostream_ptr, bool delete_later);
};
#endif // HAVE_PYTHON
#endif // NOTIFY_EXT_H

View File

@ -1,3 +1,4 @@
#include "configVariable_ext.cxx"
#include "notify_ext.cxx"
#include "streamReader_ext.cxx"
#include "streamWriter_ext.cxx"

View File

@ -35,7 +35,11 @@ PUBLISHED:
Notify();
~Notify();
#if defined(CPPPARSER) && defined(HAVE_PYTHON)
EXTEND void set_ostream_ptr(PyObject *ostream_ptr, bool delete_later);
#else
void set_ostream_ptr(std::ostream *ostream_ptr, bool delete_later);
#endif
std::ostream *get_ostream_ptr() const;
typedef bool AssertHandler(const char *expression, int line,

View File

@ -43,35 +43,12 @@
#import <OpenGL/OpenGL.h>
#import <Carbon/Carbon.h>
#include <sys/sysctl.h>
TypeHandle CocoaGraphicsWindow::_type_handle;
#ifndef MAC_OS_X_VERSION_10_15
#define NSAppKitVersionNumber10_14 1671
#endif
/**
* Returns true if this is an arm64-based mac.
*/
static int is_arm64_mac() {
#ifdef __aarch64__
return 1;
#elif defined(__x86_64__)
// Running in Rosetta 2?
static int ret = -1;
if (ret < 0) {
size_t size = sizeof(ret);
if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) == -1) {
ret = 0;
}
}
return ret;
#else
return 0;
#endif
}
/**
*
*/
@ -209,29 +186,17 @@ begin_frame(FrameMode mode, Thread *current_thread) {
cocoagsg->lock_context();
// Set the drawable.
if (_properties.get_fullscreen() && !is_arm64_mac()) {
// Fullscreen. Note that this call doesn't work with the newer
// Metal-based OpenGL drivers.
CGLError err = CGLSetFullScreenOnDisplay((CGLContextObj) [cocoagsg->_context CGLContextObj], CGDisplayIDToOpenGLDisplayMask(_display));
if (err != kCGLNoError) {
cocoadisplay_cat.error()
<< "Failed call to CGLSetFullScreenOnDisplay with display mask "
<< CGDisplayIDToOpenGLDisplayMask(_display) << ": " << CGLErrorString(err) << "\n";
return false;
}
} else {
// Although not recommended, it is technically possible to use the same
// context with multiple different-sized windows. If that happens, the
// context needs to be updated accordingly.
if ([cocoagsg->_context view] != _view) {
// XXX I'm not 100% sure that changing the view requires it to update.
_context_needs_update = true;
[cocoagsg->_context setView:_view];
// Although not recommended, it is technically possible to use the same
// context with multiple different-sized windows. If that happens, the
// context needs to be updated accordingly.
if ([cocoagsg->_context view] != _view) {
// XXX I'm not 100% sure that changing the view requires it to update.
_context_needs_update = true;
[cocoagsg->_context setView:_view];
if (cocoadisplay_cat.is_spam()) {
cocoadisplay_cat.spam()
<< "Switching context to view " << _view << "\n";
}
if (cocoadisplay_cat.is_spam()) {
cocoadisplay_cat.spam()
<< "Switching context to view " << _view << "\n";
}
}

View File

@ -113,8 +113,8 @@ pad_bytes(size_t size) {
// Now append the data.
// It is very important that we *don't* do this reserve() operation. See
// the further comments in append_data(), below. _data.reserve(_data.size()
// + size);
// the further comments in append_data(), below.
//_data.reserve(_data.size() + size);
while (size > 0) {
_data.push_back('\0');
@ -146,7 +146,8 @@ append_data(const void *data, size_t size) {
// actually slows it down on Windows, which takes the reserve() request as a
// fixed size the array should be set to (!) instead of as a minimum size to
// guarantee. This forces the array to reallocate itself with *every* call
// to append_data! _data.reserve(_data.size() + size);
// to append_data!
//_data.reserve(_data.size() + size);
_data.v().insert(_data.v().end(), (const unsigned char *)data,
(const unsigned char *)data + size);

View File

@ -287,7 +287,7 @@ PUBLISHED:
// bounding volumes.
void set_bounds_type(BoundingVolume::BoundsType bounds_type);
BoundingVolume::BoundsType get_bounds_type() const;
MAKE_PROPERTY(bounds_type, get_bounds_type);
MAKE_PROPERTY(bounds_type, get_bounds_type, set_bounds_type);
void set_bounds(const BoundingVolume *volume);
INLINE void clear_bounds();

View File

@ -33,7 +33,8 @@ ConfigVariableDouble pstats_max_rate
("pstats-max-rate", 1000.0,
PRC_DESC("The maximum number of packets per second, per thread, to send "
"to the remote PStats server. A packet is defined as a single "
"UDP packet, or each 1024 bytes of a TCP message."));
"UDP packet, or each 1024 bytes of a TCP message. Set this to a "
"negative number to disable the limit."));
ConfigVariableBool pstats_threaded_write
("pstats-threaded-write", true,

View File

@ -61,6 +61,10 @@ encode(Datagram &datagram) const {
}
break;
case T_expire_thread:
datagram.add_uint16(_first_thread_index);
break;
default:
pstats_cat.error()
<< "Invalid PStatClientControlMessage::Type " << (int)_type << "\n";
@ -117,6 +121,10 @@ decode(const Datagram &datagram, PStatClientVersion *version) {
}
break;
case T_expire_thread:
_first_thread_index = source.get_uint16();
break;
case T_datagram:
// Not, strictly speaking, a control message.
return false;

View File

@ -39,6 +39,7 @@ public:
T_hello,
T_define_collectors,
T_define_threads,
T_expire_thread,
T_invalid
};

View File

@ -34,7 +34,6 @@ sort_time() {
*/
bool PStatFrameData::
write_datagram(Datagram &destination, PStatClient *client) const {
Data::const_iterator di;
if (_time_data.size() >= 65536 || _level_data.size() >= 65536) {
pstats_cat.info()
<< "Dropping frame with " << _time_data.size()
@ -43,16 +42,62 @@ write_datagram(Datagram &destination, PStatClient *client) const {
return false;
}
#if !defined(WORDS_BIGENDIAN) || defined(__GNUC__)
// Hand-roll this, significantly more efficient for many data points
size_t size = (_time_data.size() + _level_data.size()) * 6 + 4;
PTA_uchar array = destination.modify_array();
size_t offset = array.size();
array.resize(offset + size);
unsigned char *data = &array[0] + offset;
uint16_t *ptr = (uint16_t *)data;
#ifdef WORDS_BIGENDIAN
*ptr++ = __builtin_bswap16(_time_data.size());
for (const DataPoint &dp : _time_data) {
*ptr++ = __builtin_bswap16(dp._index);
PN_float32 v = (PN_float32)dp._value;
*(uint32_t *)ptr = __builtin_bswap32(reinterpret_cast<uint32_t &>(v));
ptr += 2;
}
*ptr++ = __builtin_bswap16(_level_data.size());
for (const DataPoint &dp : _level_data) {
*ptr++ = __builtin_bswap16(dp._index);
PN_float32 v = (PN_float32)dp._value;
*(uint32_t *)ptr = __builtin_bswap32(reinterpret_cast<uint32_t &>(v));
ptr += 2;
}
#else
*ptr++ = _time_data.size();
for (const DataPoint &dp : _time_data) {
*ptr++ = dp._index;
*(PN_float32 *)ptr = dp._value;
ptr += 2;
}
*ptr++ = _level_data.size();
for (const DataPoint &dp : _level_data) {
*ptr++ = dp._index;
*(PN_float32 *)ptr = dp._value;
ptr += 2;
}
#endif
#else
destination.add_uint16(_time_data.size());
for (di = _time_data.begin(); di != _time_data.end(); ++di) {
destination.add_uint16((*di)._index);
destination.add_float32((*di)._value);
for (const DataPoint &dp : _time_data) {
destination.add_uint16(dp._index);
destination.add_float32(dp._value);
}
destination.add_uint16(_level_data.size());
for (di = _level_data.begin(); di != _level_data.end(); ++di) {
destination.add_uint16((*di)._index);
destination.add_float32((*di)._value);
for (const DataPoint &dp : _level_data) {
destination.add_uint16(dp._index);
destination.add_float32(dp._value);
}
#endif
return true;
}
@ -61,25 +106,38 @@ write_datagram(Datagram &destination, PStatClient *client) const {
* Extracts the FrameData definition from the datagram.
*/
void PStatFrameData::
read_datagram(DatagramIterator &source, PStatClientVersion *) {
read_datagram(DatagramIterator &source, PStatClientVersion *version) {
clear();
int i;
int time_size = source.get_uint16();
for (i = 0; i < time_size; i++) {
nassertv(source.get_remaining_size() > 0);
DataPoint dp;
dp._index = source.get_uint16();
dp._value = source.get_float32();
_time_data.push_back(dp);
{
size_t time_size;
if (version->is_at_least(3, 2)) {
time_size = source.get_uint32();
} else {
time_size = source.get_uint16();
}
_time_data.resize(time_size);
for (DataPoint &dp : _time_data) {
nassertv(source.get_remaining_size() > 0);
dp._index = source.get_uint16();
dp._value = source.get_float32();
}
}
int level_size = source.get_uint16();
for (i = 0; i < level_size; i++) {
nassertv(source.get_remaining_size() > 0);
DataPoint dp;
dp._index = source.get_uint16();
dp._value = source.get_float32();
_level_data.push_back(dp);
{
size_t level_size;
if (version->is_at_least(3, 2)) {
level_size = source.get_uint32();
} else {
level_size = source.get_uint16();
}
_level_data.resize(level_size);
for (DataPoint &dp : _level_data) {
nassertv(source.get_remaining_size() > 0);
dp._index = source.get_uint16();
dp._value = source.get_float32();
}
}
//nassertv(source.get_remaining_size() == 0);
}

View File

@ -31,6 +31,7 @@ static const int current_pstat_minor_version = 0;
// Incremented to 2.1 on 5/21/01 to add support for TCP frame data.
// Incremented to 3.0 on 4/28/05 to bump TCP headers to 32 bits.
// Incremented to 3.1 on 11/29/22 to support nested start/stop pairs.
// Incremented to 3.2 on 12/10/22 to use 32-bit data counts, T_expire_thread.
/**
* Returns the current major version number of the PStats protocol. This is

View File

@ -195,7 +195,7 @@ handle_client_control_message(const PStatClientControlMessage &message) {
if (message._major_version != server_major_version ||
(message._major_version == server_major_version &&
message._minor_version > server_minor_version &&
(message._major_version != 3 || message._minor_version != 1))) {
(message._major_version != 3 || message._minor_version > 2))) {
_monitor->bad_version(message._client_hostname, message._client_progname,
message._client_pid,
message._major_version, message._minor_version,
@ -228,6 +228,10 @@ handle_client_control_message(const PStatClientControlMessage &message) {
}
break;
case PStatClientControlMessage::T_expire_thread:
// Ignore for now.
break;
default:
nout << "Invalid control message received from client.\n";
}