Re: [asio-users] Emulating non-blocking file-IO with asio
Brought to you by:
chris_kohlhoff
From: Thomas I. <tho...@tu...> - 2019-01-24 19:10:17
|
Using two io_services sounds good. I did some more reading and put together an example based on some asio examples: template <class Handler> void async_read(const std::string& filename, Handler handler) { auto& strand = get_strand(filename); // Create executor_work for the handler's associated executor. auto work = asio::make_work_guard(handler); // Post a function object to do the work asynchronously. asio::post(strand, [this, filename, work, handler = std::move(handler)]() mutable { log("start heavy work on " + filename); std::this_thread::sleep_for(std::chrono::seconds(5)); log("finished heavy work on " + filename); std::string result = "after long consideration, here are the contents of " + filename; // Pass the result to the handler, via the associated executor. dispatch(work.get_executor(), [result = std::move(result), handler = std::move(handler)]() mutable { handler(std::move(result)); }); }); } asio::strand<asio::thread_pool::executor_type>& get_strand(const std::string& id) { std::lock_guard<std::mutex> guard(strand_lock_); auto it = strands_.try_emplace(id, pool_.get_executor()); return it.first->second; } std::mutex strand_lock_; std::map<std::string, asio::strand<asio::thread_pool::executor_type>> strands_; asio::thread_pool pool_; Calling it elsewhere like file_service_.async_read( filename, asio::bind_executor(strand_, [this, self](const std::string& result) { send(result); })); Full example https://gist.github.com/tilsche/74f4e5532fecf5e92542af96848c7b7d It appears to work and as far as I can tell code is running on the right threads. Nevertheless I am unsure whether I correctly understood all the aspects. Is it correct, that it is necessary to bind the handler to the calling execution context? I would appreciate any feedback on this. Thanks, Thomas On 1/18/19 7:04 PM, Matt Gruenke wrote: > First, you don't want to dispatch blocking operations, since dispatching one handler from another will directly execute (and therefore block) the former. > > Second, you can add a strand per file, but: > 1. That only increases concurrency if you've also got more threads. > 2. I thought your original use of strands was to keep a thread free to respond to incoming messages. > > You could increase the concurrency of your file operations, if you maintain fewer file strands than the total number of worker threads. Of course, you'll also want to ensure that all operations on a given file are funneled through the same strand. So, a better approach might be to have two io_services - one for messages and one for file I/O. Then, in the file I/O service, you can have as many strands as you like. > > > Matt > > > -----Original Message----- > From: Thomas Ilsche [mailto:tho...@tu...] > Sent: Friday, January 18, 2019 12:13 > To: asi...@li... > Subject: [asio-users] Emulating non-blocking file-IO with asio > > I am writing a service with asio that needs to do file-IO, including opening files, to answer certain messages. The protocol (AMQP /w TSL) is full-duplex and requires regular heartbeats. The files may be on network filesystems and it may be many. So there are cases where doing too much file-IO causes the service to miss heartbeats. > > Most unfortunately there seems to be no way to do non-blocking file-IO on Linux, especially opening files. So my idea is > > run an io_context with concurrency_hint == 2 do all general protocol (never blocking) stuff in one strand encapsulate all blocking file-IO and post it to one other strand. > > My hope is then that there can never be more than one file-io function blocking the io_context so that there is always a thread free to handle the rest. > > Is this a good idea? There doesn't seem to be much of a guarantee, particularly given that it is only a concurrency_*hint*. Does it make a difference whether i post/dispatch? > > Are there any, more idiomatic, alternatives? > > How could I exploit more parallelism for the file-IO when I could create an arbitrary number of strands - basically one per file? > > Thanks, > Thomas > > > _______________________________________________ > asio-users mailing list > asi...@li... > https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.sourceforge.net%2Flists%2Flistinfo%2Fasio-users&data=02%7C01%7Cmatthew.gruenke%40jci.com%7C213c25b5064246ac342508d67d685a0f%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636834284493534876&sdata=ZEaGEnemlO2JP0j1wuIS2A3L2iGgUGr9hl%2BPjJ8as%2F4%3D&reserved=0 > _______________________________________________ > Using Asio? List your project at > https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fthink-async.com%2FAsio%2FWhoIsUsingAsio&data=02%7C01%7Cmatthew.gruenke%40jci.com%7C213c25b5064246ac342508d67d685a0f%7Ca1f1e2147ded45b681a19e8ae3459641%7C0%7C0%7C636834284493534876&sdata=1ESJ5M9k2UQ%2F4CtwLOaZZllvJlPBbe12x4c8CF6BIqE%3D&reserved=0 > > > _______________________________________________ > asio-users mailing list > asi...@li... > https://lists.sourceforge.net/lists/listinfo/asio-users > _______________________________________________ > Using Asio? List your project at > http://think-async.com/Asio/WhoIsUsingAsio > |