/// <summary> /// DialTimeout acts like Dial but takes a timeout. The timeout includes name resolution, if required. /// </summary> public static IConn DialTimeout(string network, string address, TimeSpan timeout) { if (network != "tcp") throw new ArgumentException("only 'tcp' network is supported", "network"); var dialChan = new Chan<IConn>(); var timeoutChan = Time.After(timeout); GoFunc.Run(() => { try { var tmpConn = Dial(network, address); dialChan.Send(tmpConn); } catch { // handling timeout below, don't bring down the whole app with an unhandled thread exception } }, "Net:DialTimeout"); IConn conn = null; Select .CaseReceive(dialChan, c => conn = c) .CaseReceive(timeoutChan, o => { throw new TimeoutException(string.Format("timeout {0} exceed when dialing {1}", timeout, address)); }) .NoDefault(); timeoutChan.Close(); return conn; }
public void BufferedChannelsDontBlock() { var c = new Chan<int>(1); c.Send(2); int actual = c.Receive(); Assert.AreEqual(2, actual); }
public void Count() { var chan = new Chan<int>(); chan .Send(Enumerable.Range(0, 10)) .ContinueWith(t => chan.Close()); var counting = chan.Count(); if (!counting.Wait(TimeSpan.FromSeconds(10))) { Assert.Fail(); } Assert.AreEqual(10, counting.Result); }
public void BufferedChannelsReceiveSelectInGoroutineSendOnMainThread() { var c = new Chan<int>(10); var list = new List<int>(); var wg = new WaitGroup(); wg.Add(1); GoFunc.Run(() => { bool doLoop = true; while (doLoop) { Select .CaseReceiveOk(c, (i, ok) => { if (ok) list.Add(i); else doLoop = false; }) .NoDefault(); } wg.Done(); }, "bufferChannelsTest:receiveLoop"); for (int i = 0; i < 10; i++) { c.Send(i); } c.Close(); wg.Wait(); Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, list.ToArray()); }
public void CloseSelecting() { var msgChan = new Chan<int>(); var closeChan = new Chan<bool>(); Func<Task> select = async () => { var run = true; while (run) { await new Select() .Case(msgChan, (_, ok) => {}) .Case(closeChan, (_, ok) => { run = false; }) .End(); } }; var t = select(); msgChan.Close(); closeChan.Send(true).ContinueWith(_ => t.Wait()).Wait(); }
public void Forward() { var source = new Chan<int>(); var target = new Chan<int>(); var tasks = new Task[2]; tasks[0] = source.Forward(target); source .Send(Enumerable.Range(0, 10)) .ContinueWith(t => source.Close()); var cnt = 0; tasks[1] = target.ForEach(item => cnt++); if (!Task.WaitAll(tasks, TimeSpan.FromSeconds(10))) { Assert.Fail(); } }
public void MultipleNumberGenerators() { var c = new Chan<int>(); for (int i = 0; i < 10; i++) { int localNum = i; var t = new Thread(() => c.Send(localNum)); t.IsBackground = true; t.Start(); } var list = new List<int>(); for (int i = 0; i < 10; i++) { list.Add(c.Receive()); } list.Sort(); Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, list); }
public void ClosedChannelsWithDataShouldNotReportClosedUntilDrained() { for (int i = 0; i < 10000; i++) { var chan = new Chan<int>(); var wait = new AutoResetEvent(initialState: false); GoFunc.Run(() => { chan.Send(1); chan.Close(); }, "send"); bool ok = false, ok2 = false; int actual = -1, actual2 = -1; GoFunc.Run(() => { actual = chan.ReceiveOk(out ok); actual2 = chan.ReceiveOk(out ok2); wait.Set(); }, "receive"); wait.WaitOne(); Assert.AreEqual(true, ok, string.Format("ok iteration {0}", i)); Assert.AreEqual(1, actual, string.Format("actual iteration {0}", i)); Assert.AreEqual(false, ok2, string.Format("ok2 iteration {0}", i)); Assert.AreEqual(default(int), actual2, string.Format("actual2 iteration {0}", i)); } }
public void TestTickerLoopWithNemesisChan() { var start = DateTime.Now; var ticker = new Ticker(TimeSpan.FromSeconds(1)); var listOfTimes = new List<TimeSpan>(); var exitChan = new Chan<bool>(); var lookupdRecheckChan = new Chan<bool>(); bool doLoop = true; using (var select = Select .CaseReceive(ticker.C, o => { Console.WriteLine("Received tick"); listOfTimes.Add(DateTime.Now - start); if (listOfTimes.Count == 5) { GoFunc.Run(() => lookupdRecheckChan.Send(true), "lookupd recheck sender"); } }) .CaseReceive(lookupdRecheckChan, o => { Console.WriteLine("Nemesis"); Thread.Sleep(5000); }) .CaseReceive(exitChan, o => doLoop = false) .NoDefault(defer: true)) { // ReSharper disable once LoopVariableIsNeverChangedInsideLoop while (doLoop) { select.Execute(); if (listOfTimes.Count >= 10) { GoFunc.Run(() => exitChan.Send(true), "exit notifier"); } } } ticker.Stop(); var duration = DateTime.Now - start; Console.WriteLine(duration); Assert.AreEqual(10, listOfTimes.Count, "listOfTimes.Count"); Assert.GreaterOrEqual(duration, TimeSpan.FromSeconds(14), "duration"); Assert.Less(duration, TimeSpan.FromSeconds(17)); }
/// <summary> /// Creates a channel which fires after the specified timeout. /// </summary> public static Chan<bool> After(TimeSpan timeout) { if (timeout < TimeSpan.Zero) throw new ArgumentOutOfRangeException("timeout", timeout, "timeout must be >= 0"); var timeoutChan = new Chan<bool>(); var started = DateTime.Now; System.Threading.Timer localTimer = null; System.Threading.Timer t = new System.Threading.Timer( delegate { string threadName = string.Format("Time.After started:{0} duration:{1}", started, timeout); Thread.CurrentThread.Name = threadName; try { if (localTimer != null) { lock (_threadingTimersLocker) { _threadingTimers.Remove(localTimer); localTimer.Dispose(); localTimer = null; } } } catch { } try { if (!((IChan)timeoutChan).IsClosed) timeoutChan.Send(default(bool)); } catch { } }, null, timeout, TimeSpan.FromMilliseconds(-1)); localTimer = t; lock (_threadingTimersLocker) { if (localTimer != null) { _threadingTimers.Add(localTimer); } } return timeoutChan; }
private void BenchmarkTcp(int parallel) { string topicName = "test_benchmark_" + DateTime.Now.UnixNano(); try { const int benchmarkNum = 30000; byte[] body = new byte[512]; var p = new Producer("127.0.0.1:4150"); p.Connect(); var startCh = new Chan<bool>(); var wg = new WaitGroup(); for (int j = 0; j < parallel; j++) { wg.Add(1); //int localj = j; GoFunc.Run(() => { startCh.Receive(); for (int i = 0; i < benchmarkNum / parallel; i++) { //if (i%10 == 0) //{ // Debug.WriteLine(string.Format("{0}: {1}/{2}", localj, i, benchmarkNum/parallel)); //} p.Publish(topicName, body); } wg.Done(); }, "ProducerBenchmarkTcpTest: sendLoop"); } var stopwatch = Stopwatch.StartNew(); startCh.Close(); var done = new Chan<bool>(); GoFunc.Run(() => { wg.Wait(); done.Send(true); }); bool finished = false; Select .CaseReceive(done, b => finished = b) .CaseReceive(Time.After(TimeSpan.FromSeconds(10)), b => finished = false) .NoDefault(); stopwatch.Stop(); if (!finished) { Assert.Fail("timeout"); } Console.WriteLine(string.Format("{0:#,0} sent in {1:mm\\:ss\\.fff}; Avg: {2:#,0} msgs/s; Threads: {3}", benchmarkNum, stopwatch.Elapsed, benchmarkNum / stopwatch.Elapsed.TotalSeconds, parallel)); } finally { _nsqdHttpClient.DeleteTopic(topicName); _nsqLookupdHttpClient.DeleteTopic(topicName); } }
public void SelectSendAndReceiveSendReady() { var c1 = new Chan<int>(); var c2 = new Chan<int>(); var t1 = new Thread(() => c1.Send(1)); t1.IsBackground = true; var list = new List<int>(); var t2 = new Thread(() => { Thread.Sleep(50); list.Add(c2.Receive()); }); t2.IsBackground = true; t1.Start(); t2.Start(); Select .CaseReceive(c1, list.Add) .CaseSend(c2, 2, () => { }) .NoDefault(); Assert.AreEqual(1, list.Count, "list.Count"); Assert.AreEqual(1, list[0], "list[0]"); }
public void SelectNullChannel() { var c1 = new Chan<int>(); var t1 = new Thread(() => { Thread.Sleep(10); c1.Send(3); }); t1.IsBackground = true; var list = new List<int>(); t1.Start(); Select .CaseReceive((Chan<int>)null, list.Add) .CaseReceive(c1, list.Add) .NoDefault(); Assert.AreEqual(1, list.Count, "list.Count"); Assert.AreEqual(3, list[0], "list[0]"); }
public void SendOnClosedChannelThrows() { var c = new Chan<int>(); c.Close(); Assert.Throws<ChannelClosedException>(() => c.Send(1)); }
public void Spread() { var chan1 = new Chan<int>(); var chan2 = new Chan<int>(); var chan3 = new Chan<int>(); var source = new Chan<int>(); var tasks = new Task[4]; tasks[0] = source.Spread(new[] { chan1, chan2, chan3 }); source .Send(Enumerable.Range(0, 10)) .ContinueWith(t => source.Close()); var cnt1 = 0; tasks[1] = chan1.ForEach(item => cnt1++); var cnt2 = 0; tasks[2] = chan2.ForEach(item => cnt2++); var cnt3 = 0; tasks[3] = chan3.ForEach(item => cnt3++); if (!Task.WaitAll(tasks, TimeSpan.FromSeconds(10))) { Assert.Fail(); } Assert.AreEqual(30, cnt1 + cnt2 + cnt3); }
public void SendReceive() { var chan = new Chan<int>(); chan .Send(Enumerable.Range(0, 10)) .ContinueWith(t => chan.Close()); var cnt = 0; var collection = chan.ForEach(item => cnt++); if (!collection.Wait(TimeSpan.FromSeconds(10))) { Assert.Fail(); } Assert.AreEqual(10, cnt); }
public void SelectNotEmpty() { var closeChan = new Chan<bool>(); closeChan.Send(true).Wait(); Func<Task> select = async () => { var run = true; while (run) { await new Select() .Case(closeChan, (_, ok) => { run = false; }) .End(); } }; select().Wait(); }
public void Select() { var chan = new Chan<int>(); chan .Send(Enumerable.Range(0, 10)) .ContinueWith(t => chan.Close()); var sum = 0; var collection = chan .Select(item => item % 2) .ForEach(item => sum += item); if (!collection.Wait(TimeSpan.FromSeconds(10))) { Assert.Fail(); } Assert.AreEqual(5, sum); }
public void Purge() { var chan = new Chan<int>(); chan .Send(Enumerable.Range(0, 10)) .ContinueWith(t => chan.Close()); if (!chan.Purge().Wait(TimeSpan.FromSeconds(10))) { Assert.Fail(); } }
private void handle(TcpClient conn, EndPoint remoteEndPoint) { int idx = 0; Console.WriteLine("[{0}] TCP: new client({1})", DateTime.Now.Formatted(), remoteEndPoint); using (var rdr = new BinaryReader(conn.GetStream())) using (var connw = new BinaryWriter(conn.GetStream())) { rdr.ReadBytes(4); var readChan = new Chan<byte[]>(); var readDoneChan = new Chan<int>(); var scriptTime = Time.After(script[0].delay); GoFunc.Run(() => { while (true) { try { var line = ReadBytes(rdr, (byte)'\n'); // trim the '\n' line = line.Take(line.Length - 1).ToArray(); readChan.Send(line); readDoneChan.Receive(); } catch { return; } } }, "mockNSQD:ReadBytes"); int rdyCount = 0; bool doLoop = true; while (doLoop && idx < script.Length) { Select .CaseReceive(readChan, line => { string strLine = Encoding.UTF8.GetString(line); Console.WriteLine("[{0}] mock: '{1}'", DateTime.Now.Formatted(), strLine); got.Add(line); gotTime.Add(DateTime.Now); var args = strLine.Split(' '); switch (args[0]) { case "IDENTIFY": try { byte[] l = rdr.ReadBytes(4); int size = Binary.BigEndian.Int32(l); byte[] b = rdr.ReadBytes(size); Console.WriteLine(string.Format("[{0}] {1}", DateTime.Now.Formatted(), Encoding.UTF8.GetString(b))); } catch (Exception ex) { Console.WriteLine(ex.ToString()); doLoop = false; throw; } break; case "RDY": int rdy = int.Parse(args[1]); rdyCount = rdy; break; } readDoneChan.Send(1); }) .CaseReceive(scriptTime, o => { bool doWrite = true; var inst = script[idx]; if (inst.body.SequenceEqual(Encoding.UTF8.GetBytes("exit"))) { doLoop = false; doWrite = false; } if (inst.frameType == (int)FrameType.Message) { if (rdyCount == 0) { Console.WriteLine("[{0}] !!! RDY == 0", DateTime.Now.Formatted()); scriptTime = Time.After(script[idx + 1].delay); doWrite = false; } else { rdyCount--; } } if (doWrite) { try { connw.Write(framedResponse(inst.frameType, inst.body)); scriptTime = Time.After(script[idx + 1].delay); idx++; } catch (Exception ex) { Console.WriteLine(ex.ToString()); doLoop = false; } } }) .NoDefault(); } } tcpListener.Stop(); conn.Close(); }
public void TestTickerLoopWithNemesisBufferedChan() { var start = DateTime.Now; var ticker = new Ticker(TimeSpan.FromSeconds(1)); int x = 0; var listOfTimes = new List <TimeSpan>(); var exitChan = new Chan <bool>(); var lookupdRecheckChan = new Chan <bool>(bufferSize: 1); bool doLoop = true; using (var select = Select .CaseReceive(ticker.C, o => { Console.WriteLine("Received tick"); listOfTimes.Add(DateTime.Now - start); if (listOfTimes.Count == 5) { Select .CaseSend(lookupdRecheckChan, true) .NoDefault(defer: false); } }) .CaseReceive(lookupdRecheckChan, o => { Console.WriteLine("Nemesis"); for (int i = 0; i < 5; i++) { Thread.Sleep(1000); Console.Write("."); } Console.WriteLine(); }) .CaseReceive(exitChan, o => doLoop = false) .NoDefault(defer: true)) { // ReSharper disable once LoopVariableIsNeverChangedInsideLoop while (doLoop) { Console.WriteLine("start {0}", x); if (x == 7) { Console.WriteLine("pause"); } select.Execute(); Console.WriteLine("finish {0}", x); x++; if (listOfTimes.Count >= 10) { GoFunc.Run(() => exitChan.Send(true), "exit notifier"); } } } ticker.Stop(); var duration = DateTime.Now - start; Console.WriteLine(duration); Assert.AreEqual(10, listOfTimes.Count, "listOfTimes.Count"); Assert.GreaterOrEqual(duration, TimeSpan.FromSeconds(14), "duration"); Assert.Less(duration, TimeSpan.FromSeconds(17)); }
public void SelectDefaultCaseChannelReady() { var c1 = new Chan<int>(); var c2 = new Chan<int>(); var t1 = new Thread(() => { Thread.Sleep(100); c1.Send(1); }); t1.IsBackground = true; var t2 = new Thread(() => c2.Send(5)); t2.IsBackground = true; var list = new List<int>(); t1.Start(); t2.Start(); Thread.Sleep(50); Select .CaseReceive(c1, list.Add) .CaseReceive(c2, list.Add) .Default(() => list.Add(3)); Assert.AreEqual(1, list.Count, "list.Count"); Assert.AreEqual(5, list[0], "list[0]"); }
private void handle(TcpClient conn, EndPoint remoteEndPoint) { int idx = 0; Console.WriteLine("[{0}] TCP: new client({1})", DateTime.Now.Formatted(), remoteEndPoint); using (var rdr = new BinaryReader(conn.GetStream())) using (var connw = new BinaryWriter(conn.GetStream())) { rdr.ReadBytes(4); var readChan = new Chan <byte[]>(); var readDoneChan = new Chan <int>(); var scriptTime = Time.After(script[0].delay); GoFunc.Run(() => { while (true) { try { var line = ReadBytes(rdr, (byte)'\n'); // trim the '\n' line = line.Take(line.Length - 1).ToArray(); readChan.Send(line); readDoneChan.Receive(); } catch { return; } } }, "mockNSQD:ReadBytes"); int rdyCount = 0; bool doLoop = true; while (doLoop && idx < script.Length) { Select .CaseReceive(readChan, line => { string strLine = Encoding.UTF8.GetString(line); Console.WriteLine("[{0}] mock: '{1}'", DateTime.Now.Formatted(), strLine); got.Add(line); gotTime.Add(DateTime.Now); var args = strLine.Split(' '); switch (args[0]) { case "IDENTIFY": try { byte[] l = rdr.ReadBytes(4); int size = Binary.BigEndian.Int32(l); byte[] b = rdr.ReadBytes(size); Console.WriteLine(string.Format("[{0}] {1}", DateTime.Now.Formatted(), Encoding.UTF8.GetString(b))); } catch (Exception ex) { Console.WriteLine(ex.ToString()); doLoop = false; throw; } break; case "RDY": int rdy = int.Parse(args[1]); rdyCount = rdy; break; } readDoneChan.Send(1); }) .CaseReceive(scriptTime, o => { bool doWrite = true; var inst = script[idx]; if (inst.body.SequenceEqual(Encoding.UTF8.GetBytes("exit"))) { doLoop = false; doWrite = false; } if (inst.frameType == (int)FrameType.Message) { if (rdyCount == 0) { Console.WriteLine("[{0}] !!! RDY == 0", DateTime.Now.Formatted()); scriptTime = Time.After(script[idx + 1].delay); doWrite = false; } else { rdyCount--; } } if (doWrite) { try { connw.Write(framedResponse(inst.frameType, inst.body)); scriptTime = Time.After(script[idx + 1].delay); idx++; } catch (Exception ex) { Console.WriteLine(ex.ToString()); doLoop = false; } } }) .NoDefault(); } } tcpListener.Stop(); conn.Close(); }
public void SelectSendAndReceiveReceiveReady() { object listLocker = new object(); var c1 = new Chan<int>(); var c2 = new Chan<int>(); var t1 = new Thread(() => { Thread.Sleep(150); c1.Send(1); }); t1.IsBackground = true; var list = new List<int>(); var t2 = new Thread(() => { var val = c2.Receive(); lock (listLocker) { list.Add(val); } }); t2.IsBackground = true; t1.Start(); t2.Start(); Select .CaseReceive(c1, func: o => { lock (listLocker) { list.Add(o); } }) .CaseSend(c2, message: 2) .NoDefault(); Thread.Sleep(20); lock (listLocker) { Assert.AreEqual(1, list.Count, "list.Count"); Assert.AreEqual(2, list[0], "list[0]"); } }
public void Merge() { var chan1 = new Chan<int>(); var chan2 = new Chan<int>(); chan1 .Send(Enumerable.Range(0, 10)) .ContinueWith(t => chan1.Close()); chan2 .Send(Enumerable.Range(0, 10)) .ContinueWith(t => chan2.Close()); var mergedChan = chan1.Merge(chan2); var cnt = 0; var collection = mergedChan.ForEach(item => cnt++); if (!collection.Wait(TimeSpan.FromSeconds(10))) { Assert.Fail(); } Assert.AreEqual(20, cnt); }
public void SelectTwoChannels() { var c1 = new Chan<int>(); var c2 = new Chan<int>(); var t1 = new Thread(() => { Thread.Sleep(10); c1.Send(1); }); t1.IsBackground = true; var t2 = new Thread(() => c2.Send(2)); t2.IsBackground = true; var list = new List<int>(); t2.Start(); t1.Start(); Select .CaseReceive(c1, list.Add) .CaseReceive(c2, list.Add) .NoDefault(); Assert.AreEqual(1, list.Count, "list.Count"); Assert.AreEqual(2, list[0], "list[0]"); }
public void AfterFired() { var c1 = Time.After(TimeSpan.FromMilliseconds(10)); var c2 = new Chan<string>(); var t1 = new Thread(() => { Thread.Sleep(200); c2.Send("no-timeout"); }); t1.IsBackground = true; t1.Start(); var list = new List<string>(); Select .CaseReceive(c1, o => list.Add("timeout")) .CaseReceive(c2, list.Add) .NoDefault(); Assert.AreEqual(1, list.Count, "list.Count"); Assert.AreEqual("timeout", list[0], "list[0]"); }
public void SingleNumberGeneratorIEnumerableChan() { var c = new Chan<int>(); var t = new Thread(() => { for (int i = 0; i < 10; i++) { c.Send(i); } c.Close(); }); t.IsBackground = true; t.Start(); var list = new List<int>(); foreach (var i in (IEnumerable)c) { list.Add((int)i); } Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, list); }
private static async void WaitAndSend(TimeSpan delay, Chan<DateTime> chan) { await Task.Delay(delay); await chan.Send(DateTime.Now); chan.Close(); }