public void Start() { if (_running) { throw new InvalidOperationException("Instance is already running."); } _running = true; _cancelSource = new CancellationTokenSource(); var cancel = _cancelSource.Token; _chainThread = new Thread(() => ChainController.Loop(cancel)) { Name = "ChainController", IsBackground = true }; _coinThreads = new Thread[CoinControllers.Length]; for (var i = 0; i < CoinControllers.Length; i++) { var coinController = CoinControllers[i]; _coinThreads[i] = new Thread(() => coinController.Loop(cancel)) { Name = $"CoinController[{i}]", IsBackground = true }; } _dispatchThread = new Thread(() => DispatchController.Loop(cancel)) { Name = "DispatchController", IsBackground = true }; _listenerThread = new Thread(() => Listener.Loop(cancel)) { Name = "Listener", IsBackground = true }; _chainThread.Start(); foreach (var t in _coinThreads) { t.Start(); } _dispatchThread.Start(); _listenerThread.Start(); }
public void Stop() { _cancelSource.Cancel(); // Wake controllers to let them terminate. ChainController.Wake(); foreach (var c in CoinControllers) { c.Wake(); } DispatchController.Wake(); _chainThread.Join(); foreach (var t in _coinThreads) { t.Join(); } _dispatchThread.Join(); _listenerThread.Join(); _running = false; }
public void SetupControllers() { // == Setup inboxes == var dispatchInbox = new BoundedInbox(Constants.DispatchControllerOutboxSize); var coinInboxes = new BoundedInbox[CoinStores.Length]; for (var i = 0; i < coinInboxes.Length; i++) { coinInboxes[i] = new BoundedInbox(Constants.CoinControllerInboxSize); } var chainInbox = new BoundedInbox(Constants.ChainControllerInboxSize); // == Setup controllers == Listener = new Listener( dispatchInbox, IpAddress, Port, _log); // Zero port can be re-associated to an available port. Port = Listener.Port; DispatchController = new DispatchController( dispatchInbox, chainInbox, coinInboxes, OutpointHash, _log); CoinControllers = new CoinController[CoinStores.Length]; for (var i = 0; i < CoinControllers.Length; i++) { CoinControllers[i] = new CoinController( coinInboxes[i], dispatchInbox, CoinStores[i], OutpointHash, _log, shardIndex: i); } ChainController = new ChainController( ChainStore, chainInbox, dispatchInbox, lineage => { // Whenever 'OpenBlock' or 'CommitBlock' is requested, lineages get refreshed. foreach (var c in CoinControllers) { c.Lineage = lineage; } }, _log); // == Bind controllers == Listener.OnConnectionAccepted = conn => { DispatchController.AddConnection(conn); }; foreach (var cc in CoinControllers) { cc.OnRequestHandled = () => { DispatchController.Wake(); } } ; ChainController.OnRequestHandled = () => { DispatchController.Wake(); }; DispatchController.OnConnectionAccepted = conn => conn.Start(); DispatchController.OnBlockMessageDispatched = () => { ChainController.Wake(); }; for (var i = 0; i < CoinStores.Length; i++) { var coinController = CoinControllers[i]; DispatchController.OnCoinMessageDispatched[i] = () => { coinController.Wake(); }; } }