Home | History | Annotate | Download | only in impl
      1 //
      2 // detail/impl/pipe_select_interrupter.ipp
      3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      4 //
      5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
      6 //
      7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
      8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      9 //
     10 
     11 #ifndef ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
     12 #define ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
     13 
     14 
     15 #include "asio/detail/config.hpp"
     16 
     17 
     18 #include <fcntl.h>
     19 #include <sys/stat.h>
     20 #include <sys/types.h>
     21 #include <unistd.h>
     22 #include "asio/detail/pipe_select_interrupter.hpp"
     23 #include "asio/detail/socket_types.hpp"
     24 #include "asio/detail/throw_error.hpp"
     25 #include "asio/error.hpp"
     26 
     27 #include "asio/detail/push_options.hpp"
     28 
     29 namespace asio {
     30 namespace detail {
     31 
     32 pipe_select_interrupter::pipe_select_interrupter()
     33 {
     34   open_descriptors();
     35 }
     36 
     37 void pipe_select_interrupter::open_descriptors()
     38 {
     39   int pipe_fds[2];
     40   if (pipe(pipe_fds) == 0)
     41   {
     42     read_descriptor_ = pipe_fds[0];
     43     ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
     44     write_descriptor_ = pipe_fds[1];
     45     ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
     46 
     47 #if defined(FD_CLOEXEC)
     48     ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
     49     ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC);
     50 #endif // defined(FD_CLOEXEC)
     51   }
     52   else
     53   {
     54     asio::error_code ec(errno,
     55         asio::error::get_system_category());
     56     asio::detail::throw_error(ec, "pipe_select_interrupter");
     57   }
     58 }
     59 
     60 pipe_select_interrupter::~pipe_select_interrupter()
     61 {
     62   close_descriptors();
     63 }
     64 
     65 void pipe_select_interrupter::close_descriptors()
     66 {
     67   if (read_descriptor_ != -1)
     68     ::close(read_descriptor_);
     69   if (write_descriptor_ != -1)
     70     ::close(write_descriptor_);
     71 }
     72 
     73 void pipe_select_interrupter::recreate()
     74 {
     75   close_descriptors();
     76 
     77   write_descriptor_ = -1;
     78   read_descriptor_ = -1;
     79 
     80   open_descriptors();
     81 }
     82 
     83 void pipe_select_interrupter::interrupt()
     84 {
     85   char byte = 0;
     86   signed_size_type result = ::write(write_descriptor_, &byte, 1);
     87   (void)result;
     88 }
     89 
     90 bool pipe_select_interrupter::reset()
     91 {
     92   for (;;)
     93   {
     94     char data[1024];
     95     signed_size_type bytes_read = ::read(read_descriptor_, data, sizeof(data));
     96     if (bytes_read < 0 && errno == EINTR)
     97       continue;
     98     bool was_interrupted = (bytes_read > 0);
     99     while (bytes_read == sizeof(data))
    100       bytes_read = ::read(read_descriptor_, data, sizeof(data));
    101     return was_interrupted;
    102   }
    103 }
    104 
    105 } // namespace detail
    106 } // namespace asio
    107 
    108 #include "asio/detail/pop_options.hpp"
    109 
    110 
    111 #endif // ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
    112