private void AsyncEndReceive(IAsyncResult iar) { // Asynchronous receive operations will complete here through the call // to AsyncBeginReceive // aquire a reader lock rwLock.AcquireReaderLock(-1); if (!shutdownFlag) { // start another receive - this keeps the server going! AsyncBeginReceive(); // get the buffer that was created in AsyncBeginReceive // this is the received data WrappedObject <UDPPacketBuffer> wrappedBuffer = (WrappedObject <UDPPacketBuffer>)iar.AsyncState; UDPPacketBuffer buffer = wrappedBuffer.Instance; //UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; try { // get the length of data actually read from the socket, store it with the // buffer buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); // this operation is now complete, decrement the reference count Interlocked.Decrement(ref rwOperationCount); // we're done with the socket, release the reader lock rwLock.ReleaseReaderLock(); // call the abstract method PacketReceived(), passing the buffer that // has just been filled from the socket read. PacketReceived(buffer); } catch (SocketException) { // something bad happened //SecondLife.LogStatic( // "A SocketException occurred in UDPServer.AsyncEndReceive()", // Helpers.LogLevel.Error, se); // an error occurred, therefore the operation is void. Decrement the reference count. Interlocked.Decrement(ref rwOperationCount); // we're done with the socket for now, release the reader lock. rwLock.ReleaseReaderLock(); } wrappedBuffer.Dispose(); } else { // nothing bad happened, but we are done with the operation // decrement the reference count and release the reader lock Interlocked.Decrement(ref rwOperationCount); rwLock.ReleaseReaderLock(); } }
/// <summary> /// Checks an instance of <c>T</c> from the pool. If the pool is not sufficient to /// allow the checkout, a new segment is created. /// </summary> /// <returns>A <c>WrappedObject</c> around the instance of <c>T</c>. To check /// the instance back into the segment, be sureto dispose the WrappedObject /// when finished. </returns> public WrappedObject <T> CheckOut() { if (_disposed) { throw new ObjectDisposedException("ObjectPoolBase"); } // It's key that this CheckOut always, always, uses a pooled object // from the oldest available segment. This will help keep the "newer" // segments from being used - which in turn, makes them eligible // for deletion. lock (_syncRoot) { ObjectPoolSegment <T> targetSegment = null; // find the oldest segment that has items available for checkout for (int i = 0; i < _activeSegment; i++) { ObjectPoolSegment <T> segment; if (_segments.TryGetValue(i, out segment) == true) { if (segment.AvailableItems > 0) { targetSegment = segment; break; } } } if (targetSegment == null) { // We couldn't find a sigment that had any available space in it, // so it's time to create a new segment. // Before creating the segment, do a GC to make sure the heap // is compacted. if (_gc) { GC.Collect(); } targetSegment = CreateSegment(true); if (_gc) { GC.Collect(); } _segments.Add(targetSegment.SegmentNumber, targetSegment); } WrappedObject <T> obj = new WrappedObject <T>(this, targetSegment, targetSegment.CheckOutObject()); return(obj); } }
private void AsyncBeginReceive() { // this method actually kicks off the async read on the socket. // we aquire a reader lock here to ensure that no other thread // is trying to set shutdownFlag and close the socket. rwLock.AcquireReaderLock(-1); if (!shutdownFlag) { // increment the count of pending operations Interlocked.Increment(ref rwOperationCount); // allocate a packet buffer WrappedObject <UDPPacketBuffer> buf = _bufferPool.CheckOut(); //UDPPacketBuffer buf = new UDPPacketBuffer(); try { // kick off an async read udpSocket.BeginReceiveFrom( buf.Instance.Data, //buf.Data, 0, UDPPacketBuffer.BUFFER_SIZE, SocketFlags.None, ref buf.Instance.RemoteEndPoint, new AsyncCallback(AsyncEndReceive), buf); } catch (SocketException) { // something bad happened //SecondLife.LogStatic( // "A SocketException occurred in UDPServer.AsyncBeginReceive()", // Helpers.LogLevel.Error, se); // an error occurred, therefore the operation is void. Decrement the reference count. Interlocked.Decrement(ref rwOperationCount); } } // we're done with the socket for now, release the reader lock. rwLock.ReleaseReaderLock(); }