Fixed stupid buffer copy bug partially caused by some

last minute shifts in APIs.  Anyway, outbound TCP
broadcasts work again and are more efficient since the
Kernel callers can better control when their message
buffers are copied (in this case it isn't necessary so
we save a buffer copy).


git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7088 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
PSp..om 14 years ago
parent c552080030
commit b641b5670c
  1. 6
      engine/src/networking/com/jme3/network/base/DefaultServer.java
  2. 10
      engine/src/networking/com/jme3/network/kernel/Kernel.java
  3. 26
      engine/src/networking/com/jme3/network/kernel/tcp/SelectorKernel.java
  4. 6
      engine/src/networking/com/jme3/network/kernel/udp/UdpKernel.java

@ -160,9 +160,11 @@ public class DefaultServer implements Server
// Ignore the filter for the moment
if( message.isReliable() || fast == null ) {
reliable.broadcast( adapter, buffer, true );
// Don't need to copy the data because message protocol is already
// giving us a fresh buffer
reliable.broadcast( adapter, buffer, true, false );
} else {
fast.broadcast( adapter, buffer, false );
fast.broadcast( adapter, buffer, false, false );
}
}

@ -60,9 +60,15 @@ public interface Kernel
/**
* Dispatches the data to all endpoints managed by the
* kernel that match the specified endpoint filter..
* kernel that match the specified endpoint filter..
* If 'copy' is true then the implementation will copy the byte buffer
* before delivering it to endpoints. This allows the caller to reuse
* the data buffer. Though it is important that the buffer not be changed
* by another thread while this call is running.
* Only the bytes from data.position() to data.remaining() are sent.
*/
public void broadcast( Filter<? super Endpoint> filter, ByteBuffer data, boolean reliable );
public void broadcast( Filter<? super Endpoint> filter, ByteBuffer data, boolean reliable,
boolean copy );
/**
* Returns true if there are waiting envelopes.

@ -112,14 +112,19 @@ public class SelectorKernel extends AbstractKernel
}
}
public void broadcast( Filter<? super Endpoint> filter, ByteBuffer data, boolean reliable )
public void broadcast( Filter<? super Endpoint> filter, ByteBuffer data, boolean reliable,
boolean copy )
{
if( !reliable )
throw new UnsupportedOperationException( "Unreliable send not supported by this kernel." );
// Copy the data just once
byte[] copy = new byte[data.remaining()];
System.arraycopy(data.array(), data.position(), copy, 0, data.remaining());
if( copy )
{
// Copy the data just once
byte[] temp = new byte[data.remaining()];
System.arraycopy(data.array(), data.position(), temp, 0, data.remaining());
data = ByteBuffer.wrap(temp);
}
// Hand it to all of the endpoints that match our routing
for( NioEndpoint p : endpoints.values() ) {
@ -127,8 +132,10 @@ public class SelectorKernel extends AbstractKernel
if( filter != null && !filter.apply(p) )
continue;
// Give it the data
p.send( data, false, false );
// Give it the data... but let each endpoint track their
// own completion over the shared array of bytes by
// duplicating it
p.send( data.duplicate(), false, false );
}
// Wake up the selector so it can reinitialize its
@ -268,9 +275,10 @@ public class SelectorKernel extends AbstractKernel
// efficiently done as change requests... or simply
// keeping a thread-safe set of endpoints with pending
// writes. For most cases, it shouldn't matter.
for( Map.Entry<NioEndpoint,SelectionKey> e : endpointKeys.entrySet() ) {
if( e.getKey().hasPending() )
for( Map.Entry<NioEndpoint,SelectionKey> e : endpointKeys.entrySet() ) {
if( e.getKey().hasPending() ) {
e.getValue().interestOps(SelectionKey.OP_WRITE);
}
}
}
@ -363,7 +371,7 @@ public class SelectorKernel extends AbstractKernel
}
c.write( current );
// If we wrote all of that packet then we need to remove it
if( current.remaining() == 0 ) {
p.removePending();

@ -114,11 +114,15 @@ public class UdpKernel extends AbstractKernel
* Dispatches the data to all endpoints managed by the
* kernel. 'routing' is currently ignored.
*/
public void broadcast( Filter<? super Endpoint> filter, ByteBuffer data, boolean reliable )
public void broadcast( Filter<? super Endpoint> filter, ByteBuffer data, boolean reliable,
boolean copy )
{
if( reliable )
throw new UnsupportedOperationException( "Reliable send not supported by this kernel." );
// We ignore the copy flag because we know all outbound traffic
// goes instantly.
// Hand it to all of the endpoints that match our routing
for( UdpEndpoint p : socketEndpoints.values() ) {
// Does it match the filter?

Loading…
Cancel
Save