diff --git a/include/boost/asio/detail/dev_poll_reactor.hpp b/include/boost/asio/detail/dev_poll_reactor.hpp index 873e4359..e00f501b 100644 --- a/include/boost/asio/detail/dev_poll_reactor.hpp +++ b/include/boost/asio/detail/dev_poll_reactor.hpp @@ -126,18 +126,20 @@ public: if (allow_speculative) { - if (!op_queue_[op_type].has_operation(descriptor)) + if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor)) { - if (op->perform()) + if (!op_queue_[op_type].has_operation(descriptor)) { - lock.unlock(); - io_service_.post_immediate_completion(op); - return; + if (op->perform()) + { + lock.unlock(); + io_service_.post_immediate_completion(op); + return; + } } } } - bool first = op_queue_[op_type].enqueue_operation(descriptor, op); io_service_.work_started(); if (first) diff --git a/include/boost/asio/detail/epoll_reactor.hpp b/include/boost/asio/detail/epoll_reactor.hpp index b07de7cc..46849448 100644 --- a/include/boost/asio/detail/epoll_reactor.hpp +++ b/include/boost/asio/detail/epoll_reactor.hpp @@ -180,7 +180,9 @@ public: if (descriptor_data->op_queue_[op_type].empty()) { - if (allow_speculative) + if (allow_speculative + && (op_type != read_op + || descriptor_data->op_queue_[except_op].empty())) { if (op->perform()) { diff --git a/include/boost/asio/detail/event.hpp b/include/boost/asio/detail/event.hpp index 89f9896a..e8d185fe 100644 --- a/include/boost/asio/detail/event.hpp +++ b/include/boost/asio/detail/event.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) # include #elif defined(BOOST_WINDOWS) # include @@ -35,7 +35,7 @@ namespace boost { namespace asio { namespace detail { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) typedef null_event event; #elif defined(BOOST_WINDOWS) typedef win_event event; diff --git a/include/boost/asio/detail/fenced_block.hpp b/include/boost/asio/detail/fenced_block.hpp index f43097c4..a0b14481 100644 --- a/include/boost/asio/detail/fenced_block.hpp +++ b/include/boost/asio/detail/fenced_block.hpp @@ -21,18 +21,20 @@ #include #include -#if 1//!defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) # include #elif defined(__MACH__) && defined(__APPLE__) # include #elif defined(__sun) # include #elif defined(__GNUC__) \ - && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ + && !defined(__ICC) && !defined(__ECC) # include #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) # include -#elif defined(BOOST_WINDOWS) +#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) # include #else # include @@ -42,18 +44,20 @@ namespace boost { namespace asio { namespace detail { -#if 1//!defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) typedef null_fenced_block fenced_block; #elif defined(__MACH__) && defined(__APPLE__) typedef macos_fenced_block fenced_block; #elif defined(__sun) typedef solaris_fenced_block fenced_block; #elif defined(__GNUC__) \ - && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ + && !defined(__ICC) && !defined(__ECC) typedef gcc_fenced_block fenced_block; #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) typedef gcc_x86_fenced_block fenced_block; -#elif defined(BOOST_WINDOWS) +#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE) typedef win_fenced_block fenced_block; #else typedef null_fenced_block fenced_block; diff --git a/include/boost/asio/detail/gcc_fenced_block.hpp b/include/boost/asio/detail/gcc_fenced_block.hpp index 6b58ee89..6c5edc8d 100644 --- a/include/boost/asio/detail/gcc_fenced_block.hpp +++ b/include/boost/asio/detail/gcc_fenced_block.hpp @@ -22,7 +22,9 @@ #include #if defined(__GNUC__) \ - && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ + && !defined(__ICC) && !defined(__ECC) namespace boost { namespace asio { @@ -55,6 +57,8 @@ private: #endif // defined(__GNUC__) // && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) + // && !defined(__INTEL_COMPILER) && !defined(__ICL) + // && !defined(__ICC) && !defined(__ECC) #include diff --git a/include/boost/asio/detail/kqueue_reactor.hpp b/include/boost/asio/detail/kqueue_reactor.hpp index 9b8599ba..c1a67058 100644 --- a/include/boost/asio/detail/kqueue_reactor.hpp +++ b/include/boost/asio/detail/kqueue_reactor.hpp @@ -34,10 +34,10 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -59,15 +59,24 @@ class kqueue_reactor : public boost::asio::detail::service_base { public: - enum { read_op = 0, write_op = 1, + enum op_types { read_op = 0, write_op = 1, connect_op = 1, except_op = 2, max_ops = 3 }; - // Per-descriptor data. - struct per_descriptor_data + // Per-descriptor queues. + struct descriptor_state { - bool allow_speculative[max_ops]; + descriptor_state() {} + descriptor_state(const descriptor_state&) {} + void operator=(const descriptor_state&) {} + + mutex mutex_; + op_queue op_queue_[max_ops]; + bool shutdown_; }; + // Per-descriptor data. + typedef descriptor_state* per_descriptor_data; + // Constructor. kqueue_reactor(boost::asio::io_service& io_service) : boost::asio::detail::service_base(io_service), @@ -75,34 +84,38 @@ public: mutex_(), kqueue_fd_(do_kqueue_create()), interrupter_(), - shutdown_(false), - need_kqueue_wait_(true) + shutdown_(false) { - // Add the interrupter's descriptor to the kqueue. - struct kevent event; - EV_SET(&event, interrupter_.read_descriptor(), - EVFILT_READ, EV_ADD, 0, 0, 0); - ::kevent(kqueue_fd_, &event, 1, 0, 0, 0); + // The interrupter is put into a permanently readable state. Whenever we + // want to interrupt the blocked kevent call we register a one-shot read + // operation against the descriptor. + interrupter_.interrupt(); } // Destructor. ~kqueue_reactor() { - shutdown_service(); close(kqueue_fd_); } // Destroy all user-defined handler objects owned by the service. void shutdown_service() { - boost::asio::detail::mutex::scoped_lock lock(mutex_); + mutex::scoped_lock lock(mutex_); shutdown_ = true; lock.unlock(); op_queue ops; - for (int i = 0; i < max_ops; ++i) - op_queue_[i].get_all_operations(ops); + descriptor_map::iterator iter = registered_descriptors_.begin(); + descriptor_map::iterator end = registered_descriptors_.end(); + while (iter != end) + { + for (int i = 0; i < max_ops; ++i) + ops.push(iter->second.op_queue_[i]); + iter->second.shutdown_ = true; + ++iter; + } timer_queues_.get_all_timers(ops); } @@ -115,11 +128,16 @@ public: // Register a socket with the reactor. Returns 0 on success, system error // code on failure. - int register_descriptor(socket_type, per_descriptor_data& descriptor_data) + int register_descriptor(socket_type descriptor, + per_descriptor_data& descriptor_data) { - descriptor_data.allow_speculative[read_op] = true; - descriptor_data.allow_speculative[write_op] = true; - descriptor_data.allow_speculative[except_op] = true; + mutex::scoped_lock lock(registered_descriptors_mutex_); + + descriptor_map::iterator new_entry = registered_descriptors_.insert( + std::make_pair(descriptor, descriptor_state())).first; + descriptor_data = &new_entry->second; + + descriptor_data->shutdown_ = false; return 0; } @@ -130,66 +148,57 @@ public: per_descriptor_data& descriptor_data, reactor_op* op, bool allow_speculative) { - if (allow_speculative && descriptor_data.allow_speculative[op_type]) - { - if (op->perform()) - { - io_service_.post_immediate_completion(op); - return; - } - - // We only get one shot at a speculative read in this function. - allow_speculative = false; - } - - boost::asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + if (descriptor_data->shutdown_) return; - if (!allow_speculative) - need_kqueue_wait_ = true; - else if (!op_queue_[op_type].has_operation(descriptor)) + bool first = descriptor_data->op_queue_[op_type].empty(); + if (first) { - // Speculative reads are ok as there are no queued read operations. - descriptor_data.allow_speculative[op_type] = true; - - if (op->perform()) + if (allow_speculative) { - lock.unlock(); - io_service_.post_immediate_completion(op); - return; + if (op_type != read_op || descriptor_data->op_queue_[except_op].empty()) + { + if (op->perform()) + { + descriptor_lock.unlock(); + io_service_.post_immediate_completion(op); + return; + } + } } } - // Speculative reads are not ok as there will be queued read operations. - descriptor_data.allow_speculative[op_type] = false; - - bool first = op_queue_[op_type].enqueue_operation(descriptor, op); + descriptor_data->op_queue_[op_type].push(op); io_service_.work_started(); + if (first) { struct kevent event; switch (op_type) { case read_op: - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); + EV_SET(&event, descriptor, EVFILT_READ, + EV_ADD | EV_ONESHOT, 0, 0, descriptor_data); break; case write_op: - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); + EV_SET(&event, descriptor, EVFILT_WRITE, + EV_ADD | EV_ONESHOT, 0, 0, descriptor_data); break; case except_op: - if (op_queue_[read_op].has_operation(descriptor)) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, EV_OOBAND, 0, 0); + if (!descriptor_data->op_queue_[read_op].empty()) + return; // Already registered for read events. + EV_SET(&event, descriptor, EVFILT_READ, + EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data); break; } + if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) { - boost::system::error_code ec(errno, + op->ec_ = boost::system::error_code(errno, boost::asio::error::get_system_category()); - cancel_ops_unlocked(descriptor, ec); + descriptor_data->op_queue_[op_type].pop(); + io_service_.post_deferred_completion(op); } } } @@ -197,33 +206,63 @@ public: // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. - void cancel_ops(socket_type descriptor, per_descriptor_data&) + void cancel_ops(socket_type descriptor, per_descriptor_data& descriptor_data) { - boost::asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted); + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + op_queue ops; + for (int i = 0; i < max_ops; ++i) + { + while (reactor_op* op = descriptor_data->op_queue_[i].front()) + { + op->ec_ = boost::asio::error::operation_aborted; + descriptor_data->op_queue_[i].pop(); + ops.push(op); + } + } + + descriptor_lock.unlock(); + + io_service_.post_deferred_completions(ops); } // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. - void close_descriptor(socket_type descriptor, per_descriptor_data&) + void close_descriptor(socket_type descriptor, + per_descriptor_data& descriptor_data) { - boost::asio::detail::mutex::scoped_lock lock(mutex_); + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); - // Remove the descriptor from kqueue. - struct kevent event[2]; - EV_SET(&event[0], descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); - EV_SET(&event[1], descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - ::kevent(kqueue_fd_, event, 2, 0, 0, 0); - - // Cancel any outstanding operations associated with the descriptor. - cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted); + // Remove the descriptor from the set of known descriptors. The descriptor + // will be automatically removed from the kqueue set when it is closed. + descriptor_data->shutdown_ = true; + + op_queue ops; + for (int i = 0; i < max_ops; ++i) + { + while (reactor_op* op = descriptor_data->op_queue_[i].front()) + { + op->ec_ = boost::asio::error::operation_aborted; + descriptor_data->op_queue_[i].pop(); + ops.push(op); + } + } + + descriptor_lock.unlock(); + + registered_descriptors_.erase(descriptor); + + descriptors_lock.unlock(); + + io_service_.post_deferred_completions(ops); } // Add a new timer queue to the reactor. template void add_timer_queue(timer_queue& timer_queue) { - boost::asio::detail::mutex::scoped_lock lock(mutex_); + mutex::scoped_lock lock(mutex_); timer_queues_.insert(&timer_queue); } @@ -231,7 +270,7 @@ public: template void remove_timer_queue(timer_queue& timer_queue) { - boost::asio::detail::mutex::scoped_lock lock(mutex_); + mutex::scoped_lock lock(mutex_); timer_queues_.erase(&timer_queue); } @@ -241,13 +280,13 @@ public: void schedule_timer(timer_queue& timer_queue, const typename Time_Traits::time_type& time, timer_op* op, void* token) { - boost::asio::detail::mutex::scoped_lock lock(mutex_); + mutex::scoped_lock lock(mutex_); if (!shutdown_) { bool earliest = timer_queue.enqueue_timer(time, op, token); io_service_.work_started(); if (earliest) - interrupter_.interrupt(); + interrupt(); } } @@ -256,7 +295,7 @@ public: template std::size_t cancel_timer(timer_queue& timer_queue, void* token) { - boost::asio::detail::mutex::scoped_lock lock(mutex_); + mutex::scoped_lock lock(mutex_); op_queue ops; std::size_t n = timer_queue.cancel_timer(token, ops); lock.unlock(); @@ -267,13 +306,7 @@ public: // Run the kqueue loop. void run(bool block, op_queue& ops) { - boost::asio::detail::mutex::scoped_lock lock(mutex_); - - // We can return immediately if there's no work to do and the reactor is - // not supposed to block. - if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty() - && op_queue_[except_op].empty() && timer_queues_.all_empty()) - return; + mutex::scoped_lock lock(mutex_); // Determine how long to block while waiting for events. timespec timeout_buf = { 0, 0 }; @@ -283,103 +316,104 @@ public: // Block on the kqueue descriptor. struct kevent events[128]; - int num_events = (block || need_kqueue_wait_) - ? kevent(kqueue_fd_, 0, 0, events, 128, timeout) - : 0; - - lock.lock(); + int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout); // Dispatch the waiting events. for (int i = 0; i < num_events; ++i) { int descriptor = events[i].ident; - if (descriptor == interrupter_.read_descriptor()) + void* ptr = events[i].udata; + if (ptr == &interrupter_) { - interrupter_.reset(); + // No need to reset the interrupter since we're leaving the descriptor + // in a ready-to-read state and relying on one-shot notifications. } - else if (events[i].filter == EVFILT_READ) + else { - // Dispatch operations associated with the descriptor. - bool more_reads = false; - bool more_except = false; - if (events[i].flags & EV_ERROR) + descriptor_state* descriptor_data = static_cast(ptr); + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. + static const int filter[max_ops] = + { EVFILT_READ, EVFILT_WRITE, EVFILT_READ }; + for (int j = max_ops - 1; j >= 0; --j) { - boost::system::error_code error( - events[i].data, boost::asio::error::get_system_category()); - op_queue_[except_op].perform_operations(descriptor, ops); - op_queue_[read_op].perform_operations(descriptor, ops); + if (events[i].filter == filter[j]) + { + if (j != except_op || events[i].flags & EV_OOBAND) + { + while (reactor_op* op = descriptor_data->op_queue_[j].front()) + { + if (events[i].flags & EV_ERROR) + { + op->ec_ = boost::system::error_code(events[i].data, + boost::asio::error::get_system_category()); + descriptor_data->op_queue_[j].pop(); + ops.push(op); + } + if (op->perform()) + { + descriptor_data->op_queue_[j].pop(); + ops.push(op); + } + else + break; + } + } + } } - else if (events[i].flags & EV_OOBAND) + + // Renew registration for event notifications. + struct kevent event; + switch (events[i].filter) { - more_except - = op_queue_[except_op].perform_operations(descriptor, ops); - if (events[i].data > 0) - more_reads = op_queue_[read_op].perform_operations(descriptor, ops); + case EVFILT_READ: + if (!descriptor_data->op_queue_[read_op].empty()) + EV_SET(&event, descriptor, EVFILT_READ, + EV_ADD | EV_ONESHOT, 0, 0, descriptor_data); + else if (!descriptor_data->op_queue_[except_op].empty()) + EV_SET(&event, descriptor, EVFILT_READ, + EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data); else - more_reads = op_queue_[read_op].has_operation(descriptor); + continue; + case EVFILT_WRITE: + if (!descriptor_data->op_queue_[write_op].empty()) + EV_SET(&event, descriptor, EVFILT_WRITE, + EV_ADD | EV_ONESHOT, 0, 0, descriptor_data); + else + continue; + default: + break; } - else - { - more_reads = op_queue_[read_op].perform_operations(descriptor, ops); - more_except = op_queue_[except_op].has_operation(descriptor); - } - - // Update the descriptor in the kqueue. - struct kevent event; - if (more_reads) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else if (more_except) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) { boost::system::error_code error(errno, boost::asio::error::get_system_category()); - op_queue_[except_op].cancel_operations(descriptor, ops, error); - op_queue_[read_op].cancel_operations(descriptor, ops, error); - } - } - else if (events[i].filter == EVFILT_WRITE) - { - // Dispatch operations associated with the descriptor. - bool more_writes = false; - if (events[i].flags & EV_ERROR) - { - boost::system::error_code error( - events[i].data, boost::asio::error::get_system_category()); - op_queue_[write_op].cancel_operations(descriptor, ops, error); - } - else - { - more_writes = op_queue_[write_op].perform_operations(descriptor, ops); - } - - // Update the descriptor in the kqueue. - struct kevent event; - if (more_writes) - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - boost::system::error_code error(errno, - boost::asio::error::get_system_category()); - op_queue_[write_op].cancel_operations(descriptor, ops, error); + for (int j = 0; j < max_ops; ++j) + { + while (reactor_op* op = descriptor_data->op_queue_[j].front()) + { + op->ec_ = error; + descriptor_data->op_queue_[j].pop(); + ops.push(op); + } + } } } } - timer_queues_.get_ready_timers(ops); - // Determine whether kqueue needs to be called next time the reactor is run. - need_kqueue_wait_ = !op_queue_[read_op].empty() - || !op_queue_[write_op].empty() || !op_queue_[except_op].empty(); + lock.lock(); + timer_queues_.get_ready_timers(ops); } - // Interrupt the select loop. + // Interrupt the kqueue loop. void interrupt() { - interrupter_.interrupt(); + struct kevent event; + EV_SET(&event, interrupter_.read_descriptor(), + EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_); + ::kevent(kqueue_fd_, &event, 1, 0, 0, 0); } private: @@ -410,22 +444,11 @@ private: return &ts; } - // Cancel all operations associated with the given descriptor. This function - // does not acquire the kqueue_reactor's mutex. - void cancel_ops_unlocked(socket_type descriptor, - const boost::system::error_code& ec) - { - op_queue ops; - for (int i = 0; i < max_ops; ++i) - op_queue_[i].cancel_operations(descriptor, ops, ec); - io_service_.post_deferred_completions(ops); - } - // The io_service implementation used to post completions. io_service_impl& io_service_; // Mutex to protect access to internal data. - boost::asio::detail::mutex mutex_; + mutex mutex_; // The kqueue file descriptor. int kqueue_fd_; @@ -433,17 +456,24 @@ private: // The interrupter is used to break a blocking kevent call. select_interrupter interrupter_; - // The queues of read, write and except operations. - reactor_op_queue op_queue_[max_ops]; - // The timer queues. timer_queue_set timer_queues_; // Whether the service has been shut down. bool shutdown_; - // Whether we need to call kqueue the next time the reactor is run. - bool need_kqueue_wait_; + // Mutex to protect access to the registered descriptors. + mutex registered_descriptors_mutex_; + + // Keep track of all registered descriptors. This code relies on the fact that + // the hash_map implementation pools deleted nodes, meaning that we can assume + // our descriptor_state pointer remains valid even after the entry is removed. + // Technically this is not true for C++98, as that standard says that spliced + // elements in a list are invalidated. However, C++0x fixes this shortcoming + // so we'll just assume that C++98 std::list implementations will do the right + // thing anyway. + typedef detail::hash_map descriptor_map; + descriptor_map registered_descriptors_; }; } // namespace detail diff --git a/include/boost/asio/detail/mutex.hpp b/include/boost/asio/detail/mutex.hpp index fc7ed83c..e804ec25 100644 --- a/include/boost/asio/detail/mutex.hpp +++ b/include/boost/asio/detail/mutex.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) # include #elif defined(BOOST_WINDOWS) # include @@ -35,7 +35,7 @@ namespace boost { namespace asio { namespace detail { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) typedef null_mutex mutex; #elif defined(BOOST_WINDOWS) typedef win_mutex mutex; diff --git a/include/boost/asio/detail/null_event.hpp b/include/boost/asio/detail/null_event.hpp index e926d4e3..2dc0bf6d 100644 --- a/include/boost/asio/detail/null_event.hpp +++ b/include/boost/asio/detail/null_event.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include @@ -72,7 +72,7 @@ public: } // namespace asio } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include diff --git a/include/boost/asio/detail/null_mutex.hpp b/include/boost/asio/detail/null_mutex.hpp index bdf56179..edc13584 100644 --- a/include/boost/asio/detail/null_mutex.hpp +++ b/include/boost/asio/detail/null_mutex.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include #include @@ -61,7 +61,7 @@ public: } // namespace asio } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include diff --git a/include/boost/asio/detail/null_signal_blocker.hpp b/include/boost/asio/detail/null_signal_blocker.hpp index 7fe5c108..65b55e96 100644 --- a/include/boost/asio/detail/null_signal_blocker.hpp +++ b/include/boost/asio/detail/null_signal_blocker.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include @@ -58,7 +58,7 @@ public: } // namespace asio } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include diff --git a/include/boost/asio/detail/null_thread.hpp b/include/boost/asio/detail/null_thread.hpp index 0a508f34..ba163114 100644 --- a/include/boost/asio/detail/null_thread.hpp +++ b/include/boost/asio/detail/null_thread.hpp @@ -22,7 +22,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include #include @@ -63,7 +63,7 @@ public: } // namespace asio } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include diff --git a/include/boost/asio/detail/null_tss_ptr.hpp b/include/boost/asio/detail/null_tss_ptr.hpp index 7c35b151..bd83e7ee 100644 --- a/include/boost/asio/detail/null_tss_ptr.hpp +++ b/include/boost/asio/detail/null_tss_ptr.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include @@ -65,7 +65,7 @@ private: } // namespace asio } // namespace boost -#endif // !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) #include diff --git a/include/boost/asio/detail/reactive_socket_service.hpp b/include/boost/asio/detail/reactive_socket_service.hpp index 884ce759..5f7bbf5c 100644 --- a/include/boost/asio/detail/reactive_socket_service.hpp +++ b/include/boost/asio/detail/reactive_socket_service.hpp @@ -1070,7 +1070,7 @@ public: start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, - ptr.get(), true, + ptr.get(), (flags & socket_base::message_out_of_band) == 0, (impl.protocol_.type() == SOCK_STREAM && buffer_sequence_adapter::all_empty(buffers))); diff --git a/include/boost/asio/detail/signal_blocker.hpp b/include/boost/asio/detail/signal_blocker.hpp index db11fe4d..0197e04d 100644 --- a/include/boost/asio/detail/signal_blocker.hpp +++ b/include/boost/asio/detail/signal_blocker.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) # include #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) # include @@ -35,7 +35,7 @@ namespace boost { namespace asio { namespace detail { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) typedef null_signal_blocker signal_blocker; #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) typedef win_signal_blocker signal_blocker; diff --git a/include/boost/asio/detail/task_io_service.hpp b/include/boost/asio/detail/task_io_service.hpp index fe6af3ce..f6de3706 100644 --- a/include/boost/asio/detail/task_io_service.hpp +++ b/include/boost/asio/detail/task_io_service.hpp @@ -290,9 +290,7 @@ private: } task_has_run = true; - if (more_handlers) - wake_one_idle_thread_and_unlock(lock); - else + if (!more_handlers || !wake_one_idle_thread_and_unlock(lock)) lock.unlock(); op_queue completed_ops; diff --git a/include/boost/asio/detail/thread.hpp b/include/boost/asio/detail/thread.hpp index 24a7a8ca..3e2e2159 100644 --- a/include/boost/asio/detail/thread.hpp +++ b/include/boost/asio/detail/thread.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) # include #elif defined(BOOST_WINDOWS) # if defined(UNDER_CE) @@ -39,7 +39,7 @@ namespace boost { namespace asio { namespace detail { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) typedef null_thread thread; #elif defined(BOOST_WINDOWS) # if defined(UNDER_CE) diff --git a/include/boost/asio/detail/tss_ptr.hpp b/include/boost/asio/detail/tss_ptr.hpp index 9af4965a..7ccfcf32 100644 --- a/include/boost/asio/detail/tss_ptr.hpp +++ b/include/boost/asio/detail/tss_ptr.hpp @@ -21,7 +21,7 @@ #include #include -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) # include #elif defined(BOOST_WINDOWS) # include @@ -37,7 +37,7 @@ namespace detail { template class tss_ptr -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) : public null_tss_ptr #elif defined(BOOST_WINDOWS) : public win_tss_ptr @@ -48,7 +48,7 @@ class tss_ptr public: void operator=(T* value) { -#if !defined(BOOST_HAS_THREADS) +#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS) null_tss_ptr::operator=(value); #elif defined(BOOST_WINDOWS) win_tss_ptr::operator=(value); diff --git a/include/boost/asio/detail/win_fenced_block.hpp b/include/boost/asio/detail/win_fenced_block.hpp index 443b50c9..ff4a21cb 100644 --- a/include/boost/asio/detail/win_fenced_block.hpp +++ b/include/boost/asio/detail/win_fenced_block.hpp @@ -21,7 +21,7 @@ #include #include -#if defined(BOOST_WINDOWS) +#if defined(BOOST_WINDOWS) && !defined(UNDER_CE) #include @@ -36,13 +36,33 @@ public: // Constructor. win_fenced_block() { +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1400) +# if defined(_M_IX86) +# pragma warning(push) +# pragma warning(disable:4793) + LONG barrier; + __asm { xchg barrier, eax } +# pragma warning(pop) +# endif // defined(_M_IX86) +#else // defined(BOOST_MSVC) && (BOOST_MSVC < 1400) MemoryBarrier(); +#endif // defined(BOOST_MSVC) && (BOOST_MSVC < 1400) } // Destructor. ~win_fenced_block() { +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1400) +# if defined(_M_IX86) +# pragma warning(push) +# pragma warning(disable:4793) + LONG barrier; + __asm { xchg barrier, eax } +# pragma warning(pop) +# endif // defined(_M_IX86) +#else // defined(BOOST_MSVC) && (BOOST_MSVC < 1400) MemoryBarrier(); +#endif // defined(BOOST_MSVC) && (BOOST_MSVC < 1400) } }; @@ -50,7 +70,7 @@ public: } // namespace asio } // namespace boost -#endif // defined(BOOST_WINDOWS) +#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE) #include