コード例 #1
0
ファイル: EventPollerTest.cs プロジェクト: zzms/Disruptor-net
        public void ShouldPollForEvents()
        {
            var pollSequence   = new Sequence();
            var bufferSequence = new Sequence();
            var gatingSequence = new Sequence();
            var sequencerMock  = new Mock <ISequencer>();
            var sequencer      = sequencerMock.Object;
            var handled        = false;
            Func <object, long, bool, bool> handler = (ev, seq, end) =>
            {
                handled = true;
                return(false);
            };
            var providerMock = new Mock <IDataProvider <object> >();
            var provider     = providerMock.Object;
            var poller       = EventPoller <object> .NewInstance(provider, sequencer, pollSequence, bufferSequence, gatingSequence);

            var @event = new object();

            object states = PollState.Idle;

            sequencerMock.SetupGet(x => x.Cursor)
            .Returns(() =>
            {
                switch ((PollState)states)
                {
                case PollState.Processing:
                    return(0L);

                case PollState.Gating:
                    return(0L);

                case PollState.Idle:
                    return(-1L);

                default:
                    throw new ArgumentOutOfRangeException();
                }
            });

            sequencerMock.Setup(x => x.GetHighestPublishedSequence(0L, -1L)).Returns(-1L);
            sequencerMock.Setup(x => x.GetHighestPublishedSequence(0L, 0L)).Returns(0L);

            providerMock.Setup(x => x[0]).Returns(() => (PollState)states == PollState.Processing ? @event : null);

            // Initial State - nothing published.
            states = PollState.Idle;
            Assert.That(poller.Poll(handler), Is.EqualTo(PollState.Idle));

            // Publish Event.
            states = PollState.Gating;
            bufferSequence.IncrementAndGet();
            Assert.That(poller.Poll(handler), Is.EqualTo(PollState.Gating));

            states = PollState.Processing;
            gatingSequence.IncrementAndGet();
            Assert.That(poller.Poll(handler), Is.EqualTo(PollState.Processing));

            Assert.That(handled, Is.True);
        }
 public OneToOneSequencedPollerThroughputTest()
 {
     _ringBuffer = RingBuffer<ValueEvent>.CreateSingleProducer(ValueEvent.EventFactory, _bufferSize, new YieldingWaitStrategy());
     _poller = _ringBuffer.NewPoller();
     _ringBuffer.AddGatingSequences(_poller.Sequence);
     _pollRunnable = new PollRunnable(_poller);
 }
コード例 #3
0
        /// <summary>
        /// </summary>
        /// <param name="arg"></param>
        private async void SendOutgoingUdpMessages(object arg)
        {
            object[] args = (object[])arg;

            AsyncUdpSocketSender             sender = (AsyncUdpSocketSender)args[0];
            EventPoller <OutgoingUdpMessage> outgoingMessagePoller = (EventPoller <OutgoingUdpMessage>)args[1];
            CancellationToken cancellation = (CancellationToken)args[2];

            int eventsThisIteration = 0;

            while (!cancellation.IsCancellationRequested)
            {
                // poll for send events
                outgoingMessagePoller.Poll((m, s, eob) =>
                {
                    // Send udp message
                    if (m.SendType == UdpSendType.SendTo)
                    {
                        sender.BeginSendTo(m.Buffer, 0, m.Size, m.Endpoint);
                    }

                    eventsThisIteration++;
                    return(eventsThisIteration < MaxUdpMessageSendBeforeSleep);
                });

                await Task.Delay(1, cancellation);
            }
        }
コード例 #4
0
    public BatchedPoller(RingBuffer <DataEvent> ringBuffer, int batchSize)
    {
        _poller = ringBuffer.NewPoller();
        ringBuffer.AddGatingSequences(_poller.Sequence);

        _polledData = new BatchedData(batchSize);
    }
コード例 #5
0
        public OneToOneSequencedPollerThroughputTest()
        {
            _ringBuffer = RingBuffer <PerfEvent> .CreateSingleProducer(PerfEvent.EventFactory, _bufferSize, new YieldingWaitStrategy());

            _poller = _ringBuffer.NewPoller();
            _ringBuffer.AddGatingSequences(_poller.Sequence);
            _pollRunnable = new PollRunnable(_poller);
        }
 public OneToOneSequencedPollerThroughputTest()
     : base(Test_Disruptor, ITERATIONS, 7)
 {
     ThreadPool.SetMaxThreads(1, 1);
     poller       = ringBuffer.NewPoller();
     pollRunnable = new PollRunnable(poller);
     ringBuffer.AddGatingSequences(poller.GetSequence());
 }
コード例 #7
0
 private PollState LoadNextValues(EventPoller <DataEvent> poller, BatchedData batch)
 {
     return(poller.Poll((ev, sequence, endOfBatch) =>
     {
         var item = ev.CopyOfData();
         return item != null && batch.AddDataItem(item);
     }));
 }
 public OneToOneSequencedPollerThroughputTest()
     : base(Test_Disruptor, ITERATIONS,7)
 {
     ThreadPool.SetMaxThreads (1,1);
     poller = ringBuffer.NewPoller();
     pollRunnable = new PollRunnable(poller);
     ringBuffer.AddGatingSequences(poller.GetSequence());  
 }
コード例 #9
0
    private static object GetNextValue(EventPoller <DataEvent <object> > poller)
    {
        var output = new object[1];

        poller.Poll((ev, sequence, endOfBatch) =>
        {
            output[0] = ev.CopyOfData();
            return(false);
        });
        return(output[0]);
    }
コード例 #10
0
        public BatchedPoller(RingBuffer <DataEvent> ringBuffer, int batchSize)
        {
            _poller = ringBuffer.NewPoller();
            ringBuffer.AddGatingSequences(_poller.Sequence);

            if (batchSize < 1)
            {
                batchSize = 20;
            }
            _maxBatchSize = batchSize;
            _polledData   = new BatchedData(_maxBatchSize);
        }
コード例 #11
0
 /// <summary>
 /// Creates an event poller for this sequence that will use the supplied data provider and
 /// gating sequences.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="provider">The data source for users of this event poller</param>
 /// <param name="gatingSequences">Sequence to be gated on.</param>
 /// <returns>A poller that will gate on this ring buffer and the supplied sequences.</returns>
 public EventPoller <T> NewPoller <T>(IDataProvider <T> provider, params ISequence[] gatingSequences)
 {
     return(EventPoller <T> .NewInstance(provider, this, new Sequence(), _cursor, gatingSequences));
 }
コード例 #12
0
 public PollRunnable(EventPoller <PerfEvent> poller)
 {
     _poller       = poller;
     _eventHandler = OnEvent;
 }
コード例 #13
0
        // Start is called before the first frame update
        private void Start()
        {
            // UDP Socket Listener/Sender initialization
            _socket         = new UdpSocket();
            _socketListener = new AsyncUdpSocketListener(_socket);
            _socketSender   = new AsyncUdpSocketSender(_socket);

            // Add to RingBuffer from listener async callbacks which happen off the main thread
            _socketListener.ReceivedUdpMessageEvent += AddUdpMessageToReceivedBuffer;

            // Init ring buffers
            _receivedMessageBuffer = RingBuffer <UdpMessage> .Create(
                ProducerType.Single,
                UdpMessage.DefaultFactory,
                256,
                new BusySpinWaitStrategy());

            _receivedMessagePoller = _receivedMessageBuffer.NewPoller();
            _receivedMessageBuffer.AddGatingSequences(_receivedMessagePoller.Sequence);

            _outgoingMessageBuffer = RingBuffer <OutgoingUdpMessage> .Create(
                ProducerType.Single,
                OutgoingUdpMessage.DefaultFactory,
                256,
                new BusySpinWaitStrategy());

            _outgoingMessagePoller = _outgoingMessageBuffer.NewPoller();
            _outgoingMessageBuffer.AddGatingSequences(_outgoingMessagePoller.Sequence);

            // This makes a deep copy of the sent message before publishing it to the outgoing message buffer
            // It makes a deep copy because the buffers containing the data in the main thread could change
            // before the data has a chance to be copied into the ring buffer. Prob want to think of a way around this.. maybe more ring buffers
            _outgoingUdpMessageSender = new RingBufferOutgoingUdpMessageSender(_outgoingMessageBuffer);

            // The NetManager reactor. TODO: Benchmark and see if I have actually made any improvement by implementing disruptor
            // Though I do like the idea of clearing up the locks and doing all the logic in the main thread esp since
            // the game server will need to routinely access connected client info
            RNetManager = new NetManager(null, _outgoingUdpMessageSender)
            {
                DisconnectTimeout = 600
            };
            RGameReactor.RNetManager = RNetManager;
            _updateEvent             = new GameEvent {
                EventId = GameEvent.Event.Update
            };
            _tempEvent = new GameEvent(); // reusable event for the update loop

            //if (!ShouldBind)
            //{
            //RNetManager.SimulateLatency = true;
            RNetManager.SimulatePacketLoss = true;
            //    R_NetManager.SimulationMaxLatency = 10;
            //    R_NetManager.SimulationMinLatency = 0;
            //}

            _cancellationSource = new CancellationTokenSource();
            _processOutgoing    = new Thread(SendOutgoingUdpMessages)
            {
                IsBackground = true,
                Name         = "UdpServer"
            };

            // Every frame the previous frames events get replaced with new output events created by the NetManager reactor for that frame
            _batchedEvents = new NetManagerEvent[MaxUdpMessagesPerFrame];
            for (int i = 0; i < MaxUdpMessagesPerFrame; i++)
            {
                _batchedEvents[i] = new NetManagerEvent {
                    EventId = NetManagerEvent.Event.UdpMessage
                }
            }
            ;

            // BIND
            if (ShouldBind)
            {
                _socket.BindLocalIpv4(BindAddress, BindPort);
            }

            // CONNECT - TEMPORARY - NEEDS TO BE SOME SORT OF STATE MACHINE
            if (ShouldConnect)
            {
                RNetManager.Connect(ConnectAddress, ConnectPort, "somekey");
            }

            // No point actually awaiting this call.. it kicks off a
            // recurring execution where the finish method always calls the start method again
#pragma warning disable 4014
            _socketListener.StartAsyncReceive();
#pragma warning restore 4014


            // Start thread that polls for outgoing udp messages and sends them on the socket
            _processOutgoing.Start(new object[] { _socketSender, _outgoingMessagePoller, _cancellationSource.Token });

            // Start coroutine that will send the check timeout event
            StartCoroutine("SendCheckTimeoutEvent");
        }
 public PollRunnable(EventPoller<ValueEvent> poller)
 {
     _poller = poller;
     _eventHandler = OnEvent;
 }
コード例 #15
0
 /// <summary>
 /// <see cref="ISequencer.NewPoller{T}(IValueDataProvider{T}, ISequence[])"/>.
 /// </summary>
 public ValueEventPoller <T> NewPoller <T>(IValueDataProvider <T> provider, params ISequence[] gatingSequences)
     where T : struct
 {
     return(EventPoller.Create(provider, this, new Sequence(), _cursor, gatingSequences));
 }
コード例 #16
0
 public PollRunnable(EventPoller <ValueEvent> poller)
 {
     this.poller = poller;
 }