Changed all locks to SemaphoreSlims, Slight musicbuffer changes.

This commit is contained in:
Kwoth 2016-07-23 15:04:33 +02:00
parent 106a779552
commit e66615b056
15 changed files with 173 additions and 135 deletions

View File

@ -6,6 +6,8 @@ using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace NadekoBot.Classes namespace NadekoBot.Classes
{ {
@ -27,9 +29,12 @@ namespace NadekoBot.Classes
{ {
configs = JsonConvert configs = JsonConvert
.DeserializeObject<ConcurrentDictionary<ulong, ServerSpecificConfig>>( .DeserializeObject<ConcurrentDictionary<ulong, ServerSpecificConfig>>(
File.ReadAllText(filePath), new JsonSerializerSettings() { File.ReadAllText(filePath), new JsonSerializerSettings()
Error = (s,e) => { {
if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels") { Error = (s, e) =>
{
if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels")
{
e.ErrorContext.Handled = true; e.ErrorContext.Handled = true;
} }
} }
@ -52,14 +57,19 @@ namespace NadekoBot.Classes
public ServerSpecificConfig Of(ulong id) => public ServerSpecificConfig Of(ulong id) =>
configs.GetOrAdd(id, _ => new ServerSpecificConfig()); configs.GetOrAdd(id, _ => new ServerSpecificConfig());
private readonly object saveLock = new object(); private readonly SemaphoreSlim saveLock = new SemaphoreSlim(1, 1);
public void Save() public async Task Save()
{ {
lock (saveLock) await saveLock.WaitAsync();
try
{ {
File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented)); File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented));
} }
finally
{
saveLock.Release();
}
} }
} }
@ -245,7 +255,7 @@ namespace NadekoBot.Classes
LogserverIgnoreChannels = new ObservableCollection<ulong>(); LogserverIgnoreChannels = new ObservableCollection<ulong>();
} }
public event PropertyChangedEventHandler PropertyChanged = delegate { SpecificConfigurations.Default.Save(); }; public event PropertyChangedEventHandler PropertyChanged = async delegate { await SpecificConfigurations.Default.Save().ConfigureAwait(false); };
private void OnPropertyChanged([CallerMemberName] string propertyName = null) private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{ {

View File

@ -70,7 +70,7 @@ namespace NadekoBot.Modules.Administration
{ {
var conf = SpecificConfigurations.Default.Of(e.Server.Id); var conf = SpecificConfigurations.Default.Of(e.Server.Id);
conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand; conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand;
Classes.JSONModels.ConfigHandler.SaveConfig(); await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
if (conf.AutoDeleteMessagesOnCommand) if (conf.AutoDeleteMessagesOnCommand)
await e.Channel.SendMessage("❗`Now automatically deleting successfull command invokations.`"); await e.Channel.SendMessage("❗`Now automatically deleting successfull command invokations.`");
else else

View File

@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Administration.Commands
NadekoBot.Config.CustomReactions[name].Add(message); NadekoBot.Config.CustomReactions[name].Add(message);
else else
NadekoBot.Config.CustomReactions.Add(name, new System.Collections.Generic.List<string>() { message }); NadekoBot.Config.CustomReactions.Add(name, new System.Collections.Generic.List<string>() { message });
await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false); await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
await e.Channel.SendMessage($"Added {name} : {message}").ConfigureAwait(false); await e.Channel.SendMessage($"Added {name} : {message}").ConfigureAwait(false);
}); });
@ -140,7 +140,7 @@ namespace NadekoBot.Modules.Administration.Commands
index = index - 1; index = index - 1;
NadekoBot.Config.CustomReactions[name][index] = msg; NadekoBot.Config.CustomReactions[name][index] = msg;
await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false); await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
await e.Channel.SendMessage($"Edited response #{index + 1} from `{name}`").ConfigureAwait(false); await e.Channel.SendMessage($"Edited response #{index + 1} from `{name}`").ConfigureAwait(false);
}); });
@ -183,7 +183,7 @@ namespace NadekoBot.Modules.Administration.Commands
NadekoBot.Config.CustomReactions.Remove(name); NadekoBot.Config.CustomReactions.Remove(name);
message = $"Deleted custom reaction: `{name}`"; message = $"Deleted custom reaction: `{name}`";
} }
await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false); await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
await e.Channel.SendMessage(message).ConfigureAwait(false); await e.Channel.SendMessage(message).ConfigureAwait(false);
}); });
} }

View File

@ -7,8 +7,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers; using System.Timers;
using Timer = System.Timers.Timer;
namespace NadekoBot.Modules.Administration.Commands namespace NadekoBot.Modules.Administration.Commands
{ {
@ -36,7 +38,7 @@ namespace NadekoBot.Modules.Administration.Commands
{"%trivia%", () => Games.Commands.TriviaCommands.RunningTrivias.Count.ToString()} {"%trivia%", () => Games.Commands.TriviaCommands.RunningTrivias.Count.ToString()}
}; };
private readonly object playingPlaceholderLock = new object(); private readonly SemaphoreSlim playingPlaceholderLock = new SemaphoreSlim(1,1);
public PlayingRotate(DiscordModule module) : base(module) public PlayingRotate(DiscordModule module) : base(module)
{ {
@ -47,7 +49,9 @@ namespace NadekoBot.Modules.Administration.Commands
{ {
i++; i++;
var status = ""; var status = "";
lock (playingPlaceholderLock) //wtf am i doing, just use a queue ffs
await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
try
{ {
if (PlayingPlaceholders.Count == 0 if (PlayingPlaceholders.Count == 0
|| NadekoBot.Config.RotatingStatuses.Count == 0 || NadekoBot.Config.RotatingStatuses.Count == 0
@ -59,6 +63,7 @@ namespace NadekoBot.Modules.Administration.Commands
status = PlayingPlaceholders.Aggregate(status, status = PlayingPlaceholders.Aggregate(status,
(current, kvp) => current.Replace(kvp.Key, kvp.Value())); (current, kvp) => current.Replace(kvp.Key, kvp.Value()));
} }
finally { playingPlaceholderLock.Release(); }
if (string.IsNullOrWhiteSpace(status)) if (string.IsNullOrWhiteSpace(status))
return; return;
await Task.Run(() => { NadekoBot.Client.SetGame(status); }); await Task.Run(() => { NadekoBot.Client.SetGame(status); });
@ -71,14 +76,18 @@ namespace NadekoBot.Modules.Administration.Commands
public Func<CommandEventArgs, Task> DoFunc() => async e => public Func<CommandEventArgs, Task> DoFunc() => async e =>
{ {
lock (playingPlaceholderLock) await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
try
{ {
if (timer.Enabled) if (timer.Enabled)
timer.Stop(); timer.Stop();
else else
timer.Start(); timer.Start();
NadekoBot.Config.IsRotatingStatus = timer.Enabled; NadekoBot.Config.IsRotatingStatus = timer.Enabled;
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
}
finally {
playingPlaceholderLock.Release();
} }
await e.Channel.SendMessage($"❗`Rotating playing status has been {(timer.Enabled ? "enabled" : "disabled")}.`").ConfigureAwait(false); await e.Channel.SendMessage($"❗`Rotating playing status has been {(timer.Enabled ? "enabled" : "disabled")}.`").ConfigureAwait(false);
}; };
@ -102,10 +111,15 @@ namespace NadekoBot.Modules.Administration.Commands
var arg = e.GetArg("text"); var arg = e.GetArg("text");
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
return; return;
lock (playingPlaceholderLock) await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
try
{ {
NadekoBot.Config.RotatingStatuses.Add(arg); NadekoBot.Config.RotatingStatuses.Add(arg);
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig();
}
finally
{
playingPlaceholderLock.Release();
} }
await e.Channel.SendMessage("🆗 `Added a new playing string.`").ConfigureAwait(false); await e.Channel.SendMessage("🆗 `Added a new playing string.`").ConfigureAwait(false);
}); });
@ -137,14 +151,15 @@ namespace NadekoBot.Modules.Administration.Commands
var arg = e.GetArg("number"); var arg = e.GetArg("number");
int num; int num;
string str; string str;
lock (playingPlaceholderLock) await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
{ try {
if (!int.TryParse(arg.Trim(), out num) || num <= 0 || num > NadekoBot.Config.RotatingStatuses.Count) if (!int.TryParse(arg.Trim(), out num) || num <= 0 || num > NadekoBot.Config.RotatingStatuses.Count)
return; return;
str = NadekoBot.Config.RotatingStatuses[num - 1]; str = NadekoBot.Config.RotatingStatuses[num - 1];
NadekoBot.Config.RotatingStatuses.RemoveAt(num - 1); NadekoBot.Config.RotatingStatuses.RemoveAt(num - 1);
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
} }
finally { playingPlaceholderLock.Release(); }
await e.Channel.SendMessage($"🆗 `Removed playing string #{num}`({str})").ConfigureAwait(false); await e.Channel.SendMessage($"🆗 `Removed playing string #{num}`({str})").ConfigureAwait(false);
}); });
} }

View File

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Modules.Permissions.Classes; using NadekoBot.Modules.Permissions.Classes;
using System.Threading;
namespace NadekoBot.Modules.ClashOfClans namespace NadekoBot.Modules.ClashOfClans
{ {
@ -16,8 +17,6 @@ namespace NadekoBot.Modules.ClashOfClans
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; } = new ConcurrentDictionary<ulong, List<ClashWar>>(); public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
private readonly object writeLock = new object();
public override void Install(ModuleManager manager) public override void Install(ModuleManager manager)
{ {
manager.CreateCommands("", cgb => manager.CreateCommands("", cgb =>

View File

@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Modules.Games.Commands namespace NadekoBot.Modules.Games.Commands
@ -59,7 +60,7 @@ namespace NadekoBot.Modules.Games.Commands
//channelid/messageid pair //channelid/messageid pair
ConcurrentDictionary<ulong, IEnumerable<Message>> plantedFlowerChannels = new ConcurrentDictionary<ulong, IEnumerable<Message>>(); ConcurrentDictionary<ulong, IEnumerable<Message>> plantedFlowerChannels = new ConcurrentDictionary<ulong, IEnumerable<Message>>();
private object locker = new object(); private SemaphoreSlim locker = new SemaphoreSlim(1,1);
internal override void Init(CommandGroupBuilder cgb) internal override void Init(CommandGroupBuilder cgb)
{ {
@ -84,32 +85,34 @@ namespace NadekoBot.Modules.Games.Commands
cgb.CreateCommand(Module.Prefix + "plant") cgb.CreateCommand(Module.Prefix + "plant")
.Description("Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost)") .Description("Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost)")
.Do(e => .Do(async e =>
{ {
lock (locker) await locker.WaitAsync().ConfigureAwait(false);
try
{ {
if (plantedFlowerChannels.ContainsKey(e.Channel.Id)) if (plantedFlowerChannels.ContainsKey(e.Channel.Id))
{ {
e.Channel.SendMessage($"There is already a {NadekoBot.Config.CurrencyName} in this channel."); await e.Channel.SendMessage($"There is already a {NadekoBot.Config.CurrencyName} in this channel.").ConfigureAwait(false);
return; return;
} }
var removed = FlowersHandler.RemoveFlowers(e.User, "Planted a flower.", 1, true).GetAwaiter().GetResult(); var removed = await FlowersHandler.RemoveFlowers(e.User, "Planted a flower.", 1, true).ConfigureAwait(false);
if (!removed) if (!removed)
{ {
e.Channel.SendMessage($"You don't have any {NadekoBot.Config.CurrencyName}s.").Wait(); await e.Channel.SendMessage($"You don't have any {NadekoBot.Config.CurrencyName}s.").ConfigureAwait(false);
return; return;
} }
var file = GetRandomCurrencyImagePath(); var file = GetRandomCurrencyImagePath();
Message msg; Message msg;
if (file == null) if (file == null)
msg = e.Channel.SendMessage(NadekoBot.Config.CurrencySign).GetAwaiter().GetResult(); msg = await e.Channel.SendMessage(NadekoBot.Config.CurrencySign).ConfigureAwait(false);
else else
msg = e.Channel.SendFile(file).GetAwaiter().GetResult(); msg = await e.Channel.SendFile(file).ConfigureAwait(false);
var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(NadekoBot.Config.CurrencyName[0]); var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(NadekoBot.Config.CurrencyName[0]);
var msg2 = e.Channel.SendMessage($"Oh how Nice! **{e.User.Name}** planted {(vowelFirst ? "an" : "a")} {NadekoBot.Config.CurrencyName}. Pick it using {Module.Prefix}pick").GetAwaiter().GetResult(); var msg2 = await e.Channel.SendMessage($"Oh how Nice! **{e.User.Name}** planted {(vowelFirst ? "an" : "a")} {NadekoBot.Config.CurrencyName}. Pick it using {Module.Prefix}pick").ConfigureAwait(false);
plantedFlowerChannels.TryAdd(e.Channel.Id, new[] { msg, msg2 }); plantedFlowerChannels.TryAdd(e.Channel.Id, new[] { msg, msg2 });
} }
finally { locker.Release(); }
}); });
cgb.CreateCommand(Prefix + "gencurrency") cgb.CreateCommand(Prefix + "gencurrency")
@ -129,12 +132,12 @@ namespace NadekoBot.Modules.Games.Commands
int throwaway; int throwaway;
if (config.GenerateCurrencyChannels.TryRemove(e.Channel.Id, out throwaway)) if (config.GenerateCurrencyChannels.TryRemove(e.Channel.Id, out throwaway))
{ {
await e.Channel.SendMessage("`Currency generation disabled on this channel.`"); await e.Channel.SendMessage("`Currency generation disabled on this channel.`").ConfigureAwait(false);
} }
else else
{ {
if (config.GenerateCurrencyChannels.TryAdd(e.Channel.Id, cd)) if (config.GenerateCurrencyChannels.TryAdd(e.Channel.Id, cd))
await e.Channel.SendMessage($"`Currency generation enabled on this channel. Cooldown is {cd} minutes.`"); await e.Channel.SendMessage($"`Currency generation enabled on this channel. Cooldown is {cd} minutes.`").ConfigureAwait(false);
} }
}); });
} }

View File

@ -13,7 +13,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
{ {
internal class TriviaGame internal class TriviaGame
{ {
private readonly object _guessLock = new object(); private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1,1);
private Server server { get; } private Server server { get; }
private Channel channel { get; } private Channel channel { get; }
@ -113,7 +113,8 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return; if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return;
var guess = false; var guess = false;
lock (_guessLock) await _guessLock.WaitAsync().ConfigureAwait(false);
try
{ {
if (GameActive && CurrentQuestion.IsAnswerCorrect(e.Message.Text) && !triviaCancelSource.IsCancellationRequested) if (GameActive && CurrentQuestion.IsAnswerCorrect(e.Message.Text) && !triviaCancelSource.IsCancellationRequested)
{ {
@ -122,6 +123,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
guess = true; guess = true;
} }
} }
catch { _guessLock.Release(); }
if (!guess) return; if (!guess) return;
triviaCancelSource.Cancel(); triviaCancelSource.Cancel();
await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false); await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);

View File

@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Music.Classes
public int BufferSize { get; } public int BufferSize { get; }
private readonly object readWriteLock = new object(); private readonly SemaphoreSlim readWriteLock = new SemaphoreSlim(1, 1);
public PoopyBuffer(int size) public PoopyBuffer(int size)
{ {
@ -32,51 +32,57 @@ namespace NadekoBot.Modules.Music.Classes
ringBuffer = new byte[size]; ringBuffer = new byte[size];
} }
public int Read(byte[] buffer, int count) public Task<int> ReadAsync(byte[] buffer, int count)
{ {
if (buffer.Length < count) return Task.Run(async () =>
throw new ArgumentException();
//Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***");
lock (readWriteLock)
{ {
//read as much as you can if you're reading too much if (buffer.Length < count)
if (count > ContentLength) throw new ArgumentException();
count = ContentLength; //Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***");
//if nothing to read, return 0 await readWriteLock.WaitAsync().ConfigureAwait(false);
if (WritePosition == ReadPosition) try
return 0;
// if buffer is in the "normal" state, just read
if (WritePosition > ReadPosition)
{ {
Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count); //read as much as you can if you're reading too much
ReadPosition += count; if (count > ContentLength)
//Console.WriteLine($"Read only normally1 {count}[{ReadPosition - count} to {ReadPosition}]"); count = ContentLength;
//if nothing to read, return 0
if (WritePosition == ReadPosition)
return 0;
// if buffer is in the "normal" state, just read
if (WritePosition > ReadPosition)
{
Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count);
ReadPosition += count;
//Console.WriteLine($"Read only normally1 {count}[{ReadPosition - count} to {ReadPosition}]");
return count;
}
//else ReadPos <Writepos
// buffer is in its inverted state
// A: if i can read as much as possible without hitting the buffer.length, read that
if (count + ReadPosition <= BufferSize)
{
Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count);
ReadPosition += count;
//Console.WriteLine($"Read only normally2 {count}[{ReadPosition - count} to {ReadPosition}]");
return count;
}
// B: if i can't read as much, read to the end,
var readNormaly = BufferSize - ReadPosition;
Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, readNormaly);
//Console.WriteLine($"Read normaly {count}[{ReadPosition} to {ReadPosition + readNormaly}]");
//then read the remaining amount from the start
var readFromStart = count - readNormaly;
Buffer.BlockCopy(ringBuffer, 0, buffer, readNormaly, readFromStart);
//Console.WriteLine($"Read From start {readFromStart}[{0} to {readFromStart}]");
ReadPosition = readFromStart;
return count; return count;
} }
//else ReadPos <Writepos finally { readWriteLock.Release(); }
// buffer is in its inverted state });
// A: if i can read as much as possible without hitting the buffer.length, read that
if (count + ReadPosition <= BufferSize)
{
Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count);
ReadPosition += count;
//Console.WriteLine($"Read only normally2 {count}[{ReadPosition - count} to {ReadPosition}]");
return count;
}
// B: if i can't read as much, read to the end,
var readNormaly = BufferSize - ReadPosition;
Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, readNormaly);
//Console.WriteLine($"Read normaly {count}[{ReadPosition} to {ReadPosition + readNormaly}]");
//then read the remaining amount from the start
var readFromStart = count - readNormaly;
Buffer.BlockCopy(ringBuffer, 0, buffer, readNormaly, readFromStart);
//Console.WriteLine($"Read From start {readFromStart}[{0} to {readFromStart}]");
ReadPosition = readFromStart;
return count;
}
} }
public async Task WriteAsync(byte[] buffer, int count, CancellationToken cancelToken) public async Task WriteAsync(byte[] buffer, int count, CancellationToken cancelToken)
@ -89,32 +95,37 @@ namespace NadekoBot.Modules.Music.Classes
if (cancelToken.IsCancellationRequested) if (cancelToken.IsCancellationRequested)
return; return;
} }
//the while above assures that i cannot write past readposition with my write, so i don't have to check await Task.Run(async () =>
// *unless its multithreaded or task is not awaited
lock (readWriteLock)
{ {
// if i can just write without hitting buffer.length, do it //the while above assures that i cannot write past readposition with my write, so i don't have to check
if (WritePosition + count < BufferSize) // *unless its multithreaded or task is not awaited
await readWriteLock.WaitAsync().ConfigureAwait(false);
try
{ {
Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, count); // if i can just write without hitting buffer.length, do it
WritePosition += count; if (WritePosition + count < BufferSize)
//Console.WriteLine($"Wrote only normally {count}[{WritePosition - count} to {WritePosition}]"); {
return; Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, count);
WritePosition += count;
//Console.WriteLine($"Wrote only normally {count}[{WritePosition - count} to {WritePosition}]");
return;
}
// otherwise, i have to write to the end, then write the rest from the start
var wroteNormaly = BufferSize - WritePosition;
Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, wroteNormaly);
//Console.WriteLine($"Wrote normally {wroteNormaly}[{WritePosition} to {BufferSize}]");
var wroteFromStart = count - wroteNormaly;
Buffer.BlockCopy(buffer, wroteNormaly, ringBuffer, 0, wroteFromStart);
//Console.WriteLine($"and from start {wroteFromStart} [0 to {wroteFromStart}");
WritePosition = wroteFromStart;
} }
// otherwise, i have to write to the end, then write the rest from the start finally { readWriteLock.Release(); }
});
var wroteNormaly = BufferSize - WritePosition;
Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, wroteNormaly);
//Console.WriteLine($"Wrote normally {wroteNormaly}[{WritePosition} to {BufferSize}]");
var wroteFromStart = count - wroteNormaly;
Buffer.BlockCopy(buffer, wroteNormaly, ringBuffer, 0, wroteFromStart);
//Console.WriteLine($"and from start {wroteFromStart} [0 to {wroteFromStart}");
WritePosition = wroteFromStart;
}
} }
} }
} }

View File

@ -155,7 +155,7 @@ namespace NadekoBot.Modules.Music.Classes
{ {
//Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
byte[] buffer = new byte[blockSize]; byte[] buffer = new byte[blockSize];
var read = songBuffer.Read(buffer, blockSize); var read = await songBuffer.ReadAsync(buffer, blockSize).ConfigureAwait(false);
unchecked unchecked
{ {
bytesSent += (ulong)read; bytesSent += (ulong)read;

View File

@ -689,7 +689,7 @@ namespace NadekoBot.Modules.Permissions
if (!e.Message.MentionedUsers.Any()) return; if (!e.Message.MentionedUsers.Any()) return;
var usr = e.Message.MentionedUsers.First(); var usr = e.Message.MentionedUsers.First();
NadekoBot.Config.UserBlacklist.Add(usr.Id); NadekoBot.Config.UserBlacklist.Add(usr.Id);
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
await e.Channel.SendMessage($"`Sucessfully blacklisted user {usr.Name}`").ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully blacklisted user {usr.Name}`").ConfigureAwait(false);
}).ConfigureAwait(false); }).ConfigureAwait(false);
}); });
@ -707,7 +707,7 @@ namespace NadekoBot.Modules.Permissions
if (NadekoBot.Config.UserBlacklist.Contains(usr.Id)) if (NadekoBot.Config.UserBlacklist.Contains(usr.Id))
{ {
NadekoBot.Config.UserBlacklist.Remove(usr.Id); NadekoBot.Config.UserBlacklist.Remove(usr.Id);
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
await e.Channel.SendMessage($"`Sucessfully unblacklisted user {usr.Name}`").ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully unblacklisted user {usr.Name}`").ConfigureAwait(false);
} }
else else
@ -727,7 +727,7 @@ namespace NadekoBot.Modules.Permissions
if (!e.Message.MentionedChannels.Any()) return; if (!e.Message.MentionedChannels.Any()) return;
var ch = e.Message.MentionedChannels.First(); var ch = e.Message.MentionedChannels.First();
NadekoBot.Config.UserBlacklist.Add(ch.Id); NadekoBot.Config.UserBlacklist.Add(ch.Id);
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false);
}).ConfigureAwait(false); }).ConfigureAwait(false);
}); });
@ -742,7 +742,7 @@ namespace NadekoBot.Modules.Permissions
if (!e.Message.MentionedChannels.Any()) return; if (!e.Message.MentionedChannels.Any()) return;
var ch = e.Message.MentionedChannels.First(); var ch = e.Message.MentionedChannels.First();
NadekoBot.Config.UserBlacklist.Remove(ch.Id); NadekoBot.Config.UserBlacklist.Remove(ch.Id);
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false);
}).ConfigureAwait(false); }).ConfigureAwait(false);
}); });
@ -767,7 +767,7 @@ namespace NadekoBot.Modules.Permissions
} }
var serverId = server.Id; var serverId = server.Id;
NadekoBot.Config.ServerBlacklist.Add(serverId); NadekoBot.Config.ServerBlacklist.Add(serverId);
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
//cleanup trivias and typeracing //cleanup trivias and typeracing
Modules.Games.Commands.Trivia.TriviaGame trivia; Modules.Games.Commands.Trivia.TriviaGame trivia;
TriviaCommands.RunningTrivias.TryRemove(serverId, out trivia); TriviaCommands.RunningTrivias.TryRemove(serverId, out trivia);

View File

@ -30,8 +30,6 @@ namespace NadekoBot.Modules.Searches.Commands
} }
private static Dictionary<string, CachedChampion> CachedChampionImages = new Dictionary<string, CachedChampion>(); private static Dictionary<string, CachedChampion> CachedChampionImages = new Dictionary<string, CachedChampion>();
private readonly object cacheLock = new object();
private System.Timers.Timer clearTimer { get; } = new System.Timers.Timer(); private System.Timers.Timer clearTimer { get; } = new System.Timers.Timer();
public LoLCommands(DiscordModule module) : base(module) public LoLCommands(DiscordModule module) : base(module)
@ -42,7 +40,6 @@ namespace NadekoBot.Modules.Searches.Commands
{ {
try try
{ {
lock (cacheLock)
CachedChampionImages = CachedChampionImages CachedChampionImages = CachedChampionImages
.Where(kvp => DateTime.Now - kvp.Value.AddedAt > new TimeSpan(1, 0, 0)) .Where(kvp => DateTime.Now - kvp.Value.AddedAt > new TimeSpan(1, 0, 0))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
@ -87,16 +84,14 @@ namespace NadekoBot.Modules.Searches.Commands
var resolvedRole = role; var resolvedRole = role;
var name = e.GetArg("champ").Replace(" ", "").ToLower(); var name = e.GetArg("champ").Replace(" ", "").ToLower();
CachedChampion champ = null; CachedChampion champ = null;
lock (cacheLock)
{ if(CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ))
CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ); if (champ != null)
} {
if (champ != null) champ.ImageStream.Position = 0;
{ await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false);
champ.ImageStream.Position = 0; return;
await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); }
return;
}
var allData = JArray.Parse(await Classes.SearchHelper.GetResponseStringAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.Creds.LOLAPIKey}").ConfigureAwait(false)); var allData = JArray.Parse(await Classes.SearchHelper.GetResponseStringAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.Creds.LOLAPIKey}").ConfigureAwait(false));
JToken data = null; JToken data = null;
if (role != null) if (role != null)
@ -121,17 +116,13 @@ namespace NadekoBot.Modules.Searches.Commands
role = allData[0]["role"].ToString(); role = allData[0]["role"].ToString();
resolvedRole = ResolvePos(role); resolvedRole = ResolvePos(role);
} }
lock (cacheLock) if(CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ))
{ if (champ != null)
CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ); {
} champ.ImageStream.Position = 0;
if (champ != null) await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false);
{ return;
Console.WriteLine("Sending lol image from cache."); }
champ.ImageStream.Position = 0;
await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false);
return;
}
//name = data["title"].ToString(); //name = data["title"].ToString();
// get all possible roles, and "select" the shown one // get all possible roles, and "select" the shown one
var roles = new string[allData.Count]; var roles = new string[allData.Count];

View File

@ -68,7 +68,7 @@ namespace NadekoBot.Modules.Searches.Commands
} }
} }
catch { } catch { }
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
}; };
checkTimer.Start(); checkTimer.Start();
} }
@ -254,7 +254,7 @@ namespace NadekoBot.Modules.Searches.Commands
} }
config.ObservingStreams.Remove(toRemove); config.ObservingStreams.Remove(toRemove);
ConfigHandler.SaveConfig(); await ConfigHandler.SaveConfig().ConfigureAwait(false);
await e.Channel.SendMessage($":ok: Removed `{toRemove.Username}`'s stream from notifications.").ConfigureAwait(false); await e.Channel.SendMessage($":ok: Removed `{toRemove.Username}`'s stream from notifications.").ConfigureAwait(false);
}); });

View File

@ -197,7 +197,7 @@ namespace NadekoBot
return; return;
} }
#if NADEKO_RELEASE #if NADEKO_RELEASE
await Task.Delay(90000).ConfigureAwait(false); await Task.Delay(100000).ConfigureAwait(false);
#else #else
await Task.Delay(1000).ConfigureAwait(false); await Task.Delay(1000).ConfigureAwait(false);
#endif #endif

View File

@ -78,13 +78,14 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants> <DefineConstants>TRACE;DEBUG</DefineConstants>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath> <OutputPath>bin\x64\Release\</OutputPath>

View File

@ -4,6 +4,8 @@ using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
namespace NadekoBot.Classes.JSONModels namespace NadekoBot.Classes.JSONModels
{ {
@ -187,13 +189,17 @@ Nadeko Support Server: <https://discord.gg/0ehQwTK2RBjAxzEY>";
public static class ConfigHandler public static class ConfigHandler
{ {
private static readonly object configLock = new object(); private static readonly SemaphoreSlim configLock = new SemaphoreSlim(1, 1);
public static void SaveConfig() public static async Task SaveConfig()
{ {
lock (configLock) await configLock.WaitAsync();
try
{ {
File.WriteAllText("data/config.json", JsonConvert.SerializeObject(NadekoBot.Config, Formatting.Indented)); File.WriteAllText("data/config.json", JsonConvert.SerializeObject(NadekoBot.Config, Formatting.Indented));
} }
finally {
configLock.Release();
}
} }
public static bool IsBlackListed(MessageEventArgs evArgs) => IsUserBlacklisted(evArgs.User.Id) || public static bool IsBlackListed(MessageEventArgs evArgs) => IsUserBlacklisted(evArgs.User.Id) ||