digitalmars.D.learn - Problem with send / receive
- crimaniak (192/192) Mar 03 2017 Hi all!
Hi all! I make vibe-d based project and now I have problem passing messages between threads. First some words about architecture. Each event in the system has a corresponding class that validates and performs the required actions. Each class has a nested structure with the parameters that are required for this event. Like this: ``` module vcm.bll.event.deleteSite; import vcm.bll.basicEvent; class DeleteSite : BasicEvent { import vcm.bll.model.types : Id; struct Params { Id siteId; } mixin EventConstructor; override bool canDo() { import std.conv : to; return errorList .addIf(!engine.sites.contains(params.siteId), "SiteModel with id "~params.siteId.to!string~" is not found") .isEmpty(); } override EventResult doIt() { engine.db.execute("DELETE FROM sites WHERE id=?", params.siteId); return EventResult(true,[],0); } } ``` I have Engine class object which resides in own thread and listen message queue for messages with event parameters. After receiving message corresponding handler is executed, and message with EventResult object sent back to caller thread (Task). For every event type there is HTTP request handler, who make EventType.Params structure, send it to engine Task, then do receiveOnly!EventResult and take actions according to it. The only proble with this approach was a lot of boilerplate in engine receive() call because of big amout of event types. I resolve it by this way (is this possible without string mixin?): ``` private static string getReceiver(EventTypes...)() pure { import std.traits; string eventHandlers; foreach(EventType; EventTypes) eventHandlers ~= `,(`~EventType.stringof~`.Params params, Task caller, Id userId){ auto event = scoped!`~EventType.stringof~`(userId, params); event.setEngine(this); caller.send(event.execute()); }`; return `receive ((ExitMessage _){ exitFlag = true; } ,(LogMessage entry){ logger.log(entry.message); } ` ~eventHandlers ~");"; } private void run() { import vibe.core.concurrency : receive, send; import std.typecons: scoped; import vcm.bll.event; bool exitFlag = false; while(!exitFlag) mixin(getReceiver!AllEvents); } ``` After adding another event I ran into a problem: ``` Task terminated with unhandled exception: Range violation core.exception.RangeError source/vcm/bll/idContainer.d(44): Range violation ---------------- ... vcm.bll.event.deleteSite.DeleteSite.canDo() [0xd8dd5a] source/vcm/bll/basicEvent.d:182 bool vcm.bll.basicEvent.BasicEvent.check() [0xd2f8bc] source/vcm/bll/basicEvent.d:197 vcm.bll.basicEvent.EventResult vcm.bll.basicEvent.BasicEvent.execute() [0xd2f9a5] source/vcm/bll/engine.d-mixin-173:198 _D3vcm3bll6engine6Engine3runMFZ9__lambda8MFS3vcm3bll5event10deleteSite10DeleteSite6ParamsS4vi e4core4task4TaskmZv [0xd34375] /usr/include/dmd/phobos/std/concurrency.d:168 void std.concurrency.Message.map!(void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, vibe.core.task.Task, ulong)).map(void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, vibe.core.task.Task, ulong)) [0xc7df3d] /usr/include/dmd/phobos/std/concurrency.d:1956 _D3std11concurrency10MessageBox1467__T3getTDFNaNbNiNfS3vcm3bll7commons11ExitMessageZvTDFS3vcm3bll6engine10LogMessageZvTDFS3vcm3bll5event9addDevice9AddDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event9addClient9AddClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addRole7AddRole6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addUser7AddUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addSite7AddSite6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteSite10DeleteSite6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event13adminEditUser13AdminEditUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event14changePassword14ChangePassword6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event12deleteDevice12DeleteDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteRole10DeleteRole6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteUser10DeleteUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10editDevice10EditDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event5login5Login6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event8register8Register6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event11adminLogout11AdminLogout6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event15adminEditClient15AdminEditClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event9importMdb9ImportMdb6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event12deleteClient12DeleteClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event18managerIncludeUser18ManagerIncludeUser6ParamsS4vibe4core /usr/include/dmd/phobos/std/concurrency.d:2037 _D3std11concurrency10MessageBox1467__T3getTDFNaNbNiNfS3vcm3bll7commons11ExitMessageZvTDFS3vcm3bll6engine10LogMessageZvTDFS3vcm3bll5event9addDevice9AddDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event9addClient9AddClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addRole7AddRole6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addUser7AddUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event7addSite7AddSite6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteSite10DeleteSite6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event13adminEditUser13AdminEditUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event14changePassword14ChangePassword6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event12deleteDevice12DeleteDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteRole10DeleteRole6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10deleteUser10DeleteUser6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event10editDevice10EditDevice6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event5login5Login6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event8register8Register6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event11adminLogout11AdminLogout6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event15adminEditClient15AdminEditClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event9importMdb9ImportMdb6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event12deleteClient12DeleteClient6ParamsS4vibe4core4task4TaskmZvTDFS3vcm3bll5event18managerIncludeUser18ManagerIncludeUser6ParamsS4vibe4core /usr/include/dmd/phobos/std/concurrency.d:2115 bool std.concurrency.MessageBox.get!(pure nothrow nogc safe void delegate(vcm.bll.commons.ExitMessage), void delegate(vcm.bll.engine.LogMessage), void delegate(vcm.bll.event.addDevice.AddDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addClient.AddClient.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addRole.AddRole.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addUser.AddUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addSite.AddSite.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminEditUser.AdminEditUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.changePassword.ChangePassword.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteDevice.DeleteDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteRole.DeleteRole.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteUser.DeleteUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.editDevice.EditDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.login.Login.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.register.Register.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminLogout.AdminLogout.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminEditClient.AdminEd /usr/include/dmd/phobos/std/concurrency.d:700 void std.concurrency.receive!(pure nothrow nogc safe void delegate(vcm.bll.commons.ExitMessage), void delegate(vcm.bll.engine.LogMessage), void delegate(vcm.bll.event.addDevice.AddDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addClient.AddClient.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addRole.AddRole.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addUser.AddUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.addSite.AddSite.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminEditUser.AdminEditUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.changePassword.ChangePassword.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteDevice.DeleteDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteRole.DeleteRole.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.deleteUser.DeleteUser.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.editDevice.EditDevice.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.login.Login.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.register.Register.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminLogout.AdminLogout.Params, vibe.core.task.Task, ulong), void delegate(vcm.bll.event.adminEditClient.AdminEditClient source/vcm/bll/engine.d:172 void vcm.bll.engine.Engine.run() [0xd33c66] ../../.dub/packages/vibe-d-0.7.30/vibe-d/source/vibe/core/core.d:592 void vibe.core.core.makeTaskFuncInfo!(void delegate()).makeTaskFuncInfo(ref void delegate()).callDelegate(vibe.core.core.TaskFuncInfo*) [0xc2b8fc] ../../.dub/packages/vibe-d-0.7.30/vibe-d/source/vibe/core/core.d:1221 void vibe.core.core.CoreTask.run() [0xf2ecc6] ??:? void core.thread.Fiber.run() [0x103f65f] ??:? fiber_entryPoint [0x103f3c2] ??:? [0xffffffff] core.exception.InvalidMemoryOperationError src/core/exception.d(693): Invalid memory operation ---------------- ``` The problem here - not the exception itself, but the fact that the stack consists a call to void delegate(vcm.bll.event.deleteSite.DeleteSite.Params, ...) because I am quite sure that the parameter passed is ManagerIncludeUser.Params. I see very long symbols in the stack trace. Is this possible I hit some restriction on the length of the symbol or the number of delegates in receive() and it leads to broken mapping?
Mar 03 2017