public void TaskFromStateServer_ThrowsBeforeCreatingTask_EnsureIsLogged()
        {
            var exception = new InvalidOperationException("Some message");

            var logger = Substitute.For <ILogger>();
            var state  = new TaskFromStateServer.State(wb =>
            {
                wb.Release();
                throw exception;
            });

            using (var waitBlock = new WaitBlock())
            {
                var waitBlockLocal = new[] { waitBlock };

                using (var context = ApplicationContext.Create(application => application
                                                               .ConfigureForUnitTest()
                                                               .WithWaitBlock(waitBlockLocal[0])
                                                               .UseLiteServer(liteServer => liteServer
                                                                              .AddServer <TaskFromStateServer>())
                                                               .Services(services => services
                                                                         .Advanced(advanced => advanced
                                                                                   .Register(kernel => logger)
                                                                                   .Register(kernel => state)))))
                {
                    context.Execute(nameof(LiteServerHost));
                }
            }

            logger.Received(1).LogError(Arg.Is(exception));
        }
 public MyHost(IShutdown shutdown, ConsoleWriterQueue consoleWriterQueue, WaitBlock waitBlock, IRuntimeSettings runtimeSettings)
 {
     _shutdown                     = shutdown;
     _consoleWriterQueue           = consoleWriterQueue;
     _waitBlock                    = waitBlock;
     _shouldHandleAsWindowsService = string.Equals(Boolean.TrueString, runtimeSettings["ShouldHandleAsWindowsService"]);
 }
        public void TaskFromStateServer_TaskFromCanceled_NoErrors()
        {
            var logger = Substitute.For <ILogger>();
            var state  = new TaskFromStateServer.State(wb =>
            {
                wb.Release();
                return(Task.FromCanceled(new CancellationToken(true)));
            });

            using (var waitBlock = new WaitBlock())
            {
                var waitBlockLocal = new[] { waitBlock };

                using (var context = ApplicationContext.Create(application => application
                                                               .ConfigureForUnitTest()
                                                               .WithWaitBlock(waitBlockLocal[0])
                                                               .UseLiteServer(liteServer => liteServer
                                                                              .AddServer <TaskFromStateServer>())
                                                               .Services(services => services
                                                                         .Advanced(advanced => advanced
                                                                                   .Register(kernel => logger)
                                                                                   .Register(kernel => state)))))
                {
                    context.Execute(nameof(LiteServerHost));
                }
            }
        }
        public void SlackMessage_EndToEnd_Test()
        {
            using (var waitBlock = new WaitBlock())
            {
                var factory        = new MessageFactory(waitBlock);
                var waitBlockLocal = new[] { waitBlock };

                using (IApplicationContext context = ApplicationContext.Create(application => application
                                                                               .ConfigureForUnitTest()
                                                                               .WithWaitBlock(waitBlockLocal[0])
                                                                               .Services(services => services
                                                                                         .Advanced(advanced => advanced
                                                                                                   .Register <ISlackBot, FakeSlackBot>()
                                                                                                   .Register <IRuntimeSettings>(kernel => new InMemoryRuntimeSettings()
                                                                                                                                .Set("Slack.Enabled", "true"))
                                                                                                   .Register(kernel => factory)))
                                                                               .UseLiteServer(liteServer => liteServer
                                                                                              .AddWorker <AddMessageToQueueAndExit>())
                                                                               .UseSlack(slack => slack
                                                                                         .MessageHandlers(messageHandlers => messageHandlers
                                                                                                          .Add <MessageHandler>())
                                                                                         .AddToLiteServer())))
                {
                    context.Execute(nameof(LiteServerHost));
                }

                Assert.That(factory.Message.HandledCount, Is.EqualTo(1));
            }
        }
        public void RestartableServer_Failing_EnsureIsRestarted()
        {
            var logger = Substitute.For <ILogger>();
            var state  = new RestartableServer.State(2);

            using (var waitBlock = new WaitBlock())
            {
                var waitBlockLocal = new[] { waitBlock };

                using (var context = ApplicationContext.Create(application => application
                                                               .ConfigureForUnitTest()
                                                               .WithWaitBlock(waitBlockLocal[0])
                                                               .UseLiteServer(liteServer => liteServer
                                                                              .AddServer <RestartableServer>())
                                                               .Services(services => services
                                                                         .Advanced(advanced => advanced
                                                                                   .Register(kernel => logger)
                                                                                   .Register(kernel => state)))))
                {
                    context.Execute(nameof(LiteServerHost));
                }
            }

            Assert.AreEqual(state.NumberOfRestarts, state.Context?.FailedCount);
            logger.Received((int)state.NumberOfRestarts).LogError(Arg.Is <RestartableServer.CreateException>(x => true));
        }
        public void Advance()
        {
            WaitBlock wb;
#if !USESPINLOCK
            lock (this)
            {
#else
                bool taken = false;
                m_lock.Enter(ref taken);
#endif
                // Advance the count
                this.value++;
                //Console.WriteLine("Advance {0}", this.value);

                // If we have waiters then we will wake them outside the lock
                wb = this.current;
                this.current = null;
#if USESPINLOCK
                m_lock.Exit();
#else
            }
#endif

            // Unblock the waiters
            if (wb != null)
            {
                NaiadTracing.Trace.RegionStart(NaiadTracingRegion.SetEvent);
                wb.ev.Set();
                NaiadTracing.Trace.RegionStop(NaiadTracingRegion.SetEvent);
            }
        }
Esempio n. 7
0
        private E <CommandError> SendCommandBase(WaitBlock wb, TsCommand com)
        {
            scheduler.VerifyOwnThread();

            if (status != TsClientStatus.Connecting && status != TsClientStatus.Connected)
            {
                return(CommandError.ConnectionClosed);
            }

            if (context is null)
            {
                throw new InvalidOperationException("context should be set");
            }

            if (com.ExpectResponse)
            {
                var responseNumber   = unchecked (++returnCode);
                var retCodeParameter = new CommandParameter("return_code", responseNumber);
                com.Add(retCodeParameter);
                msgProc.EnqueueRequest(retCodeParameter.Value, wb);
            }

            var message = com.ToString();

            Log.Debug("[O] {0}", message);
            byte[] data       = Tools.Utf8Encoder.GetBytes(message);
            var    sendResult = context.PacketHandler.AddOutgoingPacket(data, PacketType.Command);

            if (!sendResult)
            {
                Log.Debug("packetHandler couldn't send packet: {0}", sendResult.Error);
            }
            return(R.Ok);
        }
        private void RefreshWaitedObjects(ThreadStack threadStack)
        {
            List <WaitBlock> newWaitedNodes = new List <WaitBlock>(threadStack.WaitBlocks.Values);

            int countOld = r_waitedNodes.Count;
            int countNew = newWaitedNodes.Count;
            int to       = countNew;

            if (countNew < countOld)
            {
                for (int i = countNew; i < countOld; ++i)
                {
                    r_ownedNodes[countNew].Remove();
                    r_ownedNodes.RemoveAt(countNew);
                }
            }
            else if (countOld < countNew)
            {
                to = countOld;
                int index = countOld;

                for (int i = 0; i < (countNew - countOld); ++i)
                {
                    WaitBlock objectAddress = newWaitedNodes[index];
                    ThreadStackWaitedOnNode waitedOnNode = new ThreadStackWaitedOnNode(r_manager, r_threadStackNode, index, objectAddress);
                    r_waitedNodes.Add(waitedOnNode);
                    ++index;
                }
            }

            for (int i = 0; i < to; ++i)
            {
                r_waitedNodes[i].Refresh(newWaitedNodes[i]);
            }
        }
Esempio n. 9
0
        private void SendCommandBase(WaitBlock wb, Ts3Command com)
        {
            lock (CommmandQueueLock)
            {
                if (com.ExpectResponse)
                {
                    var retCode = new CommandParameter("return_code", returnCode);
                    com.AppendParameter(retCode);
                    msgProc.EnqueueRequest(retCode.Value, wb);
                    returnCode++;
                }

                byte[] data = Util.Encoder.GetBytes(com.ToString());
                lock (StatusLock)
                {
                    if (wasExit)
                    {
                        throw new Ts3CommandException(new CommandError {
                            Id = Ts3ErrorCode.custom_error, Message = "Connection closed"
                        });
                    }
                    packetHandler.AddOutgoingPacket(data, PacketType.Command);
                }
            }
        }
Esempio n. 10
0
        public Task WaitAsync(Mutex mutex)
        {
            WaitBlock block = new WaitBlock(mutex);

            _pending.Add(block);
            _pendingReady.Set();
            return(block.Source.Task);
        }
Esempio n. 11
0
        public Task <IDisposable> WaitAsync(Mutex mutex)
        {
            var block = new WaitBlock(mutex);

            _pending.Add(block);
            _pendingReady.Set();
            return(block.Source.Task.ContinueWith(_ => (IDisposable) new MutexLock(this, mutex)));
        }
            public Message(WaitBlock waitBlock)
            {
                if (waitBlock == null)
                {
                    throw new ArgumentNullException(nameof(waitBlock));
                }

                _waitBlock = waitBlock;
            }
Esempio n. 13
0
        public override Task <R <T[], CommandError> > Send <T>(TsCommand com)
        {
            using var wb = new WaitBlock(msgProc.Deserializer);
            lock (sendQueueLock)
            {
                msgProc.EnqueueRequest(wb);
                SendRaw(com.ToString());
            }

            return(wb.WaitForMessageAsync <T>());
        }
        public EventCount()
        {
#if USESPINLOCK
            this.m_lock = new SpinLock();
            Console.Error.WriteLine("Using EventCount with spinlock");
#else
            Console.Error.WriteLine("Using EventCount with monitor");
#endif
            this.value = 0;
            this.current = null;
            this.freelist = null;
        }
Esempio n. 15
0
        public override R <T[], CommandError> Send <T>(Ts3Command com)       // Synchronous
        {
            using (var wb = new WaitBlock(msgProc.Deserializer, false))
            {
                lock (sendQueueLock)
                {
                    msgProc.EnqueueRequest(wb);
                    SendRaw(com.ToString());
                }

                return(wb.WaitForMessage <T>());
            }
        }
Esempio n. 16
0
        protected override IEnumerable <T> SendCommand <T>(Ts3Command com)       // Synchronous
        {
            using (var wb = new WaitBlock())
            {
                lock (SendQueueLock)
                {
                    msgProc.EnqueueRequest(wb);
                    SendRaw(com.ToString());
                }

                return(wb.WaitForMessage <T>());
            }
        }
Esempio n. 17
0
        public LazyNotification SendSpecialCommand(Ts3Command com, params NotificationType[] dependsOn)
        {
            if (!com.ExpectResponse)
            {
                throw new ArgumentException("A special command must take a response");
            }

            using (var wb = new WaitBlock(dependsOn))
            {
                SendCommandBase(wb, com);
                return(wb.WaitForNotification());
            }
        }
Esempio n. 18
0
        private E <CommandError> SendCommandBase(WaitBlock wb, Ts3Command com)
        {
            if (context.WasExit || com.ExpectResponse)
            {
                return(Util.TimeOutCommandError);
            }

            var message = com.ToString();

            byte[] data = Util.Encoder.GetBytes(message);
            packetHandler.AddOutgoingPacket(data, PacketType.Command);
            return(R.Ok);
        }
Esempio n. 19
0
 /// <summary>
 /// Sends a command to the server. Commands look exactly like query commands and mostly also behave identically.
 /// <para>NOTE: Do not expect all commands to work exactly like in the query documentation.</para>
 /// </summary>
 /// <typeparam name="T">The type to deserialize the response to. Use <see cref="ResponseDictionary"/> for unknow response data.</typeparam>
 /// <param name="com">The raw command to send.
 /// <para>NOTE: By default does the command expect an answer from the server. Set <see cref="Ts3Command.ExpectResponse"/> to false
 /// if the client hangs after a special command (<see cref="SendCommand{T}"/> will return <code>null</code> instead).</para></param>
 /// <returns>Returns an enumeration of the deserialized and split up in <see cref="T"/> objects data.
 /// Or <code>null</code> if no reponse is expected.</returns>
 /// <exception cref="Ts3CommandException">When the response has an error code.</exception>
 public override IEnumerable <T> SendCommand <T>(Ts3Command com)
 {
     using (var wb = new WaitBlock())
     {
         SendCommandBase(wb, com);
         if (com.ExpectResponse)
         {
             return(wb.WaitForMessage <T>());
         }
         else
         {
             return(null);
         }
     }
 }
        internal ThreadStackWaitedOnNode(ThreadStackNodeManager manager, TreeNode threadStackNode, int index, WaitBlock waitblock)
        {
            if (threadStackNode == null)
                throw new ArgumentNullException("r_threadStackNode");

            if (manager == null)
                throw new ArgumentNullException("manager");

            r_manager = manager;
            r_threadStackNode = threadStackNode;

            r_waitedOnNode = r_threadStackNode.Nodes.Insert(index, GetText(waitblock));
            r_waitedOnNode.ImageKey = "hourglass.png";
            r_waitedOnNode.SelectedImageKey = r_waitedOnNode.ImageKey;
            r_waitedOnNode.Tag = this;
        }
Esempio n. 21
0
        public async Task <R <LazyNotification, CommandError> > SendNotifyCommand(TsCommand com, params NotificationType[] dependsOn)
        {
            if (!com.ExpectResponse)
            {
                throw new ArgumentException("A special command must take a response");
            }

            using var wb = new WaitBlock(msgProc.Deserializer, dependsOn);
            var result = SendCommandBase(wb, com);

            if (!result.Ok)
            {
                return(result.Error);
            }
            return(await wb.WaitForNotificationAsync());
        }
Esempio n. 22
0
        public R <LazyNotification, CommandError> SendNotifyCommand(Ts3Command com, params NotificationType[] dependsOn)
        {
            if (!com.ExpectResponse)
            {
                throw new ArgumentException("A special command must take a response");
            }

            using (var wb = new WaitBlock(false, dependsOn))
            {
                var result = SendCommandBase(wb, com);
                if (!result.Ok)
                {
                    return(result.Error);
                }
                return(wb.WaitForNotification());
            }
        }
Esempio n. 23
0
        private void Run(CancellationToken token)
        {
            using (token.Register(() => _pendingReady.Set()))
            {
                var waiting = new List <WaitBlock>();
                while (!token.IsCancellationRequested)
                {
                    var waits = new WaitHandle[1 + waiting.Count];
                    waits[0] = _pendingReady;
                    waiting.Select(w => (WaitHandle)w.Mutex).ToList().CopyTo(waits, 1);

                    int index = WaitHandle.WaitAny(waits, TimeSpan.FromSeconds(1));
                    {
                        Mutex toRelease;
                        while (_releaseable.TryTake(out toRelease))
                        {
                            toRelease.ReleaseMutex();
                        }
                    }

                    if (index == WaitHandle.WaitTimeout)
                    {
                        continue;
                    }

                    if (index == 0)
                    {
                        WaitBlock item;
                        while (_pending.TryTake(out item))
                        {
                            waiting.Add(item);
                        }

                        continue;
                    }

                    index--;

                    {
                        WaitBlock item = waiting[index];
                        waiting.RemoveAt(index);
                        item.Source.TrySetResult(null);
                    }
                }
            }
        }
Esempio n. 24
0
 /// <summary>
 /// Sends a command to the server. Commands look exactly like query commands and mostly also behave identically.
 /// <para>NOTE: Do not expect all commands to work exactly like in the query documentation.</para>
 /// </summary>
 /// <typeparam name="T">The type to deserialize the response to. Use <see cref="ResponseDictionary"/> for unknow response data.</typeparam>
 /// <param name="com">The command to send.
 /// <para>NOTE: By default does the command expect an answer from the server. Set <see cref="TsCommand.ExpectResponse"/> to false
 /// if the client hangs after a special command (<see cref="Send{T}(TsCommand)"/> will return a generic error instead).</para></param>
 /// <returns>Returns <code>R(OK)</code> with an enumeration of the deserialized and split up in <see cref="T"/> objects data.
 /// Or <code>R(ERR)</code> with the returned error if no response is expected.</returns>
 public override R <T[], CommandError> Send <T>(TsCommand com)
 {
     using (var wb = new WaitBlock(msgProc.Deserializer, false))
     {
         var result = SendCommandBase(wb, com);
         if (!result.Ok)
         {
             return(result.Error);
         }
         if (com.ExpectResponse)
         {
             return(wb.WaitForMessage <T>());
         }
         else
         {
             return(Array.Empty <T>());
         }
     }
 }
Esempio n. 25
0
        protected override IEnumerable <T> SendCommand <T>(Ts3Command com)
        {
            var retCode = new CommandParameter("return_code", returnCode);

            if (com.ExpectResponse)
            {
                com.AppendParameter(retCode);
            }

            using (var wb = new WaitBlock())
            {
                lock (CommmandQueueLock)
                {
                    if (com.ExpectResponse)
                    {
                        msgProc.EnqueueRequest(retCode.Value, wb);
                        returnCode++;
                    }

                    byte[] data = Util.Encoder.GetBytes(com.ToString());
                    lock (StatusLock)
                    {
                        if (wasExit)
                        {
                            throw new Ts3CommandException(new CommandError {
                                Id = Ts3ErrorCode.custom_error, Message = "Connection closed"
                            });
                        }
                        packetHandler.AddOutgoingPacket(data, PacketType.Command);
                    }
                }

                if (com.ExpectResponse)
                {
                    return(wb.WaitForMessage <T>());
                }
                else
                {
                    return(null);
                }
            }
        }
Esempio n. 26
0
        public void SendMessageFromWorker_InMemory_GetsHandled()
        {
            using (var waitBlock = new WaitBlock())
            {
                var message          = new MyMessage(Guid.NewGuid());
                var receivedMessages = new ConcurrentQueue <MyMessage>();

                var waitBlockLocal = new[] { waitBlock };

                using (var context = ApplicationContext.Create(application => application
                                                               .ConfigureForUnitTest()
                                                               .WithWaitBlock(waitBlockLocal[0])
                                                               .UseRebus(rebus => rebus
                                                                         .Bus((bus, kernel) => bus
                                                                              .Routing(routing => routing
                                                                                       .TypeBased()
                                                                                       .Map <MyMessage>("inputQueue"))
                                                                              .Transport(transport => transport
                                                                                         .UseInMemoryTransport(new InMemNetwork(), "inputQueue")))
                                                                         .Handlers(handlers => handlers
                                                                                   .Handler <MyMessageHandler>())
                                                                         .AddToLiteServer())
                                                               .UseLiteServer(liteServer => liteServer
                                                                              .AddWorker <SendMyMessageWorker>())
                                                               .Services(services => services
                                                                         .Advanced(advanced => advanced
                                                                                   .Register(kernel => message)
                                                                                   .Register(kernel => receivedMessages)))))
                {
                    context.Execute(nameof(LiteServerHost));
                }

                Assert.That(receivedMessages.Count, Is.EqualTo(1));

                MyMessage receivedMessage;
                bool      canDequeue = receivedMessages.TryDequeue(out receivedMessage);

                Assert.IsTrue(canDequeue);
                Assert.That(receivedMessage, Is.EqualTo(message));
                Assert.IsTrue(receivedMessage.IsHandled);
            }
        }
Esempio n. 27
0
        /// <summary>
        /// Sends a command to the server. Commands look exactly like query commands and mostly also behave identically.
        /// <para>NOTE: Do not expect all commands to work exactly like in the query documentation.</para>
        /// </summary>
        /// <typeparam name="T">The type to deserialize the response to. Use <see cref="ResponseDictionary"/> for unknow response data.</typeparam>
        /// <param name="com">The command to send.
        /// <para>NOTE: By default does the command expect an answer from the server. Set <see cref="TsCommand.ExpectResponse"/> to false
        /// if the client hangs after a special command (<see cref="Send{T}(TsCommand)"/> will return a generic error instead).</para></param>
        /// <returns>Returns <code>R(OK)</code> with an enumeration of the deserialized and split up in <see cref="T"/> objects data.
        /// Or <code>R(ERR)</code> with the returned error if no response is expected.</returns>
        public override async Task <R <T[], CommandError> > Send <T>(TsCommand com)
        {
            using var wb = new WaitBlock(msgProc.Deserializer);
            var result = SendCommandBase(wb, com);

            if (!result.Ok)
            {
                return(result.Error);
            }
            if (com.ExpectResponse)
            {
                return(await wb.WaitForMessageAsync <T>());
            }
            else
            {
                // This might not be the nicest way to return in this case
                // but we don't know what the response is, so this acceptable.
                return(CommandError.NoResult);
            }
        }
        public void Nothing_To_Do()
        {
            var logger = Substitute.For <ILogger>();

            using (var waitBlock = new WaitBlock())
            {
                var waitBlockLocal = new[] { waitBlock };

                using (var context = ApplicationContext.Create(application => application
                                                               .ConfigureForUnitTest()
                                                               .WithWaitBlock(waitBlockLocal[0])
                                                               .UseLiteServer(liteServer => liteServer.OnStartup(startup => { waitBlockLocal[0].Release(); }))
                                                               .Services(services => services
                                                                         .Advanced(advanced => advanced
                                                                                   .Register(kernel => logger)))))
                {
                    context.Execute(nameof(LiteServerHost));
                }
            }
        }
        private bool TryEnqueue(WaitBlock w)
        {
            if (w.parker.TryLock())
            {
                //
                // Move the locked wait block to the lock's queue.
                //

                mlock.EnqueueWaiter(w);
                return(true);
            }

            //
            // Mark the WaitBlock as unlinked so that WaitBlockQueue::Remove
            // returns immediately.
            //

            w.next = w;
            return(false);
        }
Esempio n. 30
0
 public async Task <R <IEnumerable <T>, CommandError> > SendCommandAsync <T>(Ts3Command com) where T : IResponse, new()
 {
     using (var wb = new WaitBlock(true))
     {
         var result = SendCommandBase(wb, com);
         if (!result.Ok)
         {
             return(result.Error);
         }
         if (com.ExpectResponse)
         {
             return(await wb.WaitForMessageAsync <T>());
         }
         else
         {
             // This might not be the nicest way to return in this case
             // but we don't know what the response is, so this acceptable.
             return(Util.NoResultCommandError);
         }
     }
 }
Esempio n. 31
0
 /// <summary>
 /// Sends a command to the server. Commands look exactly like query commands and mostly also behave identically.
 /// <para>NOTE: Do not expect all commands to work exactly like in the query documentation.</para>
 /// </summary>
 /// <typeparam name="T">The type to deserialize the response to. Use <see cref="ResponseDictionary"/> for unknow response data.</typeparam>
 /// <param name="com">The raw command to send.
 /// <para>NOTE: By default does the command expect an answer from the server. Set <see cref="Ts3Command.ExpectResponse"/> to false
 /// if the client hangs after a special command (<see cref="SendCommand{T}"/> will return <code>null</code> instead).</para></param>
 /// <returns>Returns <code>R(OK)</code> with an enumeration of the deserialized and split up in <see cref="T"/> objects data.
 /// Or <code>R(ERR)</code> with the returned error if no response is expected.</returns>
 public override R <IEnumerable <T>, CommandError> SendCommand <T>(Ts3Command com)
 {
     using (var wb = new WaitBlock(false))
     {
         var result = SendCommandBase(wb, com);
         if (!result.Ok)
         {
             return(result.Error);
         }
         if (com.ExpectResponse)
         {
             return(wb.WaitForMessage <T>());
         }
         else
         {
             // This might not be the nicest way to return in this case
             // but we don't know what the response is, so this acceptable.
             return(Util.NoResultCommandError);
         }
     }
 }
        /// <summary>
        /// Unblocks a wait block.
        /// </summary>
        /// <param name="waitBlock">The wait block to unblock.</param>
        private void Unblock(WaitBlock* waitBlock)
        {
            int flags;

            // Clear the spinning flag.
            do
            {
                flags = waitBlock->Flags;
            } while (Interlocked.CompareExchange(
                ref waitBlock->Flags,
                flags & ~WaiterSpinning,
                flags
                ) != flags);

            if ((flags & WaiterSpinning) == 0)
            {
#if RIGOROUS_CHECKS
                System.Diagnostics.Trace.Assert(_wakeEvent != IntPtr.Zero);

#endif
                NativeMethods.NtReleaseKeyedEvent(
                    _wakeEvent,
                    new IntPtr(waitBlock),
                    false,
                    IntPtr.Zero
                    );
            }
        }
        private static void InsertHeadList(WaitBlock* listHead, WaitBlock* entry)
        {
            WaitBlock* flink;

            flink = listHead->Flink;
            entry->Flink = flink;
            entry->Blink = listHead;
            flink->Blink = entry;
            listHead->Flink = entry;
        }
        private static void InsertTailList(WaitBlock* listHead, WaitBlock* entry)
        {
            WaitBlock* blink;

            blink = listHead->Blink;
            entry->Flink = listHead;
            entry->Blink = blink;
            blink->Flink = entry;
            listHead->Blink = entry;
        }
 internal void Refresh(WaitBlock waitblock)
 {
     r_waitedOnNode.Text = GetText(waitblock);
 }
        private static bool RemoveEntryList(WaitBlock* entry)
        {
            WaitBlock* blink;
            WaitBlock* flink;

            flink = entry->Flink;
            blink = entry->Blink;
            blink->Flink = flink;
            flink->Blink = blink;

            return flink == blink;
        }
        private static WaitBlock* RemoveHeadList(WaitBlock* listHead)
        {
            WaitBlock* flink;
            WaitBlock* entry;

            entry = listHead->Flink;
            flink = entry->Flink;
            listHead->Flink = flink;
            flink->Blink = listHead;

            return entry;
        }
        /// <summary>
        /// Blocks on a wait block.
        /// </summary>
        /// <param name="waitBlock">The wait block to block on.</param>
        private void Block(WaitBlock* waitBlock)
        {
            int flags;

            // Spin for a while.
            for (int j = 0; j < _spinCount; j++)
            {
                if ((Thread.VolatileRead(ref waitBlock->Flags) & WaiterSpinning) == 0)
                    break;
            }

#if DEFER_EVENT_CREATION
            IntPtr wakeEvent;

            wakeEvent = Interlocked.CompareExchange(ref _wakeEvent, IntPtr.Zero, IntPtr.Zero);

            if (wakeEvent == IntPtr.Zero)
            {
                wakeEvent = this.CreateWakeEvent();

                if (Interlocked.CompareExchange(ref _wakeEvent, wakeEvent, IntPtr.Zero) != IntPtr.Zero)
                    NativeMethods.CloseHandle(wakeEvent);
            }

#endif
            // Clear the spinning flag.
            do
            {
                flags = waitBlock->Flags;
            } while (Interlocked.CompareExchange(
                ref waitBlock->Flags,
                flags & ~WaiterSpinning,
                flags
                ) != flags);

            // Go to sleep if necessary.
            if ((flags & WaiterSpinning) != 0)
            {
#if ENABLE_STATISTICS
                if ((waitBlock->Flags & WaiterExclusive) != 0)
                    Interlocked.Increment(ref _acqExclSlpCount);
                else
                    Interlocked.Increment(ref _acqShrdSlpCount);

#endif
                if (NativeMethods.NtWaitForKeyedEvent(
                    _wakeEvent,
                    new IntPtr(waitBlock),
                    false,
                    IntPtr.Zero
                    ) != 0)
                    throw new Exception(Utils.MsgFailedToWaitIndefinitely);
            }
        }
 /// <summary>
 /// Inserts a wait block into the waiters list.
 /// </summary>
 /// <param name="waitBlock">The wait block to insert.</param>
 /// <param name="position">Specifies where to insert the wait block.</param>
 private void InsertWaitBlock(WaitBlock* waitBlock, ListPosition position)
 {
     switch (position)
     {
         case ListPosition.First:
             InsertHeadList(_waitersListHead, waitBlock);
             break;
         case ListPosition.LastExclusive:
             InsertTailList(_firstSharedWaiter, waitBlock);
             break;
         case ListPosition.Last:
             InsertTailList(_waitersListHead, waitBlock);
             break;
     }
 }
 private String GetText(WaitBlock waitblock)
 {
     return "Waiting (" + waitblock.ObjectWaitType.ToString() +
            ") on " + r_manager.GetValue(waitblock.ObjectAddress) +
            " with Key " + waitblock.WaitKey;
 }
 void IMonitorLock.EnqueueWaiter(WaitBlock wb) {
     EnqueueLockedWaiter(wb);
 }
        /// <summary>
        /// Wakes either one exclusive waiter or multiple shared waiters.
        /// </summary>
        private void Wake()
        {
            WaitBlock wakeList = new WaitBlock();
            WaitBlock* wb;
            WaitBlock* exclusiveWb = null;

            wakeList.Flink = &wakeList;
            wakeList.Blink = &wakeList;

            _lock.Acquire();

            try
            {
                bool first = true;

                while (true)
                {
                    wb = _waitersListHead->Flink;

                    if (wb == _waitersListHead)
                    {
                        int value;

                        // No more waiters. Clear the waiters bit.
                        do
                        {
                            value = _value;
                        } while (Interlocked.CompareExchange(
                            ref _value,
                            value & ~LockWaiters,
                            value
                            ) != value);

                        break;
                    }

                    // If this is an exclusive waiter, don't wake 
                    // anyone else.
                    if (first && (wb->Flags & WaiterExclusive) != 0)
                    {
                        exclusiveWb = RemoveHeadList(_waitersListHead);
#if ENABLE_STATISTICS
                        _exclusiveWaitersCount--;

#endif
                        break;
                    }

#if RIGOROUS_CHECKS
                    // If this is not the first waiter we have looked at 
                    // and it is an exclusive waiter, then we have a bug - 
                    // we should have stopped upon encountering the first 
                    // exclusive waiter (previous block), so this means 
                    // we have an exclusive waiter *behind* shared waiters.
                    if (!first && (wb->Flags & WaiterExclusive) != 0)
                    {
                        System.Diagnostics.Trace.Fail("Exclusive waiter behind shared waiters!");
                    }

#endif
                    // Remove the (shared) waiter and add it to the wake list.
                    wb = RemoveHeadList(_waitersListHead);
                    InsertTailList(&wakeList, wb);
#if ENABLE_STATISTICS
                    _sharedWaitersCount--;
#endif

                    first = false;
                }

                if (exclusiveWb == null)
                {
                    // If we removed shared waiters, we removed all of them. 
                    // Reset the first shared waiter pointer.
                    // Note that this also applies if we haven't woken anyone 
                    // at all; this just becomes a redundant assignment.
                    _firstSharedWaiter = _waitersListHead;
                }
            }
            finally
            {
                _lock.Release();
            }

            // If we removed one exclusive waiter, unblock it.
            if (exclusiveWb != null)
            {
                this.Unblock(exclusiveWb);
                return;
            }

            // Carefully traverse the wake list and wake each shared waiter.
            wb = wakeList.Flink;

            while (wb != &wakeList)
            {
                WaitBlock* flink;

                flink = wb->Flink;
                this.Unblock(wb);
                wb = flink;
            }
        }
        /// <summary>
        /// Wakes multiple shared waiters.
        /// </summary>
        private void WakeShared()
        {
            WaitBlock wakeList = new WaitBlock();
            WaitBlock* wb;

            wakeList.Flink = &wakeList;
            wakeList.Blink = &wakeList;

            _lock.Acquire();

            try
            {
                wb = _firstSharedWaiter;

                while (true)
                {
                    WaitBlock* flink;

                    if (wb == _waitersListHead)
                    {
                        int value;

                        // No more waiters. Clear the waiters bit.
                        do
                        {
                            value = _value;
                        } while (Interlocked.CompareExchange(
                            ref _value,
                            value & ~LockWaiters,
                            value
                            ) != value);

                        break;
                    }
#if RIGOROUS_CHECKS
                    // We shouldn't have *any* exclusive waiters at this 
                    // point since we started at _firstSharedWaiter.
                    if ((wb->Flags & WaiterExclusive) != 0)
                        System.Diagnostics.Trace.Fail("Exclusive waiter behind shared waiters!");

#endif

                    // Remove the waiter and add it to the wake list.
                    flink = wb->Flink;
                    RemoveEntryList(wb);
                    InsertTailList(&wakeList, wb);
#if ENABLE_STATISTICS
                    _sharedWaitersCount--;
#endif
                    wb = flink;
                }

                // Reset the first shared waiter pointer.
                _firstSharedWaiter = _waitersListHead;
            }
            finally
            {
                _lock.Release();
            }

            // Carefully traverse the wake list and wake each waiter.
            wb = wakeList.Flink;

            while (wb != &wakeList)
            {
                WaitBlock* flink;

                flink = wb->Flink;
                this.Unblock(wb);
                wb = flink;
            }
        }