diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,19 +9,19 @@ endif() set(CXX_FLAGS -g # -DVALGRIND - # -DMUDUO_STD_STRING + -DMUDUO_STD_STRING -D_FILE_OFFSET_BITS=64 -Wall -Wextra -Werror -Wconversion -Wno-unused-parameter - -Wold-style-cast + # -Wold-style-cast -Woverloaded-virtual -Wpointer-arith - -Wshadow + # -Wshadow -Wwrite-strings - -march=native + -march=nocona # -MMD # -std=c++0x -rdynamic @@ -31,7 +31,7 @@ if(CMAKE_BUILD_BITS EQUAL 32) endif() string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}") -set(CMAKE_CXX_COMPILER "g++") +set(CMAKE_CXX_COMPILER "g++4") #set(CMAKE_CXX_COMPILER "icpc") set(CMAKE_CXX_FLAGS_DEBUG "-O0") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -finline-limit=1000 -DNDEBUG") diff --git a/examples/idleconnection/CMakeLists.txt b/examples/idleconnection/CMakeLists.txt --- a/examples/idleconnection/CMakeLists.txt +++ b/examples/idleconnection/CMakeLists.txt @@ -1,4 +1,4 @@ -add_executable(idleconnection_echo echo.cc main.cc) +add_executable(idleconnection_echo EXCLUDE_FROM_ALL echo.cc main.cc) target_link_libraries(idleconnection_echo muduo_net) add_executable(idleconnection_echo2 sortedlist.cc) diff --git a/muduo/base/Timestamp.cc b/muduo/base/Timestamp.cc --- a/muduo/base/Timestamp.cc +++ b/muduo/base/Timestamp.cc @@ -4,7 +4,7 @@ #include #define __STDC_FORMAT_MACROS #include -#undef __STDC_FORMAT_MACROS +//#undef __STDC_FORMAT_MACROS #include diff --git a/muduo/base/tests/CMakeLists.txt b/muduo/base/tests/CMakeLists.txt --- a/muduo/base/tests/CMakeLists.txt +++ b/muduo/base/tests/CMakeLists.txt @@ -10,7 +10,7 @@ target_link_libraries(blockingqueue_test muduo_base) add_executable(blockingqueue_bench BlockingQueue_bench.cc) target_link_libraries(blockingqueue_bench muduo_base) -add_executable(boundedblockingqueue_test BoundedBlockingQueue_test.cc) +add_executable(boundedblockingqueue_test EXCLUDE_FROM_ALL BoundedBlockingQueue_test.cc) target_link_libraries(boundedblockingqueue_test muduo_base) add_executable(date_unittest Date_unittest.cc) diff --git a/muduo/net/Channel.cc b/muduo/net/Channel.cc --- a/muduo/net/Channel.cc +++ b/muduo/net/Channel.cc @@ -21,6 +21,10 @@ const int Channel::kNoneEvent = 0; const int Channel::kReadEvent = POLLIN | POLLPRI; const int Channel::kWriteEvent = POLLOUT; +#ifndef POLLRDHUP +#define POLLRDHUP 0x2000 +#endif + Channel::Channel(EventLoop* loop, int fd__) : loop_(loop), fd_(fd__), diff --git a/muduo/net/Endian.h b/muduo/net/Endian.h --- a/muduo/net/Endian.h +++ b/muduo/net/Endian.h @@ -13,6 +13,7 @@ #include #include +#include namespace muduo { @@ -23,48 +24,38 @@ namespace sockets // the inline assembler code makes type blur, // so we disable warnings for a while. -#if __GNUC_MINOR__ >= 6 -#pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wold-style-cast" +#if __BYTE_ORDER == __LITTLE_ENDIAN inline uint64_t hostToNetwork64(uint64_t host64) { - return htobe64(host64); + return bswap_64(host64); } inline uint32_t hostToNetwork32(uint32_t host32) { - return htobe32(host32); + return bswap_32(host32); } inline uint16_t hostToNetwork16(uint16_t host16) { - return htobe16(host16); + return bswap_16(host16); } inline uint64_t networkToHost64(uint64_t net64) { - return be64toh(net64); + return bswap_64(net64); } inline uint32_t networkToHost32(uint32_t net32) { - return be32toh(net32); + return bswap_32(net32); } inline uint16_t networkToHost16(uint16_t net16) { - return be16toh(net16); + return bswap_16(net16); } -#if __GNUC_MINOR__ >= 6 -#pragma GCC diagnostic pop -#else -#pragma GCC diagnostic error "-Wconversion" -#pragma GCC diagnostic error "-Wold-style-cast" #endif - } } } diff --git a/muduo/net/EventLoop.cc b/muduo/net/EventLoop.cc --- a/muduo/net/EventLoop.cc +++ b/muduo/net/EventLoop.cc @@ -18,7 +18,8 @@ #include #include -#include +#include +#include using namespace muduo; using namespace muduo::net; @@ -29,18 +30,6 @@ __thread EventLoop* t_loopInThisThread = 0; const int kPollTimeMs = 10000; -int createEventfd() -{ - int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - if (evtfd < 0) - { - LOG_SYSERR << "Failed in eventfd"; - abort(); - } - return evtfd; -} - -#pragma GCC diagnostic ignored "-Wold-style-cast" class IgnoreSigPipe { public: @@ -50,7 +39,6 @@ class IgnoreSigPipe LOG_TRACE << "Ignore SIGPIPE"; } }; -#pragma GCC diagnostic error "-Wold-style-cast" IgnoreSigPipe initObj; } @@ -69,11 +57,17 @@ EventLoop::EventLoop() threadId_(CurrentThread::tid()), poller_(Poller::newDefaultPoller(this)), timerQueue_(new TimerQueue(this)), - wakeupFd_(createEventfd()), - wakeupChannel_(new Channel(this, wakeupFd_)), currentActiveChannel_(NULL) { LOG_DEBUG << "EventLoop created " << this << " in thread " << threadId_; + if (::socketpair(AF_UNIX, SOCK_STREAM, 0, wakeupFd_) < 0) + { + LOG_SYSFATAL << "Failed in socketpair"; + } + sockets::setNonBlockAndCloseOnExec(wakeupFd_[0]); + sockets::setNonBlockAndCloseOnExec(wakeupFd_[1]); + wakeupChannel_.reset(new Channel(this, wakeupFd_[0])); + if (t_loopInThisThread) { LOG_FATAL << "Another EventLoop " << t_loopInThisThread @@ -93,7 +87,8 @@ EventLoop::~EventLoop() { LOG_DEBUG << "EventLoop " << this << " of thread " << threadId_ << " destructs in thread " << CurrentThread::tid(); - ::close(wakeupFd_); + ::close(wakeupFd_[0]); + ::close(wakeupFd_[1]); t_loopInThisThread = NULL; } @@ -108,12 +103,13 @@ void EventLoop::loop() while (!quit_) { activeChannels_.clear(); - pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_); + pollReturnTime_ = poller_->poll(timerQueue_->getTimeout(), &activeChannels_); ++iteration_; if (Logger::logLevel() <= Logger::TRACE) { printActiveChannels(); } + timerQueue_->processTimers(); // TODO sort channel by priority eventHandling_ = true; for (ChannelList::iterator it = activeChannels_.begin(); @@ -215,22 +211,19 @@ void EventLoop::abortNotInLoopThread() void EventLoop::wakeup() { - uint64_t one = 1; - ssize_t n = sockets::write(wakeupFd_, &one, sizeof one); + char one = '1'; + ssize_t n = sockets::write(wakeupFd_[1], &one, sizeof one); if (n != sizeof one) { - LOG_ERROR << "EventLoop::wakeup() writes " << n << " bytes instead of 8"; + LOG_ERROR << "EventLoop::wakeup() writes " << n << " bytes instead of 1"; } } void EventLoop::handleRead() { - uint64_t one = 1; - ssize_t n = sockets::read(wakeupFd_, &one, sizeof one); - if (n != sizeof one) - { - LOG_ERROR << "EventLoop::handleRead() reads " << n << " bytes instead of 8"; - } + char buf[4096] = { 0 }; + ssize_t n = sockets::read(wakeupFd_[0], buf, sizeof buf); + (void)n; } void EventLoop::doPendingFunctors() diff --git a/muduo/net/EventLoop.h b/muduo/net/EventLoop.h --- a/muduo/net/EventLoop.h +++ b/muduo/net/EventLoop.h @@ -130,7 +130,7 @@ class EventLoop : boost::noncopyable Timestamp pollReturnTime_; boost::scoped_ptr poller_; boost::scoped_ptr timerQueue_; - int wakeupFd_; + int wakeupFd_[2]; // unlike in TimerQueue, which is an internal class, // we don't expose Channel to client. boost::scoped_ptr wakeupChannel_; diff --git a/muduo/net/InetAddress.cc b/muduo/net/InetAddress.cc --- a/muduo/net/InetAddress.cc +++ b/muduo/net/InetAddress.cc @@ -17,9 +17,7 @@ #include // INADDR_ANY use (type)value casting. -#pragma GCC diagnostic ignored "-Wold-style-cast" static const in_addr_t kInaddrAny = INADDR_ANY; -#pragma GCC diagnostic error "-Wold-style-cast" // /* Structure describing an Internet socket address. */ // struct sockaddr_in { diff --git a/muduo/net/SocketsOps.cc b/muduo/net/SocketsOps.cc --- a/muduo/net/SocketsOps.cc +++ b/muduo/net/SocketsOps.cc @@ -37,7 +37,9 @@ SA* sockaddr_cast(struct sockaddr_in* addr) return static_cast(implicit_cast(addr)); } -void setNonBlockAndCloseOnExec(int sockfd) +} + +void sockets::setNonBlockAndCloseOnExec(int sockfd) { // non-block int flags = ::fcntl(sockfd, F_GETFL, 0); @@ -54,12 +56,9 @@ void setNonBlockAndCloseOnExec(int sockfd) (void)ret; } -} - int sockets::createNonblockingOrDie() { // socket -#if VALGRIND int sockfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockfd < 0) { @@ -67,13 +66,6 @@ int sockets::createNonblockingOrDie() } setNonBlockAndCloseOnExec(sockfd); -#else - int sockfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP); - if (sockfd < 0) - { - LOG_SYSFATAL << "sockets::createNonblockingOrDie"; - } -#endif return sockfd; } @@ -98,13 +90,8 @@ void sockets::listenOrDie(int sockfd) int sockets::accept(int sockfd, struct sockaddr_in* addr) { socklen_t addrlen = static_cast(sizeof *addr); -#if VALGRIND int connfd = ::accept(sockfd, sockaddr_cast(addr), &addrlen); setNonBlockAndCloseOnExec(connfd); -#else - int connfd = ::accept4(sockfd, sockaddr_cast(addr), - &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); -#endif if (connfd < 0) { int savedErrno = errno; diff --git a/muduo/net/SocketsOps.h b/muduo/net/SocketsOps.h --- a/muduo/net/SocketsOps.h +++ b/muduo/net/SocketsOps.h @@ -25,6 +25,8 @@ namespace sockets /// abort if any error. int createNonblockingOrDie(); +void setNonBlockAndCloseOnExec(int sockfd); + int connect(int sockfd, const struct sockaddr_in& addr); void bindOrDie(int sockfd, const struct sockaddr_in& addr); void listenOrDie(int sockfd); diff --git a/muduo/net/TimerQueue.cc b/muduo/net/TimerQueue.cc --- a/muduo/net/TimerQueue.cc +++ b/muduo/net/TimerQueue.cc @@ -16,8 +16,6 @@ #include -#include - namespace muduo { namespace net @@ -25,57 +23,15 @@ namespace net namespace detail { -int createTimerfd() -{ - int timerfd = ::timerfd_create(CLOCK_MONOTONIC, - TFD_NONBLOCK | TFD_CLOEXEC); - if (timerfd < 0) - { - LOG_SYSFATAL << "Failed in timerfd_create"; - } - return timerfd; -} - -struct timespec howMuchTimeFromNow(Timestamp when) +int howMuchTimeFromNow(Timestamp when) { int64_t microseconds = when.microSecondsSinceEpoch() - Timestamp::now().microSecondsSinceEpoch(); - if (microseconds < 100) - { - microseconds = 100; - } - struct timespec ts; - ts.tv_sec = static_cast( - microseconds / Timestamp::kMicroSecondsPerSecond); - ts.tv_nsec = static_cast( - (microseconds % Timestamp::kMicroSecondsPerSecond) * 1000); - return ts; -} - -void readTimerfd(int timerfd, Timestamp now) -{ - uint64_t howmany; - ssize_t n = ::read(timerfd, &howmany, sizeof howmany); - LOG_TRACE << "TimerQueue::handleRead() " << howmany << " at " << now.toString(); - if (n != sizeof howmany) - { - LOG_ERROR << "TimerQueue::handleRead() reads " << n << " bytes instead of 8"; - } -} - -void resetTimerfd(int timerfd, Timestamp expiration) -{ - // wake up loop by timerfd_settime() - struct itimerspec newValue; - struct itimerspec oldValue; - bzero(&newValue, sizeof newValue); - bzero(&oldValue, sizeof oldValue); - newValue.it_value = howMuchTimeFromNow(expiration); - int ret = ::timerfd_settime(timerfd, 0, &newValue, &oldValue); - if (ret) + if (microseconds < 1000) { - LOG_SYSERR << "timerfd_settime()"; + microseconds = 1000; } + return static_cast(microseconds / 1000); } } @@ -88,20 +44,13 @@ using namespace muduo::net::detail; TimerQueue::TimerQueue(EventLoop* loop) : loop_(loop), - timerfd_(createTimerfd()), - timerfdChannel_(loop, timerfd_), timers_(), callingExpiredTimers_(false) { - timerfdChannel_.setReadCallback( - boost::bind(&TimerQueue::handleRead, this)); - // we are always reading the timerfd, we disarm it with timerfd_settime. - timerfdChannel_.enableReading(); } TimerQueue::~TimerQueue() { - ::close(timerfd_); // do not remove channel, since we're in EventLoop::dtor(); for (TimerList::iterator it = timers_.begin(); it != timers_.end(); ++it) @@ -129,11 +78,19 @@ void TimerQueue::cancel(TimerId timerId) void TimerQueue::addTimerInLoop(Timer* timer) { loop_->assertInLoopThread(); - bool earliestChanged = insert(timer); + insert(timer); +} - if (earliestChanged) +int TimerQueue::getTimeout() const +{ + loop_->assertInLoopThread(); + if (timers_.empty()) + { + return 10000; + } + else { - resetTimerfd(timerfd_, timer->expiration()); + return howMuchTimeFromNow(timers_.begin()->second->expiration()); } } @@ -157,11 +114,10 @@ void TimerQueue::cancelInLoop(TimerId timerId) assert(timers_.size() == activeTimers_.size()); } -void TimerQueue::handleRead() +void TimerQueue::processTimers() { loop_->assertInLoopThread(); Timestamp now(Timestamp::now()); - readTimerfd(timerfd_, now); std::vector expired = getExpired(now); @@ -225,11 +181,6 @@ void TimerQueue::reset(const std::vector& expired, Timestamp now) { nextExpire = timers_.begin()->second->expiration(); } - - if (nextExpire.valid()) - { - resetTimerfd(timerfd_, nextExpire); - } } bool TimerQueue::insert(Timer* timer) diff --git a/muduo/net/TimerQueue.h b/muduo/net/TimerQueue.h --- a/muduo/net/TimerQueue.h +++ b/muduo/net/TimerQueue.h @@ -51,6 +51,9 @@ class TimerQueue : boost::noncopyable void cancel(TimerId timerId); + int getTimeout() const; + void processTimers(); + private: // FIXME: use unique_ptr instead of raw pointers. @@ -61,8 +64,6 @@ class TimerQueue : boost::noncopyable void addTimerInLoop(Timer* timer); void cancelInLoop(TimerId timerId); - // called when timerfd alarms - void handleRead(); // move out all expired timers std::vector getExpired(Timestamp now); void reset(const std::vector& expired, Timestamp now); @@ -70,9 +71,6 @@ class TimerQueue : boost::noncopyable bool insert(Timer* timer); EventLoop* loop_; - const int timerfd_; - Channel timerfdChannel_; - // Timer list sorted by expiration TimerList timers_; // for cancel() diff --git a/muduo/net/poller/EPollPoller.cc b/muduo/net/poller/EPollPoller.cc --- a/muduo/net/poller/EPollPoller.cc +++ b/muduo/net/poller/EPollPoller.cc @@ -26,7 +26,6 @@ using namespace muduo::net; BOOST_STATIC_ASSERT(EPOLLIN == POLLIN); BOOST_STATIC_ASSERT(EPOLLPRI == POLLPRI); BOOST_STATIC_ASSERT(EPOLLOUT == POLLOUT); -BOOST_STATIC_ASSERT(EPOLLRDHUP == POLLRDHUP); BOOST_STATIC_ASSERT(EPOLLERR == POLLERR); BOOST_STATIC_ASSERT(EPOLLHUP == POLLHUP); @@ -39,7 +38,7 @@ const int kDeleted = 2; EPollPoller::EPollPoller(EventLoop* loop) : Poller(loop), - epollfd_(::epoll_create1(EPOLL_CLOEXEC)), + epollfd_(::epoll_create(32)), events_(kInitEventListSize) { if (epollfd_ < 0)