add set_handle_c_updates()

This commit is contained in:
David Rose
2007-05-17 18:44:45 +00:00
parent 2c7d1a8f60
commit 52d2ba31fd
4 changed files with 176 additions and 11 deletions

View File

@@ -33,6 +33,11 @@ class ClientRepositoryBase(ConnectionRepository):
self.context=100000
self.setClientDatagram(1)
self.deferredGenerates = []
self.deferredDoIds = {}
self.lastGenerate = 0
self.setDeferInterval(base.config.GetDouble('deferred-generate-interval', 0.2))
self.recorder = base.recorder
self.readDCFile(dcFileNames)
@@ -57,6 +62,23 @@ class ClientRepositoryBase(ConnectionRepository):
self.heartbeatStarted = 0
self.lastHeartbeat = 0
def setDeferInterval(self, deferInterval):
"""Specifies the minimum amount of time, in seconds, that must
elapse before generating any two DistributedObjects whose
class type is marked "deferrable". Set this to 0 to indicate
no deferring will occur."""
# Temporary condition for old Pandas.
if hasattr(self, 'setHandleCUpdates'):
self.deferInterval = deferInterval
self.setHandleCUpdates(self.deferInterval != 0)
else:
self.deferInterval = 0
if self.deferredGenerates:
taskMgr.remove('deferredGenerate')
taskMgr.doMethodLater(self.deferInterval, self.__doDeferredGenerate, 'deferredGenerate')
## def queryObjectAll(self, doID, context=0):
## """
## Get a one-time snapshot look at the object.
@@ -154,13 +176,98 @@ class ClientRepositoryBase(ConnectionRepository):
classId = di.getUint16()
# Get the DO Id
doId = di.getUint32()
dclass = self.dclassesByNumber[classId]
deferrable = getattr(dclass.getClassDef(), 'deferrable', False)
if not self.deferInterval:
deferrable = False
now = globalClock.getFrameTime()
if self.deferredGenerates or deferrable:
# This object is deferrable, or there are already deferred
# objects in the queue (so all objects have to be held
# up).
if self.deferredGenerates or now - self.lastGenerate < self.deferInterval:
# Queue it for later.
assert(self.notify.debug("deferring generate for %s %s" % (dclass.getName(), doId)))
self.deferredGenerates.append(doId)
# Keep a copy of the datagram, and move the di to the copy
dg = Datagram(di.getDatagram())
di = DatagramIterator(dg, di.getCurrentIndex())
self.deferredDoIds[doId] = ((parentId, zoneId, classId, doId, di), deferrable, dg, [])
if len(self.deferredGenerates) == 1:
# We just deferred the first object on the queue;
# start the task to generate it.
taskMgr.remove('deferredGenerate')
taskMgr.doMethodLater(self.deferInterval, self.__doDeferredGenerate, 'deferredGenerate')
else:
# We haven't generated any deferrable objects in a
# while, so it's safe to go ahead and generate this
# one immediately.
self.lastGenerate = now
self.__doGenerate(parentId, zoneId, classId, doId, di)
else:
self.__doGenerate(parentId, zoneId, classId, doId, di)
def __doGenerate(self, parentId, zoneId, classId, doId, di):
# Look up the dclass
dclass = self.dclassesByNumber[classId]
assert(self.notify.debug("performing generate for %s %s" % (dclass.getName(), doId)))
dclass.startGenerate()
# Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
dclass.stopGenerate()
def flushGenerates(self):
""" Forces all pending generates to be performed immediately. """
while self.deferredGenerates:
doId = self.deferredGenerates[0]
del self.deferredGenerates[0]
if doId in self.deferredDoIds:
args, deferrable, dg, updates = self.deferredDoIds[doId]
del self.deferredDoIds[doId]
self.__doGenerate(*args)
for dg, di in updates:
self.__doUpdate(doId, di)
taskMgr.remove('deferredGenerate')
def __doDeferredGenerate(self, task):
""" This is the task that generates an object on the deferred
queue. """
now = globalClock.getFrameTime()
if now - self.lastGenerate < self.deferInterval:
# Come back later.
return Task.again
while self.deferredGenerates:
# Generate the next deferred object.
doId = self.deferredGenerates[0]
del self.deferredGenerates[0]
if doId in self.deferredDoIds:
args, deferrable, dg, updates = self.deferredDoIds[doId]
del self.deferredDoIds[doId]
self.__doGenerate(*args)
for dg, di in updates:
self.__doUpdate(doId, di)
if deferrable:
# If this was an actual deferrable object, wait
# for the next pass to generate any more.
self.lastGenerate = now
return Task.again
# All objects are generaetd.
return Task.done
def handleGenerateWithRequiredOtherOwner(self, di):
# Get the class Id
classId = di.getUint16()
@@ -360,6 +467,16 @@ class ClientRepositoryBase(ConnectionRepository):
cache.cache(distObj)
else:
distObj.deleteOrDelay()
elif self.deferredDoIds.has_key(doId):
# The object had been deferred. Great; we don't even have
# to generate it now.
del self.deferredDoIds[doId]
i = self.deferredGenerates.index(doId)
del self.deferredGenerates[i]
if len(self.deferredGenerates) == 0:
taskMgr.remove('deferredGenerate')
else:
self._logFailedDisable(doId, ownerView)
@@ -393,9 +510,23 @@ class ClientRepositoryBase(ConnectionRepository):
"""
# Get the DO Id
doId = di.getUint32()
#print("Updating " + str(doId))
# Find the DO
if doId in self.deferredDoIds:
# This object hasn't really been generated yet. Sit on
# the update.
args, deferrable, dg0, updates = self.deferredDoIds[doId]
# Keep a copy of the datagram, and move the di to the copy
dg = Datagram(di.getDatagram())
di = DatagramIterator(dg, di.getCurrentIndex())
updates.append((dg, di))
else:
# This object has been fully generated. It's OK to update.
self.__doUpdate(doId, di)
def __doUpdate(self, doId, di):
# Find the DO
do = self.doId2do.get(doId)
if do is not None:
# Let the dclass finish the job

View File

@@ -39,6 +39,30 @@ has_owner_view() const {
return _has_owner_view;
}
////////////////////////////////////////////////////////////////////
// Function: CConnectionRepository::set_handle_c_updates
// Access: Published
// Description: Set true to specify this repository should process
// distributed updates internally in C++ code, or false
// if it should return them to Python.
////////////////////////////////////////////////////////////////////
INLINE void CConnectionRepository::
set_handle_c_updates(bool handle_c_updates) {
_handle_c_updates = handle_c_updates;
}
////////////////////////////////////////////////////////////////////
// Function: CConnectionRepository::get_handle_c_updates
// Access: Published
// Description: Returns true if this repository will process
// distributed updates internally in C++ code, or false
// if it will return them to Python.
////////////////////////////////////////////////////////////////////
INLINE bool CConnectionRepository::
get_handle_c_updates() const {
return _handle_c_updates;
}
////////////////////////////////////////////////////////////////////
// Function: CConnectionRepository::set_client_datagram
// Access: Published

View File

@@ -70,7 +70,8 @@ CConnectionRepository(bool has_owner_view) :
// _msg_channels(),
_msg_sender(0),
_msg_type(0),
_has_owner_view(has_owner_view)
_has_owner_view(has_owner_view),
_handle_c_updates(true)
{
#if defined(HAVE_NET) && defined(SIMULATE_NETWORK_DELAY)
if (min_lag != 0.0 || max_lag != 0.0) {
@@ -290,14 +291,19 @@ check_datagram() {
#ifdef HAVE_PYTHON
case CLIENT_OBJECT_UPDATE_FIELD:
case STATESERVER_OBJECT_UPDATE_FIELD:
if (_has_owner_view) {
if (!handle_update_field_owner()) {
return false;
if (_handle_c_updates) {
if (_has_owner_view) {
if (!handle_update_field_owner()) {
return false;
}
} else {
if (!handle_update_field()) {
return false;
}
}
} else {
if (!handle_update_field()) {
return false;
}
// Let the caller (Python) deal with this update.
return true;
}
break;
#endif // HAVE_PYTHON
@@ -953,4 +959,4 @@ bool CConnectionRepository::handle_update_field_ai(PyObject *doId2do)
}
#endif // #ifdef WANT_NATIVE_NET
#endif // #ifdef HAVE_PYTHON
#endif // #ifdef HAVE_PYTHON

View File

@@ -62,13 +62,16 @@ class SocketStream;
////////////////////////////////////////////////////////////////////
class EXPCL_DIRECT CConnectionRepository {
PUBLISHED:
CConnectionRepository(bool has_owner_view=false);
CConnectionRepository(bool has_owner_view = false);
~CConnectionRepository();
INLINE DCFile &get_dc_file();
INLINE bool has_owner_view() const;
INLINE void set_handle_c_updates(bool handle_c_updates);
INLINE bool get_handle_c_updates() const;
INLINE void set_client_datagram(bool client_datagram);
INLINE bool get_client_datagram() const;
@@ -170,6 +173,7 @@ private:
DCFile _dc_file;
bool _has_owner_view;
bool _handle_c_updates;
bool _client_datagram;
bool _simulated_disconnect;
bool _verbose;