/// <summary> /// Enqueues an upload. /// </summary> /// <param name="username">The username of the remote user.</param> /// <param name="filename">The filename to enqueue.</param> public void Enqueue(string username, string filename) { SyncRoot.Wait(); try { var upload = new Upload() { Username = username, Filename = filename }; Uploads.AddOrUpdate( key: username, addValue: new List <Upload>(new[] { upload }), updateValueFactory: (key, list) => { list.Add(upload); return(list); }); Log.Debug("Enqueued: {File} for {User} at {Time}", Path.GetFileName(upload.Filename), upload.Username, upload.Enqueued); } finally { SyncRoot.Release(); Process(); } }
/// <summary> /// Awaits the start of an upload. /// </summary> /// <param name="username">The username of the remote user.</param> /// <param name="filename">The filename for which to await the start.</param> /// <returns>The operation context.</returns> public Task AwaitStartAsync(string username, string filename) { SyncRoot.Wait(); try { if (!Uploads.TryGetValue(username, out var list)) { throw new SlskdException($"No enqueued uploads for user {username}"); } var upload = list.FirstOrDefault(e => e.Filename == filename); if (upload == default) { throw new SlskdException($"File {filename} is not enqueued for user {username}"); } upload.Ready = DateTime.UtcNow; Log.Debug("Ready: {File} for {User} at {Time}", Path.GetFileName(upload.Filename), upload.Username, upload.Enqueued); return(upload.TaskCompletionSource.Task); } finally { SyncRoot.Release(); Process(); } }
/// <summary> /// Scans the configured <see cref="Directory"/> and fills the cache. /// </summary> public void Fill() { var sw = new Stopwatch(); sw.Start(); Console.WriteLine($"[SHARED FILE CACHE]: Refreshing..."); SyncRoot.EnterWriteLock(); try { CreateTable(); Files = System.IO.Directory.GetFiles(Directory, "*", SearchOption.AllDirectories) .Select(f => new Soulseek.File(1, f, new FileInfo(f).Length, Path.GetExtension(f), 0)) .ToDictionary(f => f.Filename, f => f); // potentially optimize with multi-valued insert // https://stackoverflow.com/questions/16055566/insert-multiple-rows-in-sqlite foreach (var file in Files) { InsertFilename(file.Key); } } finally { SyncRoot.ExitWriteLock(); } sw.Stop(); Console.WriteLine($"[SHARED FILE CACHE]: Refreshed in {sw.ElapsedMilliseconds}ms. Found {Files.Count()} files."); LastFill = DateTime.UtcNow; }
void IDisposable.Dispose() { using (SyncRoot.Enter()) { if (IsDisposed || IsDisposing) { return; } IsDisposing = true; } try { Dispose(true); } catch (Exception) { // Disposing so not much we can do with this exception } finally { IsDisposed = true; } }
public override void OnInspectorGUI() { DrawDefaultInspector(); if (Application.isPlaying) { SharingStage networkManager = (SharingStage)target; SyncRoot root = networkManager.Root; if (root != null) { EditorGUILayout.Separator(); EditorGUILayout.BeginVertical(); { EditorGUILayout.LabelField("Object Hierarchy"); DrawDataModelGUI(root, string.Empty); } EditorGUILayout.EndVertical(); } // Force this inspector to repaint every frame so that it reflects changes to the undo stack // immediately rather than showing stale data until the user clicks on the inspector window Repaint(); } }
public bool TryEnqueue(T item, int timeoutMilliseconds = 0) { if (item == null) { return(false); } //The method only throws exception on thread lock timeout using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { if (IsDisposing || IsDisposed) { return(false); } if (m_count == m_size) { return(false); } m_items[m_tail++] = item; // Place the new item immediately after tail, then increment tail pos m_tail %= m_size; // Modulus new tail pos with size so queue items will wrap around m_count++; // Count will never be more than size after incrementing here //Signal that an item has been enqueued to unblock waiting //dequeue threads syncLock.PulseAll(); return(true); } }
public bool TryDequeue(out T item, int timeoutMilliseconds = 0) { //This method only throws exception on thread lock timeout using (IWaitable syncRoot = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { if (IsDisposing || IsDisposed) { item = null; return(false); } if (m_count == 0) { item = null; return(false); } item = m_items[m_head]; // Get item at head of queue m_items[m_head++] = null; // Clear item at head of queue then increment head pos m_head %= m_size; // Modulus new head pos with size so queue items will wrap around m_count--; // Count will never be less than zero after decrementing here //Signal that an item has been dequeued to unblock waiting //enqueue threads syncRoot.PulseAll(); return(true); } }
} // OperatingParameters constructor private void InitializeOnFirstUse ( SyncRoot ps_srCriticalSection , AppSettingsForEntryAssembly pappSettingsForEntryAssembly , SettingsPropertyCollection psettingsPropertyValueCollection ) { lock ( ps_srCriticalSection ) _settingsPropertyValueCollection = psettingsPropertyValueCollection; } // private void InitializeOnFirstUse
} // GetTheSingleInstance Method private void InitializeOnFirstUse ( SyncRoot ps_srCriticalSection , OperatingParametersCollection<T, U> operatingParametersCollection ) { lock ( ps_srCriticalSection ) { } // lock ( ps_srCriticalSection ) } // private void InitializeOnFirstUse
public void Set(T token) { using (SyncRoot.Enter()) { var signal = GetSignal(token); signal.Set(); } }
protected override void Dispose(bool disposing) { using (SyncRoot.Enter()) { Clear(); m_items = null; } }
private AutoResetEvent GetSignal(T token) { using (SyncRoot.Enter()) { if (!m_signals.ContainsKey(token)) { m_signals[token] = new AutoResetEvent(false); } return(m_signals[token]); } }
public void Clear() { using (IWaitable syncLock = SyncRoot.Enter() as IWaitable) { //Unblock waiting threads syncLock.PulseAll(); m_count = 0; m_head = 0; m_tail = 0; m_items = new T[m_size]; } }
/// <summary> /// <c>Release</c> an object and add it back into the pool - increases pool size if the pool is full /// </summary> /// <param name="item">the object released back into the pool</param> /// <exception cref="ObjectDisposedException">throws when accessed during or after disposal</exception> public override void Release(T item) { if (!TryRelease(item)) //Tf the pool is full { using (SyncRoot.Enter()) { if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(PrimitiveObjectPool <T>)); } m_internalStorage.Add(item); //This will increment storage bag count Size++; } } }
public override void AcceptVisitor(StatementVisitor visitor) { visitor.VisitLockStatement(this); if (SyncRoot != null) { SyncRoot.AcceptVisitor(visitor); } if (EnterTimeout != null) { EnterTimeout.AcceptVisitor(visitor); } if (Body != null) { Body.AcceptVisitor(visitor); } }
protected T ExecStoredProcedure <T>(params object[] arguments) { using (_logger.BeginScope(nameof(ExecStoredProcedure))) { try { _logger.LogDebug("Searching for calling method"); var stackFrames = new StackTrace().GetFrames(); var caller = stackFrames.Select(x => (MethodInfo)x.GetMethod()) .Skip(1) .FirstOrDefault(x => typeof(DbContext).IsAssignableFrom(x.DeclaringType)); if (caller == null) { throw new MissingMethodException("Caller procedure could not be found, probably it was removed by optimizer. Check if caller method is marked by [MethodImpl(MethodImplOptions.NoInlining)]"); } var fullName = $"{caller.DeclaringType.FullName}.{caller.Name}"; lock (SyncRoot.Get(fullName)) { _logger.LogDebug($"Found: {fullName}"); if (arguments.Length != caller.GetParameters().Length) { throw new InvalidOperationException("ExecStoredProcedure is executed with invalid number of arguments"); } var logger = _parameters.LoggerFactory.CreateLogger($"{nameof(DbContextProxyHelper)}.{nameof(DbContextProxyHelper.CreateProxy)}"); var callerProxyMethod = _dbContextHelper.CreateProxy(caller, logger); _logger.LogTrace("Calling proxy method"); var result = (T)callerProxyMethod.Invoke(null, arguments.Prepend(this).ToArray()); return(result); } } catch (Exception e) { _logger.LogError(e, e.Message); throw; } } }
public void Enqueue(T item, int timeoutMilliseconds = -1) { if (item == null) { throw new ArgumentNullException("item", "item cannot be null"); } if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { //While the queue is full, wait for an empty space //Timeout won't be exact if multiple enqueues are blocked on a full queue //So a dequeue could be followed by a different enqueue so this will wait //for another loop while (m_count == m_size) { //Wait for a pulse from a dequeue if (!syncLock.Wait(timeoutMilliseconds)) { throw new TimeoutException("Enqueue timed out while waiting for available queue space"); } //Double check not disposed since waiting for available space if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } } m_items[m_tail++] = item; // Place the new item immediately after tail, then increment tail pos m_tail %= m_size; // Modulus new tail pos with size so queue items will wrap around m_count++; // Count will never be more than size after incrementing here //Signal that an item has been enqueued to unblock waiting //dequeue threads syncLock.PulseAll(); } }
/// <summary> /// Signals the completion of an upload. /// </summary> /// <param name="username">The username of the remote user.</param> /// <param name="filename">The completed filename.</param> public void Complete(string username, string filename) { SyncRoot.Wait(); try { if (!Uploads.TryGetValue(username, out var list)) { throw new SlskdException($"No enqueued uploads for user {username}"); } var upload = list.FirstOrDefault(e => e.Filename == filename); if (upload == default) { throw new SlskdException($"File {filename} is not enqueued for user {username}"); } list.Remove(upload); Log.Debug("Complete: {File} for {User} at {Time}", Path.GetFileName(upload.Filename), upload.Username, upload.Enqueued); // ensure the slot is returned to the group from which it was acquired the group may have been removed during the // transfer. if so, do nothing. if (Groups.ContainsKey(upload.Group ?? string.Empty)) { var group = Groups[upload.Group]; group.UsedSlots = Math.Max(0, group.UsedSlots - 1); Log.Debug("Group {Group} slots: {Used}/{Available}", group.Name, group.UsedSlots, group.Slots); } if (!list.Any() && Uploads.TryRemove(username, out _)) { Log.Debug("Cleaned up tracking list for {User}; no more queued uploads to track", username); } } finally { SyncRoot.Release(); Process(); } }
/// <summary> /// Adds a new arena team member /// Calls ArenaTeamMgr.OnJoinTeam /// </summary> /// <param name="chr">character to add</param> /// <returns>ArenaTeamMember of new member</returns> public ArenaTeamMember AddMember(CharacterRecord chr) { ArenaTeamMember newMember; if (Members.Count >= Type * 2) { return(null); } SyncRoot.Enter(); try { if (Members.TryGetValue(chr.EntityLowId, out newMember)) { return(newMember); } newMember = new ArenaTeamMember(chr, this, false); newMember.Character.SetArenaTeamInfoField(Slot, ArenaTeamInfoType.ARENA_TEAM_ID, Id); newMember.Character.SetArenaTeamInfoField(Slot, ArenaTeamInfoType.ARENA_TEAM_MEMBER, 1); Members.Add(newMember.Id, newMember); newMember.Create(); Update(); } catch (Exception e) { LogUtil.ErrorException(e, string.Format("Could not add member {0} to arena team {1}", chr, this)); return(null); } finally { SyncRoot.Exit(); } ArenaMgr.RegisterArenaTeamMember(newMember); //ArenaTeamHandler.SendEventToTeam(this, ArenaTeamEvents.JOINED_SS, newMember); return(newMember); }
private async Task AttemptReconnect() { if (await SyncRoot.WaitAsync(0)) { try { if (State.CurrentValue.Server.IsConnected) { return; } var attempts = 1; while (true) { var(delay, jitter) = Compute.ExponentialBackoffDelay( iteration: attempts, maxDelayInMilliseconds: ReconnectMaxDelayMilliseconds); var approximateDelay = (int)Math.Ceiling((double)(delay + jitter) / 1000); Log.Information($"Waiting about {(approximateDelay == 1 ? "a second" : $"{approximateDelay} seconds")} before reconnecting"); await Task.Delay(delay + jitter); Log.Information("Attempting to reconnect (#{Attempts})...", attempts); try { // reconnect with the latest configuration values we have for username and password, instead of the // options that were captured at startup. if a user has updated these values prior to the disconnect, // the changes will take effect now. await Client.ConnectAsync(Options.CurrentValue.Soulseek.Username, Options.CurrentValue.Soulseek.Password); break; } catch (Exception ex) { attempts++; Log.Error("Failed to reconnect: {Message}", ex.Message); } } }
/// <summary> /// <c>TryObtain</c> an object and remove it from the pool - does not throw an exception if pool is empty /// </summary> /// <param name="item">the object obtained from the pool, if successful - null if unsuccessful</param> /// <returns>returns true if successful, false if unsuccessful i.e. pool is empty</returns> /// <exception cref="ObjectDisposedException">throws when accessed during or after disposal</exception> public bool TryObtain(out T item) { using (SyncRoot.Enter()) { //This is called from Obtain so only need to check dispose state here if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(PrimitiveObjectPool <T>)); } if (m_internalStorage.TryTake(out item)) //This will decrement count { InUse++; return(true); } else //if bag is empty { return(false); } } }
/// <summary> /// <c>Obtain</c> and remove an object from the pool - increases pool size if the pool is empty /// </summary> /// <returns>returns an object of type <typeparamref name="T"/> from the pool</returns> /// <exception cref="ObjectDisposedException">throws when accessed during or after disposal</exception> public override T Obtain() { if (TryObtain(out T item)) { return(item); } else //If the pool is empty { using (SyncRoot.Enter()) { if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(PrimitiveObjectPool <T>)); } InUse++; Size++; //Increment Size so releasing item will just add to pool in TryRelease return(new T()); //Create new item } } }
public bool TryPeek(out T item, int timeoutMilliseconds = 0) { //This method only throws exception on thread lock timeout using (SyncRoot.Enter(timeoutMilliseconds)) { if (IsDisposing || IsDisposed) { item = null; return(false); } if (m_count == 0) { item = null; return(false); } item = m_items[m_head]; return(true); } }
public T Peek(int timeoutMilliseconds = -1, bool waitForEnqueue = false) { using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } if (m_count == 0) { if (waitForEnqueue) { //While queue is empty, wait for an item to enqueue while (m_count == 0) { //Wait for a signal from an enqueue if (!syncLock.Wait(timeoutMilliseconds)) { throw new TimeoutException("Dequeue timed out while waiting for queue item to dequeue"); } //Double check not disposed since waiting for item to be enqueued if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } } } else { throw new InvalidOperationException("Bounded Blocking Queue is empty"); } } T value = m_items[m_head]; return(value); } }
private IEnumerable <Soulseek.File> QueryTable(string text) { // sanitize the query string. there's probably more to it than this. text = text .Replace("/", " ") .Replace("\\", " ") .Replace(":", " ") .Replace("\"", " "); var query = $"SELECT * FROM cache WHERE cache MATCH '\"{text.Replace("'", "''")}\"'"; SyncRoot.EnterReadLock(); try { using (var cmd = new SqliteCommand(query, SQLite)) { var results = new List <string>(); var reader = cmd.ExecuteReader(); while (reader.Read()) { results.Add(reader.GetString(0)); } return(results.Select(r => Files[r.Replace("''", "'")])); } } catch (Exception ex) { // temporary error trap to refine substitution rules Console.WriteLine($"[MALFORMED QUERY]: {query} ({ex.Message})"); return(Enumerable.Empty <Soulseek.File>()); } finally { SyncRoot.ExitReadLock(); } }
public T Dequeue(int timeoutMilliseconds = -1) { if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable) { //Similar reasoning for here from Enqueue method //While queue is empty, wait for an item to enqueue while (m_count == 0) { //Wait for a signal from an enqueue if (!syncLock.Wait(timeoutMilliseconds)) { throw new TimeoutException("Dequeue timed out while waiting for queue item to dequeue"); } //Double check not disposed since waiting for item to be enqueued if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>)); } } T value = m_items[m_head]; // Get item at head of queue m_items[m_head++] = null; // Clear item at head of queue then increment head pos m_head %= m_size; // Modulus new head pos with size so queue items will wrap around m_count--; // Count will never be less than zero after decrementing here //Signal that an item has been dequeued to unblock waiting //enqueue threads syncLock.PulseAll(); return(value); } }
/// <summary> /// Сохраняет свою сделку. /// </summary> /// <param name="fill">Данные своей сделки.</param> protected void AddFill(FillMessage fill) { if (!storeFillsInMemory) { return; } if (!IsPermittedAccount(fill.Account)) { return; } using (SyncRoot.Lock()) { Dictionary <Instrument, List <FillMessage> > accountFills; if (!AvailableAccounts.Contains(fill.Account)) { AvailableAccounts.Add(fill.Account); accountFills = new Dictionary <Instrument, List <FillMessage> >(); Fills.Add(fill.Account, accountFills); } else { accountFills = Fills[fill.Account]; } List <FillMessage> instrumentFills; if (!accountFills.TryGetValue(fill.Instrument, out instrumentFills)) { instrumentFills = new List <FillMessage>(); accountFills.Add(fill.Instrument, instrumentFills); } instrumentFills.Add(fill); } }
/// <summary> /// <c>TryRelease</c> an object and add it back into the pool - does not throw exception if pool is full /// </summary> /// <param name="item">the object released back into the pool</param> /// <returns>returns true if successful, false if successful i.e. if pool is full</returns> /// <exception cref="ObjectDisposedException">throws when accessed during or after disposal</exception> public bool TryRelease(T item) { using (SyncRoot.Enter()) { //This is called from Obtain so only need to check dispose state here if (IsDisposing || IsDisposed) { throw new ObjectDisposedException(nameof(PrimitiveObjectPool <T>)); } //If storage bag is full i.e., equal to initial size, don't release item into bag if (m_internalStorage.Count == Size) { return(false); } else { m_internalStorage.Add(item); //This will increment storage bag count InUse--; return(true); } } }
protected bool AddAccount(string account) { if (string.IsNullOrWhiteSpace(account)) { return(false); } if (!IsPermittedAccount(account)) { return(false); } using (SyncRoot.Lock()) { if (AvailableAccounts.Contains(account)) { return(false); } AvailableAccounts.Add(account); Fills.Add(account, new Dictionary <Instrument, List <FillMessage> >()); return(true); } }
public void Exit() { SyncRoot.Exit(); }