{"action":"closed","issue":{"url":"https://api.github.com/repos/O-Log-N/Autom.cpp/issues/19","repository_url":"https://api.github.com/repos/O-Log-N/Autom.cpp","labels_url":"https://api.github.com/repos/O-Log-N/Autom.cpp/issues/19/labels{/name}","comments_url":"https://api.github.com/repos/O-Log-N/Autom.cpp/issues/19/comments","events_url":"https://api.github.com/repos/O-Log-N/Autom.cpp/issues/19/events","html_url":"https://github.com/O-Log-N/Autom.cpp/issues/19","id":146820452,"number":19,"title":"Support for chained Future::then()?","user":{"login":"nobugs-hare","id":10727344,"avatar_url":"https://avatars.githubusercontent.com/u/10727344?v=3","gravatar_id":"","url":"https://api.github.com/users/nobugs-hare","html_url":"https://github.com/nobugs-hare","followers_url":"https://api.github.com/users/nobugs-hare/followers","following_url":"https://api.github.com/users/nobugs-hare/following{/other_user}","gists_url":"https://api.github.com/users/nobugs-hare/gists{/gist_id}","starred_url":"https://api.github.com/users/nobugs-hare/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nobugs-hare/subscriptions","organizations_url":"https://api.github.com/users/nobugs-hare/orgs","repos_url":"https://api.github.com/users/nobugs-hare/repos","events_url":"https://api.github.com/users/nobugs-hare/events{/privacy}","received_events_url":"https://api.github.com/users/nobugs-hare/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/O-Log-N/Autom.cpp/labels/priority","name":"priority","color":"d93f0b"},{"url":"https://api.github.com/repos/O-Log-N/Autom.cpp/labels/question","name":"question","color":"cc317c"}],"state":"closed","locked":false,"assignee":{"login":"dl-dl","id":17916933,"avatar_url":"https://avatars.githubusercontent.com/u/17916933?v=3","gravatar_id":"","url":"https://api.github.com/users/dl-dl","html_url":"https://github.com/dl-dl","followers_url":"https://api.github.com/users/dl-dl/followers","following_url":"https://api.github.com/users/dl-dl/following{/other_user}","gists_url":"https://api.github.com/users/dl-dl/gists{/gist_id}","starred_url":"https://api.github.com/users/dl-dl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dl-dl/subscriptions","organizations_url":"https://api.github.com/users/dl-dl/orgs","repos_url":"https://api.github.com/users/dl-dl/repos","events_url":"https://api.github.com/users/dl-dl/events{/privacy}","received_events_url":"https://api.github.com/users/dl-dl/received_events","type":"User","site_admin":false},"milestone":null,"comments":3,"created_at":"2016-04-08T05:48:04Z","updated_at":"2016-04-09T06:34:53Z","closed_at":"2016-04-09T06:34:53Z","body":"For reference: equivalent blocking code would look as follows:\r\n```\r\n    void run() override {\r\n        std::string fname( \"path1\" );\r\n        Buffer data = FS::readFile( this, fname.c_str() );\r\n        infraConsole.log( \"READ1: file {}---{}\", fname.c_str(), data.value().toString() );\r\n        Buffer data2 = FS::readFile( this, \"path2\" );\r\n        infraConsole.log( \"READ2: {} : {}\", data.value().toString(), data2.value().toString() );\r\n        Buffer data3 = FS::readFile( this, \"path3\" );\r\n        infraConsole.log( \"READ3: {} : {}\", data.value().toString(), data3.value().toString() );\r\n        }\r\n```\r\n\r\nCurrently the sample code (equivalent to blocking one above) goes as follows:\r\n```\r\n    void run() override {\r\n        std::string fname( \"path1\" );\r\n        Future< Buffer > data = FS::readFile( this, fname.c_str() );\r\n        data.then( [ = ]() {\r\n            infraConsole.log( \"READ1: file {}---{}\", fname.c_str(), data.value().toString() );\r\n            Future< Buffer > data2 = FS::readFile( this, \"path2\" );\r\n            data2.then( [ = ]() {\r\n                infraConsole.log( \"READ2: {} : {}\", data.value().toString(), data2.value().toString() );\r\n                Future< Buffer > data3 = FS::readFile( this, \"path3\" );\r\n                data3.then( [ = ]() {\r\n                    infraConsole.log( \"READ3: {} : {}\", data.value().toString(), data3.value().toString() );\r\n                } );\r\n            } );\r\n        } );\r\n    }\r\n```\r\nThis is ok (well, better than \"callback hell\"), but is too reminiscent of \"lambda pyramid\" (and the main problem is that the code is not exactly linear). Guys here: https://code.facebook.com/posts/1661982097368498/futures-for-c-11-at-facebook/ describe an alternative way of doing the same thing with futures. For our case, it would look as follows:\r\n```\r\n    void run() override {\r\n        std::string fname( \"path1\" );\r\n        Future< Buffer > data = FS::readFile( this, fname.c_str() );\r\n        Future<Buffer> data2(this);//not completely initialised (yet); DOES have a corresponding InfraFuture, but does NOT wait for anything\r\n        Future<Buffer> data3(this);//see comment above\r\n        data.then( [ = ]() {\r\n            infraConsole.log( \"READ1: file {}---{}\", fname.c_str(), data.value().toString() );\r\n            data2 = FS::readFile( this, \"path2\" );\r\n            })\r\n         .then(data2, [=](){\r\n            infraConsole.log( \"READ2: {} : {}\", data.value().toString(), data2.value().toString() );\r\n            data3 = FS::readFile( this, \"path3\" );\r\n         })\r\n         .then(data3, [=](){\r\n            infraConsole.log( \"READ3: {} : {}\", data.value().toString(), data3.value().toString() );\r\n         });\r\n    }\r\n```\r\nQuestion 1: do we want to support it (IN ADDITION to existing \"ladder\" style)? (IMHO yes: the code does IMHO read better - it is just more linear this way)\r\nQuestion 2: can we support it? IMHO yes. Our concept of Futures doesn't change, and we DO know what we're waiting for at the each of then() points. Also I do NOT see a need to use something like `list<FutureFunction>` in InfraFutureBase: instead, we can add InfraFutureBase* InfraFutureBase::chainedFuture, and to start waiting for an event for chainedFuture after our current Future has finished processing; at this point we MUST check that chainedFuture already has something-to-wait-for (otherwise it is malformed program).\r\n\r\n@marcosbracco and @divanchykhin, PLEASE COMMENT ON QUESTION 1!"}}