예제 #1
0
        public void AsyncLock_Locked_PreventsLockUntilUnlocked()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();

                var task1 = TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                var task2Start = Task.Factory.StartNew(async () =>
                {
                    await mutex.LockAsync();
                });
                var task2 = await task2Start;

                Assert.IsFalse(task2.IsCompleted);
                task1Continue.SetResult();
                await task2;
            });
        }
예제 #2
0
        public void AsyncLock_Locked_PreventsLockUntilUnlocked()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();

                Task<IDisposable> task1LockTask = null;
                var task1 = Task.Run(async () =>
                {
                    task1LockTask = mutex.LockAsync();
                    using (await task1LockTask)
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                Task<IDisposable> task2LockTask = null;
                var task2Start = Task.Factory.StartNew(async () =>
                {
                    task2LockTask = mutex.LockAsync();
                    await task2LockTask;
                });
                var task2 = await task2Start;

                Assert.IsFalse(task2.IsCompleted);
                task1Continue.SetResult();
                await task2;
            });
        }
예제 #3
0
		public WebSocket(DiscordClient client, JsonSerializer serializer, Logger logger)
		{
            _client = client;
            Logger = logger;
            _serializer = serializer;

            _lock = new AsyncLock();
            _taskManager = new TaskManager(Cleanup);
            CancelToken = new CancellationToken(true);
			_connectedEvent = new ManualResetEventSlim(false);

#if !DOTNET5_4
			_engine = new WS4NetEngine(client.Config, _taskManager);
#else
			_engine = new BuiltInEngine(client.Config);
#endif
            _engine.BinaryMessage += (s, e) =>
            {
	            using (var compressed = new MemoryStream(e.Data, 2, e.Data.Length - 2))
	            using (var decompressed = new MemoryStream())
	            {
		            using (var zlib = new DeflateStream(compressed, CompressionMode.Decompress))
			            zlib.CopyTo(decompressed);
		            decompressed.Position = 0;
                    using (var reader = new StreamReader(decompressed))
			            ProcessMessage(reader.ReadToEnd()).GetAwaiter().GetResult();
	            }
            };
			_engine.TextMessage += (s, e) => ProcessMessage(e.Message).Wait(); 
		}
예제 #4
0
        public AudioClient(DiscordClient client, Server server, int id)
		{
            Id = id;
            _config = client.Config;
            Service = client.Services.Get<AudioService>();
            Config = Service.Config;
            Serializer = client.Serializer;
            _gatewayState = (int)ConnectionState.Disconnected;

            //Logging
            Logger = client.Log.CreateLogger($"AudioClient #{id}");

            //Async
            _taskManager = new TaskManager(Cleanup, false);
            _connectionLock = new AsyncLock();
            CancelToken = new CancellationToken(true);

            //Networking
            if (Config.EnableMultiserver)
            {
                ClientAPI = new JsonRestClient(_config, DiscordConfig.ClientAPIUrl, client.Log.CreateLogger($"ClientAPI #{id}"));
                GatewaySocket = new GatewaySocket(_config, client.Serializer, client.Log.CreateLogger($"Gateway #{id}"));
                GatewaySocket.Connected += (s, e) =>
                {
                    if (_gatewayState == ConnectionState.Connecting)
                        EndGatewayConnect();
                };
            }
            else
                GatewaySocket = client.GatewaySocket;
            GatewaySocket.ReceivedDispatch += (s, e) => OnReceivedEvent(e);
            VoiceSocket = new VoiceSocket(_config, Config, client.Serializer, client.Log.CreateLogger($"Voice #{id}"));
            VoiceSocket.Server = server;
            OutputStream = new OutStream(this);
        }
예제 #5
0
 /// <summary>
 /// Initializes a new instance.
 /// </summary>
 /// <param name="endpoint"></param>
 /// <param name="holdUri"></param>
 /// <param name="conferenceId"></param>
 public QueueHoldConference(LocalEndpoint endpoint, string holdUri, string conferenceId = null)
 {
     this.sync = new AsyncLock();
     this.endpoint = endpoint;
     this.holdUri = holdUri;
     this.conferenceId = conferenceId;
 }
        public void MultipleWaits_NotifyAll_AllAreCompleted()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                var key1 = await mutex.LockAsync();
                var task1 = cv.WaitAsync();
                var __ = task1.ContinueWith(_ => key1.Dispose());
                var key2 = await mutex.LockAsync();
                var task2 = cv.WaitAsync();
                var ___ = task2.ContinueWith(_ => key2.Dispose());

                await Task.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.NotifyAll();
                    }
                });

                await task1;
                await task2;
            });
        }
예제 #7
0
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var a = 1;
            var b = 1 + 1;
            var c = new StringBuilder();

            var al = new AsyncLock();
        }
예제 #8
0
        public AudioClient(AudioService service, int clientId, Server server, GatewaySocket gatewaySocket, Logger logger)
		{
			Service = service;
			Id = clientId;
            GatewaySocket = gatewaySocket;
            Logger = logger;
            
            _connectionLock = new AsyncLock();   
                     
            _serializer = new JsonSerializer();
            _serializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
            _serializer.Error += (s, e) =>
            {
                e.ErrorContext.Handled = true;
                Logger.Error("Serialization Failed", e.ErrorContext.Error);
            };

            GatewaySocket.ReceivedDispatch += OnReceivedDispatch;

            VoiceSocket = new VoiceWebSocket(service.Client, this, _serializer, logger);
            VoiceSocket.Server = server;

            /*_voiceSocket.Connected += (s, e) => RaiseVoiceConnected();
			_voiceSocket.Disconnected += async (s, e) =>
			{
				_voiceSocket.CurrentServerId;
				if (voiceServerId != null)
					_gatewaySocket.SendLeaveVoice(voiceServerId.Value);
				await _voiceSocket.Disconnect().ConfigureAwait(false);
				RaiseVoiceDisconnected(socket.CurrentServerId.Value, e);
				if (e.WasUnexpected)
					await socket.Reconnect().ConfigureAwait(false);
			};*/

            /*_voiceSocket.IsSpeaking += (s, e) =>
			{
				if (_voiceSocket.State == WebSocketState.Connected)
				{
					var user = _users[e.UserId, socket.CurrentServerId];
					bool value = e.IsSpeaking;
					if (user.IsSpeaking != value)
					{
						user.IsSpeaking = value;
						var channel = _channels[_voiceSocket.CurrentChannelId];
						RaiseUserIsSpeaking(user, channel, value);
						if (Config.TrackActivity)
							user.UpdateActivity();
					}
				}
			};*/

            /*this.Connected += (s, e) =>
			{
				_voiceSocket.ParentCancelToken = _cancelToken;
			};*/
        }
예제 #9
0
        public void AsyncLock_Unlocked_SynchronouslyPermitsLock()
        {
            var mutex = new AsyncLock();

            var lockTask = mutex.LockAsync();

            Assert.IsTrue(lockTask.IsCompleted);
            Assert.IsFalse(lockTask.IsFaulted);
            Assert.IsFalse(lockTask.IsCanceled);
        }
예제 #10
0
		public VoiceBuffer(int frameCount, int frameSize)
		{
			_frameSize = frameSize;
			_frameCount = frameCount;
			_bufferSize = _frameSize * _frameCount;
            _readCursor = 0;
			_writeCursor = 0;
			_buffer = new byte[_bufferSize];
			_blankFrame = new byte[_frameSize];
			_notOverflowEvent = new ManualResetEventSlim(); //Notifies when an overflow is solved
            _lock = new AsyncLock();
        }
예제 #11
0
		internal ModuleManager(DiscordClient client, IModule instance, string name, ModuleFilter filterType)
		{
            Client = client;
            Instance = instance;
            Name = name;
            FilterType = filterType;

            Id = name.ToLowerInvariant();
            _lock = new AsyncLock();

			_allowAll = filterType == ModuleFilter.None;
			_useServerWhitelist = filterType.HasFlag(ModuleFilter.ServerWhitelist);
			_useChannelWhitelist = filterType.HasFlag(ModuleFilter.ChannelWhitelist);
			_allowPrivate = filterType.HasFlag(ModuleFilter.AlwaysAllowPrivate);

            _enabledServers = new ConcurrentDictionary<ulong, Server>();
			_enabledChannels = new ConcurrentDictionary<ulong, Channel>();
			_indirectServers = new ConcurrentDictionary<ulong, int>();

			if (_allowAll || _useServerWhitelist) //Server-only events
			{
				client.ChannelCreated += (s, e) => { if (e.Server != null && HasServer(e.Server)) ChannelCreated(s, e); };
				client.UserVoiceStateUpdated += (s, e) => { if (HasServer(e.Server)) UserVoiceStateUpdated(s, e); };
			}

			client.ChannelDestroyed += (s, e) => { if (HasChannel(e.Channel)) ChannelDestroyed(s, e); };
			client.ChannelUpdated += (s, e) => { if (HasChannel(e.Channel)) ChannelUpdated(s, e); };

			client.MessageReceived += (s, e) => { if (HasChannel(e.Channel)) MessageReceived(s, e); };
			client.MessageSent += (s, e) => { if (HasChannel(e.Channel)) MessageSent(s, e); };
			client.MessageDeleted += (s, e) => { if (HasChannel(e.Channel)) MessageDeleted(s, e); };
			client.MessageUpdated += (s, e) => { if (HasChannel(e.Channel)) MessageUpdated(s, e); };
			client.MessageAcknowledged += (s, e) => { if (HasChannel(e.Channel)) MessageReadRemotely(s, e); };

			client.RoleCreated += (s, e) => { if (HasIndirectServer(e.Server)) RoleCreated(s, e); };
			client.RoleUpdated += (s, e) => { if (HasIndirectServer(e.Server)) RoleUpdated(s, e); };
			client.RoleDeleted += (s, e) => { if (HasIndirectServer(e.Server)) RoleDeleted(s, e); };

			client.LeftServer += (s, e) => { if (HasIndirectServer(e.Server)) { DisableServer(e.Server); LeftServer(s, e); } };
			client.ServerUpdated += (s, e) => { if (HasIndirectServer(e.Server)) ServerUpdated(s, e); };
			client.ServerUnavailable += (s, e) => { if (HasIndirectServer(e.Server)) ServerUnavailable(s, e); };
			client.ServerAvailable += (s, e) => { if (HasIndirectServer(e.Server)) ServerAvailable(s, e); };

			client.UserJoined += (s, e) => { if (HasIndirectServer(e.Server)) UserJoined(s, e); };
			client.UserLeft += (s, e) => { if (HasIndirectServer(e.Server)) UserLeft(s, e); };
			client.UserUpdated += (s, e) => { if (HasIndirectServer(e.Server)) UserUpdated(s, e); };
			client.UserIsTypingUpdated += (s, e) => { if (HasChannel(e.Channel)) UserIsTypingUpdated(s, e); };
			//TODO: We aren't getting events from UserPresence if AllowPrivate is enabled, but the server we know that user through isn't on the whitelist
			client.UserPresenceUpdated += (s, e) => { if (HasIndirectServer(e.Server)) UserPresenceUpdated(s, e); };
			client.UserBanned += (s, e) => { if (HasIndirectServer(e.Server)) UserBanned(s, e); };
			client.UserUnbanned += (s, e) => { if (HasIndirectServer(e.Server)) UserUnbanned(s, e); };
		}
        public void WaitAsync_WithoutNotify_IsNotCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);

                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await AssertEx.NeverCompletesAsync(task);
            });
        }
예제 #13
0
        public BuiltInEngine(DiscordConfig config, string baseUrl, ILogger logger)
		{
			_config = config;
            _baseUrl = baseUrl;
            _logger = logger;

            _rateLimitLock = new AsyncLock();
            _client = new HttpClient(new HttpClientHandler
            {
                AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
                UseCookies = false,
                UseProxy = false
            });
            _client.DefaultRequestHeaders.Add("accept", "*/*");
            _client.DefaultRequestHeaders.Add("accept-encoding", "gzip,deflate");
            _client.DefaultRequestHeaders.Add("user-agent", config.UserAgent);
        }
예제 #14
0
        public RestSharpEngine(DiscordConfig config, string baseUrl, Logger logger)
		{
			_config = config;
            Logger = logger;

            _rateLimitLock = new AsyncLock();
            _client = new RestSharpClient(baseUrl)
			{
				PreAuthenticate = false,
				ReadWriteTimeout = _config.RestTimeout,
				UserAgent = config.UserAgent
            };
			_client.Proxy = null;
            _client.RemoveDefaultParameter("Accept");
            _client.AddDefaultHeader("accept", "*/*");
			_client.AddDefaultHeader("accept-encoding", "gzip,deflate");
        }
        public void WaitAsync_Notified_IsCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.Notify();
                    }
                });
                await task;
            });
        }
예제 #16
0
        public void AsyncLock_DoubleDispose_OnlyPermitsOneTask()
        {
            AsyncContext.Run(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();

                Task<IDisposable> lockTask = null;
                await Task.Run(async () =>
                {
                    lockTask = mutex.LockAsync();
                    var key = await lockTask;
                    key.Dispose();
                    key.Dispose();
                });

                Task<IDisposable> task1LockTask = null;
                var task1 = Task.Run(async () =>
                {
                    task1LockTask = mutex.LockAsync();
                    using (await task1LockTask)
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                Task<IDisposable> task2LockTask = null;
                var task2Start = Task.Factory.StartNew(async () =>
                {
                    task2LockTask = mutex.LockAsync();
                    await task2LockTask;
                });
                var task2 = await task2Start;

                Assert.IsFalse(task2.IsCompleted);
                task1Continue.SetResult();
                await task2;
            });
        }
        public void WaitAsync_AfterNotify_IsNotCompleted()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var cv = new AsyncConditionVariable(mutex);
                await TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        cv.Notify();
                    }
                });

                await mutex.LockAsync();
                var task = cv.WaitAsync();

                await AssertEx.NeverCompletesAsync(task);
            });
        }
예제 #18
0
        public AudioClient(DiscordClient client, Server server, int id)
        {
            Id = id;
            Service = client.GetService<AudioService>();
            Config = Service.Config;
            Serializer = client.Serializer;
            _gatewayState = (int)ConnectionState.Disconnected;

            //Logging
            Logger = client.Log.CreateLogger($"AudioClient #{id}");

            //Async
            _taskManager = new TaskManager(Cleanup, false);
            _connectionLock = new AsyncLock();
            CancelToken = new CancellationToken(true);

            //Networking
            _config = client.Config;
            GatewaySocket = client.GatewaySocket;
            GatewaySocket.ReceivedDispatch += (s, e) => OnReceivedEvent(e);
            VoiceSocket = new VoiceSocket(_config, Config, client.Serializer, client.Log.CreateLogger($"Voice #{id}"));
            VoiceSocket.Server = server;
            OutputStream = new OutStream(this);
        }
예제 #19
0
        public void AsyncLock_DoubleDispose_OnlyPermitsOneTask()
        {
            Test.Async(async () =>
            {
                var mutex = new AsyncLock();
                var task1HasLock = new TaskCompletionSource();
                var task1Continue = new TaskCompletionSource();

                await TaskShim.Run(async () =>
                {
                    var key = await mutex.LockAsync();
                    key.Dispose();
                    key.Dispose();
                });

                var task1 = TaskShim.Run(async () =>
                {
                    using (await mutex.LockAsync())
                    {
                        task1HasLock.SetResult();
                        await task1Continue.Task;
                    }
                });
                await task1HasLock.Task;

                var task2Start = Task.Factory.StartNew(async () =>
                {
                    await mutex.LockAsync();
                });
                var task2 = await task2Start;

                Assert.IsFalse(task2.IsCompleted);
                task1Continue.SetResult();
                await task2;
            });
        }
예제 #20
0
 public DebugView(AsyncLock mutex)
 {
     _mutex = mutex;
 }
예제 #21
0
 /// <summary>
 /// Creates the key for a lock.
 /// </summary>
 /// <param name="asyncLock">The lock to release. May not be <c>null</c>.</param>
 public Key(AsyncLock asyncLock)
 {
     _asyncLock = asyncLock;
 }
예제 #22
0
 public void Id_IsNotZero()
 {
     var mutex = new AsyncLock();
     Assert.AreNotEqual(0, mutex.Id);
 }
 public RecursiveAsyncLock()
 {
     mutex = new AsyncLock();
 }
예제 #24
0
 /// <summary>
 /// Creates an async-compatible condition variable associated with an async-compatible lock.
 /// </summary>
 /// <param name="asyncLock">The lock associated with this condition variable.</param>
 public AsyncConditionVariable(AsyncLock asyncLock)
     : this(asyncLock, new DefaultAsyncWaitQueue<object>())
 {
 }
 /// <summary>
 /// Constructs a new monitor.
 /// </summary>
 public AsyncMonitor(IAsyncWaitQueue <IDisposable> lockQueue, IAsyncWaitQueue <object> conditionVariableQueue)
 {
     _asyncLock         = new AsyncLock(lockQueue);
     _conditionVariable = new AsyncConditionVariable(_asyncLock, conditionVariableQueue);
 }
예제 #26
0
 /// <summary>
 /// Creates an async-compatible condition variable associated with an async-compatible lock.
 /// </summary>
 /// <param name="asyncLock">The lock associated with this condition variable.</param>
 public AsyncConditionVariable(AsyncLock asyncLock)
     : this(asyncLock, new DefaultAsyncWaitQueue <object>())
 {
 }
예제 #27
0
 /// <summary>
 /// Creates the key for a lock.
 /// </summary>
 /// <param name="asyncLock">The lock to release. May not be <c>null</c>.</param>
 public Key(AsyncLock asyncLock)
 {
     _asyncLock = asyncLock;
 }
예제 #28
0
 public DebugView(AsyncLock mutex)
 {
     _mutex = mutex;
 }
예제 #29
0
        /// <summary> Initializes a new instance of the DiscordClient class. </summary>
        public DiscordClient(DiscordConfig config = null)
        {
            Config = config ?? new DiscordConfig();
            Config.Lock();

            State = (int)ConnectionState.Disconnected;
            Status = UserStatus.Online;

            //Logging
            Log = new LogManager(this);
            Logger = Log.CreateLogger("Discord");

            //Async
            _taskManager = new TaskManager(Cleanup);
            _connectionLock = new AsyncLock();
            _disconnectedEvent = new ManualResetEvent(true);
            _connectedEvent = new ManualResetEventSlim(false);
            CancelToken = new CancellationToken(true);

            //Cache
            _servers = new ConcurrentDictionary<ulong, Server>();
            _channels = new ConcurrentDictionary<ulong, Channel>();
            _privateChannels = new ConcurrentDictionary<ulong, Channel>();

            //Serialization
            _serializer = new JsonSerializer();
            _serializer.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
#if TEST_RESPONSES
            _serializer.CheckAdditionalContent = true;
            _serializer.MissingMemberHandling = MissingMemberHandling.Error;
#else
            _serializer.Error += (s, e) =>
            {
                e.ErrorContext.Handled = true;
                Logger.Error("Serialization Failed", e.ErrorContext.Error);
            };
#endif

            //Networking
            ClientAPI = new RestClient(Config, DiscordConfig.ClientAPIUrl, Log.CreateLogger("ClientAPI"));
            StatusAPI = new RestClient(Config, DiscordConfig.StatusAPIUrl, Log.CreateLogger("StatusAPI"));
            GatewaySocket = new GatewaySocket(this, _serializer, Log.CreateLogger("Gateway"));
            GatewaySocket.Connected += (s, e) =>
            {
                if (State == ConnectionState.Connecting)
                    EndConnect();
            };
            GatewaySocket.Disconnected += (s, e) => OnDisconnected(e.WasUnexpected, e.Exception);
            GatewaySocket.ReceivedDispatch += (s, e) => OnReceivedEvent(e);

            if (Config.UseMessageQueue)
                MessageQueue = new MessageQueue(this, Log.CreateLogger("MessageQueue"));

            //Extensibility
            Services = new ServiceManager(this);

            //Import/Export
            //_messageImporter = new JsonSerializer();
            //_messageImporter.ContractResolver = new Message.ImportResolver();
        }
예제 #30
0
 /// <summary>
 /// Constructs a new monitor.
 /// </summary>
 public AsyncMonitor(IAsyncWaitQueue <IDisposable> lockQueue, IAsyncWaitQueue <object> conditionVariableQueue)
 {
     _asyncLock         = new AsyncLock(lockQueue);
     _conditionVariable = new AsyncConditionVariable(_asyncLock, conditionVariableQueue);
     //Enlightenment.Trace.AsyncMonitor_Created(_asyncLock, _conditionVariable);
 }
예제 #31
0
 /// <summary>
 /// Creates an async-compatible condition variable associated with an async-compatible lock.
 /// </summary>
 /// <param name="asyncLock">The lock associated with this condition variable.</param>
 /// <param name="queue">The wait queue used to manage waiters. This may be <c>null</c> to use a default (FIFO) queue.</param>
 internal AsyncConditionVariable(AsyncLock asyncLock, IAsyncWaitQueue <object> queue)
 {
     _asyncLock = asyncLock;
     _queue     = queue ?? new DefaultAsyncWaitQueue <object>();
     _mutex     = new object();
 }
예제 #32
0
 /// <summary>
 /// Constructs a new monitor.
 /// </summary>
 public AsyncMonitor(IAsyncWaitQueue<IDisposable> lockQueue, IAsyncWaitQueue<object> conditionVariableQueue)
 {
     _asyncLock = new AsyncLock(lockQueue);
     _conditionVariable = new AsyncConditionVariable(_asyncLock, conditionVariableQueue);
     //Enlightenment.Trace.AsyncMonitor_Created(_asyncLock, _conditionVariable);
 }
예제 #33
0
 internal TaskManager(bool stopOnCompletion)
 {
     _lock = new AsyncLock();
     StopOnCompletion = stopOnCompletion;
 }
예제 #34
0
 /// <summary>
 /// Creates an async-compatible condition variable associated with an async-compatible lock.
 /// </summary>
 /// <param name="asyncLock">The lock associated with this condition variable.</param>
 /// <param name="queue">The wait queue used to manage waiters.</param>
 public AsyncConditionVariable(AsyncLock asyncLock, IAsyncWaitQueue<object> queue)
 {
     _asyncLock = asyncLock;
     _queue = queue;
     _mutex = new object();
 }
예제 #35
0
 /// <summary>
 /// Creates an async-compatible condition variable associated with an async-compatible lock.
 /// </summary>
 /// <param name="asyncLock">The lock associated with this condition variable.</param>
 /// <param name="queue">The wait queue used to manage waiters.</param>
 public AsyncConditionVariable(AsyncLock asyncLock, IAsyncWaitQueue <object> queue)
 {
     _asyncLock = asyncLock;
     _queue     = queue;
     _mutex     = new object();
 }
        public async Task AsyncLock_DoesNotPermitRecursiveWaits()
        {
            var mutex = new AsyncLock();
            var key = await mutex.LockAsync();
            
            var waiter = mutex.LockAsync().AsTask();

            Assert.IsFalse(waiter.Wait(1000));
            key.Dispose();
        }
예제 #37
0
        /// <summary>
        /// The Lock mechanism designed for standard using blocks. This lock is thread and interprocess safe.
        /// You can create and use it from anywhere.
        /// </summary>
        /// <param name="pollInterval">The frequency of polling the termination of the mutex-thread.</param>
        /// <returns>The IDisposable await-able Task.</returns>
        public async Task <IDisposable> LockAsync(CancellationToken cancellationToken = default, int pollInterval = 100)
        {
            Exception inner = null;

            try
            {
                if (IsQuitPending)
                {
                    throw new OperationCanceledException($"{nameof(AsyncMutex)}.{nameof(AsyncMutex.LockAsync)} failed because quit is pending on: {ShortName}.");
                }

                // Local lock for thread safety.
                await AsyncLock.LockAsync(cancellationToken).ConfigureAwait(false);

                if (IsAlive)
                {
                    throw new InvalidOperationException("Thread should not be alive.");
                }

                MutexThread = new Thread(new ParameterizedThreadStart(HoldLock))
                {
                    Name = $"{nameof(MutexThread)}"
                };

                MutexThread.Start(cancellationToken);

                ChangeStatus(AsyncLockStatus.StatusAcquiring, AsyncLockStatus.StatusReady);

                // Thread is running from now.

                try
                {
                    // Create the mutex and acquire it.
                    await SetCommandAsync(1, cancellationToken, pollInterval).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex);

                    // If the thread is still alive we must stop it
                    StopThread();

                    ChangeStatus(AsyncLockStatus.StatusReady, AsyncLockStatus.StatusAcquiring);

                    throw ex;
                }

                ChangeStatus(AsyncLockStatus.StatusAcquired, AsyncLockStatus.StatusAcquiring);

                return(new Key(this));
            }
            catch (TaskCanceledException)
            {
                // Let it go.
            }
            catch (AbandonedMutexException)
            {
                // abandoned mutexes are still acquired, we just need
                // to handle the exception and treat it as acquisition
                Logger.LogWarning($"{nameof(AbandonedMutexException)} in {ShortName}.");
                return(new Key(this));
            }
            catch (Exception ex)
            {
                Logger.LogError($"{ex.ToTypeMessageString()} in {ShortName}.");
                inner = ex;
                // Let it go.
            }

            // Release the local lock.
            AsyncLock.ReleaseLock();

            throw new IOException($"Could not acquire system wide mutex on {ShortName}.", inner);
        }
 public RecursiveAsyncLock(IAsyncWaitQueue<IDisposable> queue)
 {
     mutex = new AsyncLock(queue);
 }
예제 #39
0
 /// <summary>
 /// Creates an async-compatible condition variable associated with an async-compatible lock.
 /// </summary>
 /// <param name="asyncLock">The lock associated with this condition variable.</param>
 public AsyncConditionVariable(AsyncLock asyncLock)
     : this(asyncLock, null)
 {
 }