std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) { TORRENT_ASSERT(!m_read_handler); if (m_impl == 0) { ec = asio::error::not_connected; return 0; } if (read_buffer_size() == 0) { ec = asio::error::would_block; return 0; } #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS size_t buf_size = 0; #endif for (typename Mutable_Buffers::const_iterator i = buffers.begin() , end(buffers.end()); i != end; ++i) { using asio::buffer_cast; using asio::buffer_size; add_read_buffer(buffer_cast<void*>(*i), buffer_size(*i)); #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS buf_size += buffer_size(*i); #endif } std::size_t ret = read_some(true); TORRENT_ASSERT(ret <= buf_size); TORRENT_ASSERT(ret > 0); return ret; }
void async_write_some(Const_Buffers const& buffers, Handler const& handler) { if (m_impl == 0) { m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0)); return; } TORRENT_ASSERT(!m_write_handler); if (m_write_handler) { m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0)); return; } for (typename Const_Buffers::const_iterator i = buffers.begin() , end(buffers.end()); i != end; ++i) { TORRENT_ASSERT(buffer_size(*i) > 0); using asio::buffer_cast; using asio::buffer_size; add_write_buffer((void*)buffer_cast<void const*>(*i), buffer_size(*i)); } m_write_handler = handler; set_write_handler(&utp_stream::on_write); }
void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) { if (m_impl == 0) { m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0)); return; } TORRENT_ASSERT(!m_read_handler); if (m_read_handler) { m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0)); return; } int bytes_added = 0; for (typename Mutable_Buffers::const_iterator i = buffers.begin() , end(buffers.end()); i != end; ++i) { if (buffer_size(*i) == 0) continue; using asio::buffer_cast; using asio::buffer_size; add_read_buffer(buffer_cast<void*>(*i), buffer_size(*i)); bytes_added += buffer_size(*i); } if (bytes_added == 0) { // if we're reading 0 bytes, post handler immediately // asio's SSL layer depends on this behavior m_io_service.post(boost::bind<void>(handler, error_code(), 0)); return; } m_read_handler = handler; issue_read(); }
int main(int argc, char* argv[]) { try { if (argc < 2) { std::cerr << "Usage: parallel_grep <string> <files...>\n"; return 1; } // We use a fixed size pool of threads for reading the input files. The // number of threads is automatically determined based on the number of // CPUs available in the system. thread_pool pool; // To prevent the output from being garbled, we use a strand to synchronise // printing. strand<thread_pool::executor_type> output_strand(pool.get_executor()); // Spawn a new coroutine for each file specified on the command line. std::string search_string = argv[1]; for (int argn = 2; argn < argc; ++argn) { std::string input_file = argv[argn]; spawn(pool, [=](yield_context yield) { std::ifstream is(input_file.c_str()); std::string line; std::size_t line_num = 0; while (std::getline(is, line)) { // If we find a match, send a message to the output. if (line.find(search_string) != std::string::npos) { dispatch(output_strand, [=] { std::cout << input_file << ':' << line << std::endl; }); } // Every so often we yield control to another coroutine. if (++line_num % 10 == 0) post(yield); } }); } // Join the thread pool to wait for all the spawned tasks to complete. pool.join(); } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; }
inline void deallocate(void* p, std::size_t s, Handler& h) { #if !defined(ASIO_HAS_HANDLER_HOOKS) ::operator delete(p); #else using asio::asio_handler_deallocate; asio_handler_deallocate(p, s, asio::detail::addressof(h)); #endif }
inline void* allocate(std::size_t s, Handler& h) { #if !defined(ASIO_HAS_HANDLER_HOOKS) return ::operator new(s); #else using asio::asio_handler_allocate; return asio_handler_allocate(s, asio::detail::addressof(h)); #endif }
friend void send(Message msg, actor_address from, actor_address to) { // Execute the message handler in the context of the target's executor. post(to->executor_, [=, msg=std::move(msg)] { to->call_handler(std::move(msg), from); }); }
void tail_send(Message msg, actor_address to) { // Execute the message handler in the context of the target's executor. defer(to->executor_, [=, msg=std::move(msg), from=this] { to->call_handler(std::move(msg), from); }); }
inline void invoke(const Function& function, Context& context) { #if !defined(ASIO_HAS_HANDLER_HOOKS) Function tmp(function); tmp(); #else using asio::asio_handler_invoke; asio_handler_invoke(function, asio::detail::addressof(context)); #endif }
inline void deallocate(void* p, std::size_t s, Handler& h) { #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \ || BOOST_WORKAROUND(__GNUC__, < 3) ::operator delete(p); #else using asio::asio_handler_deallocate; asio_handler_deallocate(p, s, boost::addressof(h)); #endif }
inline void* allocate(std::size_t s, Handler& h) { #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \ || BOOST_WORKAROUND(__GNUC__, < 3) return ::operator new(s); #else using asio::asio_handler_allocate; return asio_handler_allocate(s, boost::addressof(h)); #endif }
void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) { if (m_impl == 0) { m_io_service.post(boost::bind<void>(handler, asio::error::not_connected, 0)); return; } LIBED2K_ASSERT(!m_read_handler); if (m_read_handler) { m_io_service.post(boost::bind<void>(handler, asio::error::operation_not_supported, 0)); return; } for (typename Mutable_Buffers::const_iterator i = buffers.begin(), end(buffers.end()); i != end; ++i) { LIBED2K_ASSERT(buffer_size(*i) > 0); using asio::buffer_cast; using asio::buffer_size; add_read_buffer(buffer_cast<void*>(*i), buffer_size(*i)); } m_read_handler = handler; set_read_handler(&utp_stream::on_read); }
void search_file(std::string search_string, std::string input_file, strand<thread_pool::executor_type> output_strand, yield_context yield) { std::ifstream is(input_file.c_str()); std::string line; std::size_t line_num = 0; while (std::getline(is, line)) { // If we find a match, send a message to the output. if (line.find(search_string) != std::string::npos) { dispatch(output_strand, boost::bind(&print_match, input_file, line)); } // Every so often we yield control to another coroutine. if (++line_num % 10 == 0) post(yield); } }
int main(int argc, char* argv[]) { try { if (argc < 2) { std::cerr << "Usage: parallel_grep <string> <files...>\n"; return 1; } // We use a fixed size pool of threads for reading the input files. The // number of threads is automatically determined based on the number of // CPUs available in the system. thread_pool pool; // To prevent the output from being garbled, we use a strand to synchronise // printing. strand<thread_pool::executor_type> output_strand(pool.get_executor()); // Spawn a new coroutine for each file specified on the command line. std::string search_string = argv[1]; for (int argn = 2; argn < argc; ++argn) { std::string input_file = argv[argn]; spawn(pool, boost::bind(&search_file, search_string, input_file, output_strand, _1)); } // Join the thread pool to wait for all the spawned tasks to complete. pool.join(); } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << "\n"; } return 0; }
receiver() : actor(system_executor()) { register_handler(&receiver::message_handler); }