From 8043970df78b2a3d0f7a5872a8167190c8899d6f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 8 Nov 2013 02:22:10 -0800 Subject: [PATCH] bug fixes to JurisdictionListener, PacketSender, addition of packetsToSendCount() to Voxels JS --- .../src/voxels/VoxelScriptingInterface.cpp | 7 +++- .../src/voxels/VoxelScriptingInterface.h | 4 +++ libraries/shared/src/PacketSender.cpp | 35 ++++++++++++++----- .../shared/src/ReceivedPacketProcessor.cpp | 9 ++++- .../shared/src/ReceivedPacketProcessor.h | 5 ++- libraries/voxels/src/JurisdictionListener.cpp | 9 +++-- libraries/voxels/src/JurisdictionListener.h | 2 +- 7 files changed, 56 insertions(+), 15 deletions(-) diff --git a/assignment-client/src/voxels/VoxelScriptingInterface.cpp b/assignment-client/src/voxels/VoxelScriptingInterface.cpp index 5b1a296aa7..687b0fe0b8 100644 --- a/assignment-client/src/voxels/VoxelScriptingInterface.cpp +++ b/assignment-client/src/voxels/VoxelScriptingInterface.cpp @@ -40,4 +40,9 @@ void VoxelScriptingInterface::queueVoxelDelete(float x, float y, float z, float VoxelDetail deleteVoxelDetail = {x, y, z, scale, 0, 0, 0}; _voxelPacketSender.queueVoxelEditMessages(PACKET_TYPE_ERASE_VOXEL, 1, &deleteVoxelDetail); -} \ No newline at end of file +} + + +int VoxelScriptingInterface::packetsToSendCount() const { + return _voxelPacketSender.packetsToSendCount(); +} diff --git a/assignment-client/src/voxels/VoxelScriptingInterface.h b/assignment-client/src/voxels/VoxelScriptingInterface.h index a2c18b8018..60a4fbc0b1 100644 --- a/assignment-client/src/voxels/VoxelScriptingInterface.h +++ b/assignment-client/src/voxels/VoxelScriptingInterface.h @@ -49,6 +49,10 @@ public slots: /// \param z the z-coordinate of the voxel (in VS space) /// \param scale the scale of the voxel (in VS space) void queueVoxelDelete(float x, float y, float z, float scale); + + /// get the current number of pending, queued, but unsent packets + int packetsToSendCount() const; + private: /// attached VoxelEditPacketSender that handles queuing and sending of packets to VS VoxelEditPacketSender _voxelPacketSender; diff --git a/libraries/shared/src/PacketSender.cpp b/libraries/shared/src/PacketSender.cpp index c03ef21bea..76d4ac47ad 100644 --- a/libraries/shared/src/PacketSender.cpp +++ b/libraries/shared/src/PacketSender.cpp @@ -39,8 +39,11 @@ void PacketSender::queuePacketForSending(sockaddr& address, unsigned char* packe } bool PacketSender::process() { + bool hasSlept = false; uint64_t USECS_PER_SECOND = 1000 * 1000; + uint64_t USECS_SMALL_ADJUST = 2 * 1000; // approaximate 2ms uint64_t SEND_INTERVAL_USECS = (_packetsPerSecond == 0) ? USECS_PER_SECOND : (USECS_PER_SECOND / _packetsPerSecond); + uint64_t INTERVAL_SLEEP_USECS = (SEND_INTERVAL_USECS > USECS_SMALL_ADJUST) ? SEND_INTERVAL_USECS - USECS_SMALL_ADJUST : SEND_INTERVAL_USECS; // keep track of our process call times, so we have a reliable account of how often our caller calls us uint64_t now = usecTimestampNow(); @@ -50,7 +53,8 @@ bool PacketSender::process() { if (_packets.size() == 0) { if (isThreaded()) { - usleep(SEND_INTERVAL_USECS); + usleep(INTERVAL_SLEEP_USECS); + hasSlept = true; } else { return isStillRunning(); // in non-threaded mode, if there's nothing to do, just return, keep running till they terminate us } @@ -62,6 +66,7 @@ bool PacketSender::process() { // if we're in non-threaded mode, then we actually need to determine how many packets to send per call to process // based on how often we get called... We do this by keeping a running average of our call times, and we determine // how many packets to send per call + if (!isThreaded()) { int averageCallTime; const int TRUST_AVERAGE_AFTER = AVERAGE_CALL_TIME_SAMPLES * 2; @@ -89,8 +94,6 @@ bool PacketSender::process() { int packetsLeft = _packets.size(); bool keepGoing = packetsLeft > 0; while (keepGoing) { - uint64_t SEND_INTERVAL_USECS = (_packetsPerSecond == 0) ? USECS_PER_SECOND : (USECS_PER_SECOND / _packetsPerSecond); - lock(); NetworkPacket& packet = _packets.front(); NetworkPacket temporary = packet; // make a copy @@ -117,14 +120,15 @@ bool PacketSender::process() { if (keepGoing) { now = usecTimestampNow(); uint64_t elapsed = now - _lastSendTime; - int usecToSleep = SEND_INTERVAL_USECS - elapsed; - + int usecToSleep = INTERVAL_SLEEP_USECS - elapsed; + // we only sleep in non-threaded mode if (usecToSleep > 0) { - if (usecToSleep > SEND_INTERVAL_USECS) { - usecToSleep = SEND_INTERVAL_USECS; + if (usecToSleep > INTERVAL_SLEEP_USECS) { + usecToSleep = INTERVAL_SLEEP_USECS; } usleep(usecToSleep); + hasSlept = true; } } @@ -133,8 +137,21 @@ bool PacketSender::process() { keepGoing = (packetsThisCall < packetsPerCall) && (packetsLeft > 0); } + // if threaded and we only sent one packet, we still want to sleep.... + if (isThreaded() && !hasSlept) { + now = usecTimestampNow(); + uint64_t elapsed = now - _lastSendTime; + int usecToSleep = INTERVAL_SLEEP_USECS - elapsed; + // we only sleep in non-threaded mode + if (usecToSleep > 0) { + if (usecToSleep > INTERVAL_SLEEP_USECS) { + usecToSleep = INTERVAL_SLEEP_USECS; + } + usleep(usecToSleep); + } + } + _lastSendTime = now; } - - return isStillRunning(); // keep running till they terminate us + return isStillRunning(); } diff --git a/libraries/shared/src/ReceivedPacketProcessor.cpp b/libraries/shared/src/ReceivedPacketProcessor.cpp index c1d0a84f0f..a46cd36dbe 100644 --- a/libraries/shared/src/ReceivedPacketProcessor.cpp +++ b/libraries/shared/src/ReceivedPacketProcessor.cpp @@ -12,6 +12,10 @@ #include "ReceivedPacketProcessor.h" #include "SharedUtil.h" +ReceivedPacketProcessor::ReceivedPacketProcessor() { + _dontSleep = false; +} + void ReceivedPacketProcessor::queueReceivedPacket(sockaddr& address, unsigned char* packetData, ssize_t packetLength) { // Make sure our Node and NodeList knows we've heard from this node. Node* node = NodeList::getInstance()->nodeWithAddress(&address); @@ -26,7 +30,10 @@ void ReceivedPacketProcessor::queueReceivedPacket(sockaddr& address, unsigned ch } bool ReceivedPacketProcessor::process() { - if (_packets.size() == 0) { + + // If a derived class handles process sleeping, like the JurisdiciontListener, then it can set + // this _dontSleep member and we will honor that request. + if (_packets.size() == 0 && !_dontSleep) { const uint64_t RECEIVED_THREAD_SLEEP_INTERVAL = (1000 * 1000)/60; // check at 60fps usleep(RECEIVED_THREAD_SLEEP_INTERVAL); } diff --git a/libraries/shared/src/ReceivedPacketProcessor.h b/libraries/shared/src/ReceivedPacketProcessor.h index 78017bffd7..f36473ae12 100644 --- a/libraries/shared/src/ReceivedPacketProcessor.h +++ b/libraries/shared/src/ReceivedPacketProcessor.h @@ -17,6 +17,7 @@ /// Generalized threaded processor for handling received inbound packets. class ReceivedPacketProcessor : public virtual GenericThread { public: + ReceivedPacketProcessor(); /// Add packet from network receive thread to the processing queue. /// \param sockaddr& senderAddress the address of the sender @@ -30,7 +31,7 @@ public: /// How many received packets waiting are to be processed int packetsToProcessCount() const { return _packets.size(); } - + protected: /// Callback for processing of recieved packets. Implement this to process the incoming packets. /// \param sockaddr& senderAddress the address of the sender @@ -42,6 +43,8 @@ protected: /// Implements generic processing behavior for this thread. virtual bool process(); + bool _dontSleep; + private: std::vector _packets; diff --git a/libraries/voxels/src/JurisdictionListener.cpp b/libraries/voxels/src/JurisdictionListener.cpp index 6871c881df..223b602dfa 100644 --- a/libraries/voxels/src/JurisdictionListener.cpp +++ b/libraries/voxels/src/JurisdictionListener.cpp @@ -19,6 +19,7 @@ JurisdictionListener::JurisdictionListener(PacketSenderNotify* notify) : PacketSender(notify, JurisdictionListener::DEFAULT_PACKETS_PER_SECOND) { + ReceivedPacketProcessor::_dontSleep = true; // we handle sleeping so this class doesn't need to NodeList* nodeList = NodeList::getInstance(); nodeList->addHook(this); } @@ -53,8 +54,11 @@ bool JurisdictionListener::queueJurisdictionRequest() { } } - // set our packets per second to be the number of nodes - setPacketsPerSecond(nodeCount); + if (nodeCount > 0){ + setPacketsPerSecond(nodeCount); + } else { + setPacketsPerSecond(NO_SERVER_CHECK_RATE); + } // keep going if still running return isStillRunning(); @@ -84,5 +88,6 @@ bool JurisdictionListener::process() { // NOTE: This will sleep if there are no pending packets to process continueProcessing = ReceivedPacketProcessor::process(); } + return continueProcessing; } diff --git a/libraries/voxels/src/JurisdictionListener.h b/libraries/voxels/src/JurisdictionListener.h index 0a614446ed..8f7c4e6cf6 100644 --- a/libraries/voxels/src/JurisdictionListener.h +++ b/libraries/voxels/src/JurisdictionListener.h @@ -24,6 +24,7 @@ class JurisdictionListener : public NodeListHook, public PacketSender, public ReceivedPacketProcessor { public: static const int DEFAULT_PACKETS_PER_SECOND = 1; + static const int NO_SERVER_CHECK_RATE=60; JurisdictionListener(PacketSenderNotify* notify = NULL); ~JurisdictionListener(); @@ -50,6 +51,5 @@ private: NodeToJurisdictionMap _jurisdictions; bool queueJurisdictionRequest(); - }; #endif // __shared__JurisdictionListener__