Move event loops from trantor to core.

This commit is contained in:
Relintai 2022-02-10 01:24:36 +01:00
parent 6a29af9963
commit 9543341423
72 changed files with 1224 additions and 1236 deletions

View File

@ -7,6 +7,9 @@ env.core_sources = []
env.add_source_files(env.core_sources, "*.cpp")
env.add_source_files(env.core_sources, "./math/*.cpp")
env.add_source_files(env.core_sources, "./net/*.cpp")
env.add_source_files(env.core_sources, "./loops/*.cpp")
#todo move these to modules
env.add_source_files(env.core_sources, "./loops/poller/*.cpp")
env.add_source_files(env.core_sources, "./containers/*.cpp")
env.add_source_files(env.core_sources, "./log/*.cpp")
env.add_source_files(env.core_sources, "./os/*.cpp")

View File

@ -12,7 +12,7 @@
*
*/
#include "Acceptor.h"
#include "acceptor.h"
using namespace trantor;
#ifndef O_CLOEXEC

58
core/loops/acceptor.h Normal file
View File

@ -0,0 +1,58 @@
/**
*
* Acceptor.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "channel.h"
#include "core/net/inet_address.h"
#include "core/net/socket.h"
#include "event_loop.h"
#include <functional>
namespace trantor {
using NewConnectionCallback = std::function<void(int fd, const InetAddress &)>;
class Acceptor {
protected:
Acceptor(const Acceptor &) = delete;
Acceptor &operator=(const Acceptor &) = delete;
// some uncopyable classes maybe support move constructor....
Acceptor(Acceptor &&) noexcept(true) = default;
Acceptor &operator=(Acceptor &&) noexcept(true) = default;
public:
Acceptor(EventLoop *loop,
const InetAddress &addr,
bool reUseAddr = true,
bool reUsePort = true);
~Acceptor();
const InetAddress &addr() const {
return addr_;
}
void setNewConnectionCallback(const NewConnectionCallback &cb) {
newConnectionCallback_ = cb;
};
void listen();
protected:
#ifndef _WIN32
int idleFd_;
#endif
Socket sock_;
InetAddress addr_;
EventLoop *loop_;
NewConnectionCallback newConnectionCallback_;
Channel acceptChannel_;
void readCallback();
};
} // namespace trantor

View File

@ -12,8 +12,9 @@
*
*/
#include "Channel.h"
#include <trantor/net/EventLoop.h>
#include "channel.h"
#include "event_loop.h"
#ifdef _WIN32
#include "Wepoll.h"
#define POLLIN EPOLLIN

291
core/loops/channel.h Normal file
View File

@ -0,0 +1,291 @@
/**
*
* @file Channel.h
* @author An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "core/log/logger.h"
#include <assert.h>
#include <functional>
#include <memory>
namespace trantor {
class EventLoop;
/**
* @brief This class is used to implement reactor pattern. A Channel object
* manages a socket fd. Users use a Channel object to receive write or read
* events on the socket it manages.
*
*/
class Channel {
protected:
Channel(const Channel &) = delete;
Channel &operator=(const Channel &) = delete;
// some uncopyable classes maybe support move constructor....
Channel(Channel &&) noexcept(true) = default;
Channel &operator=(Channel &&) noexcept(true) = default;
public:
using EventCallback = std::function<void()>;
/**
* @brief Construct a new Channel instance.
*
* @param loop The event loop in which the channel works.
* @param fd The socket fd.
*/
Channel(EventLoop *loop, int fd);
/**
* @brief Set the read callback.
*
* @param cb The callback is called when read event occurs on the socket.
* @note One should call the enableReading() method to ensure that the
* callback would be called when some data is received on the socket.
*/
void setReadCallback(const EventCallback &cb) {
readCallback_ = cb;
};
void setReadCallback(EventCallback &&cb) {
readCallback_ = std::move(cb);
}
/**
* @brief Set the write callback.
*
* @param cb The callback is called when write event occurs on the socket.
* @note One should call the enableWriting() method to ensure that the
* callback would be called when the socket can be written.
*/
void setWriteCallback(const EventCallback &cb) {
writeCallback_ = cb;
};
void setWriteCallback(EventCallback &&cb) {
writeCallback_ = std::move(cb);
}
/**
* @brief Set the close callback.
*
* @param cb The callback is called when the socket is closed.
*/
void setCloseCallback(const EventCallback &cb) {
closeCallback_ = cb;
}
void setCloseCallback(EventCallback &&cb) {
closeCallback_ = std::move(cb);
}
/**
* @brief Set the error callback.
*
* @param cb The callback is called when an error occurs on the socket.
*/
void setErrorCallback(const EventCallback &cb) {
errorCallback_ = cb;
}
void setErrorCallback(EventCallback &&cb) {
errorCallback_ = std::move(cb);
}
/**
* @brief Set the event callback.
*
* @param cb The callback is called when any event occurs on the socket.
* @note If the event callback is set to the channel, any other callback
* wouldn't be called again.
*/
void setEventCallback(const EventCallback &cb) {
eventCallback_ = cb;
}
void setEventCallback(EventCallback &&cb) {
eventCallback_ = std::move(cb);
}
/**
* @brief Return the fd of the socket.
*
* @return int
*/
int fd() const {
return fd_;
}
/**
* @brief Return the events enabled on the socket.
*
* @return int
*/
int events() const {
return events_;
}
/**
* @brief Return the events that occurred on the socket.
*
* @return int
*/
int revents() const {
return revents_;
}
/**
* @brief Check whether there is no event enabled on the socket.
*
* @return true
* @return false
*/
bool isNoneEvent() const {
return events_ == kNoneEvent;
};
/**
* @brief Disable all events on the socket.
*
*/
void disableAll() {
events_ = kNoneEvent;
update();
}
/**
* @brief Remove the socket from the poller in the event loop.
*
*/
void remove();
/**
* @brief Return the event loop.
*
* @return EventLoop*
*/
EventLoop *ownerLoop() {
return loop_;
};
/**
* @brief Enable the read event on the socket.
*
*/
void enableReading() {
events_ |= kReadEvent;
update();
}
/**
* @brief Disable the read event on the socket.
*
*/
void disableReading() {
events_ &= ~kReadEvent;
update();
}
/**
* @brief Enable the write event on the socket.
*
*/
void enableWriting() {
events_ |= kWriteEvent;
update();
}
/**
* @brief Disable the write event on the socket.
*
*/
void disableWriting() {
events_ &= ~kWriteEvent;
update();
}
/**
* @brief Check whether the write event is enabled on the socket.
*
* @return true
* @return false
*/
bool isWriting() const {
return events_ & kWriteEvent;
}
/**
* @brief Check whether the read event is enabled on the socket.
*
* @return true
* @return false
*/
bool isReading() const {
return events_ & kReadEvent;
}
/**
* @brief Set and update the events enabled.
*
* @param events
*/
void updateEvents(int events) {
events_ = events;
update();
}
/**
* @brief This method is used to ensure that the callback owner is valid
* when a callback is called.
*
* @param obj The callback owner. Usually, the owner is also the owner of
* the channel.
* @note The 'obj' is kept in a weak_ptr object, so this method does not
* cause a circular reference problem.
*/
void tie(const std::shared_ptr<void> &obj) {
tie_ = obj;
tied_ = true;
}
static const int kNoneEvent;
static const int kReadEvent;
static const int kWriteEvent;
private:
friend class EventLoop;
friend class EpollPoller;
friend class KQueue;
void update();
void handleEvent();
void handleEventSafely();
int setRevents(int revt) {
// LOG_TRACE<<"revents="<<revt;
revents_ = revt;
return revt;
};
int index() {
return index_;
};
void setIndex(int index) {
index_ = index;
};
EventLoop *loop_;
const int fd_;
int events_;
int revents_;
int index_;
bool addedToLoop_{ false };
EventCallback readCallback_;
EventCallback writeCallback_;
EventCallback errorCallback_;
EventCallback closeCallback_;
EventCallback eventCallback_;
std::weak_ptr<void> tie_;
bool tied_;
};
} // namespace trantor

View File

@ -15,12 +15,13 @@
// Author: Tao An
#include <trantor/net/EventLoop.h>
#include "event_loop.h"
#include "core/log/logger.h"
#include "Channel.h"
#include "Poller.h"
#include "TimerQueue.h"
#include "channel.h"
#include "poller.h"
#include "timer_queue.h"
#include <assert.h>
#include <thread>

313
core/loops/event_loop.h Normal file
View File

@ -0,0 +1,313 @@
// Copyright 2010, Shuo Chen. All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Shuo Chen (chenshuo at chenshuo dot com)
// Taken from Muduo and modified
// Copyright 2016, Tao An. All rights reserved.
// https://github.com/an-tao/trantor
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Tao An
#pragma once
#include "core/containers/lock_free_queue.h"
#include "core/math/date.h"
#include <chrono>
#include <functional>
#include <limits>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
namespace trantor {
class Poller;
class TimerQueue;
class Channel;
using ChannelList = std::vector<Channel *>;
using Func = std::function<void()>;
using TimerId = uint64_t;
enum {
InvalidTimerId = 0
};
/**
* @brief As the name implies, this class represents an event loop that runs in
* a perticular thread. The event loop can handle network I/O events and timers
* in asynchronous mode.
* @note An event loop object always belongs to a separate thread, and there is
* one event loop object at most in a thread. We can call an event loop object
* the event loop of the thread it belongs to, or call that thread the thread of
* the event loop.
*/
class EventLoop {
protected:
EventLoop(const EventLoop &) = delete;
EventLoop &operator=(const EventLoop &) = delete;
// some uncopyable classes maybe support move constructor....
EventLoop(EventLoop &&) noexcept(true) = default;
EventLoop &operator=(EventLoop &&) noexcept(true) = default;
public:
EventLoop();
~EventLoop();
/**
* @brief Run the event loop. This method will be blocked until the event
* loop exits.
*
*/
void loop();
/**
* @brief Let the event loop quit.
*
*/
void quit();
/**
* @brief Assertion that the current thread is the thread to which the event
* loop belongs. If the assertion fails, the program aborts.
*/
void assertInLoopThread() {
if (!isInLoopThread()) {
abortNotInLoopThread();
}
};
#ifdef __linux__
/**
* @brief Make the timer queue works after calling the fork() function.
*
*/
void resetTimerQueue();
#endif
/**
* @brief Make the event loop works after calling the fork() function.
*
*/
void resetAfterFork();
/**
* @brief Return true if the current thread is the thread to which the event
* loop belongs.
*
* @return true
* @return false
*/
bool isInLoopThread() const {
return threadId_ == std::this_thread::get_id();
};
/**
* @brief Get the event loop of the current thread. Return nullptr if there
* is no event loop in the current thread.
*
* @return EventLoop*
*/
static EventLoop *getEventLoopOfCurrentThread();
/**
* @brief Run the function f in the thread of the event loop.
*
* @param f
* @note If the current thread is the thread of the event loop, the function
* f is executed directly before the method exiting.
*/
void runInLoop(const Func &f);
void runInLoop(Func &&f);
/**
* @brief Run the function f in the thread of the event loop.
*
* @param f
* @note The difference between this method and the runInLoop() method is
* that the function f is executed after the method exiting no matter if the
* current thread is the thread of the event loop.
*/
void queueInLoop(const Func &f);
void queueInLoop(Func &&f);
/**
* @brief Run a function at a time point.
*
* @param time The time to run the function.
* @param cb The function to run.
* @return TimerId The ID of the timer.
*/
TimerId runAt(const Date &time, const Func &cb);
TimerId runAt(const Date &time, Func &&cb);
/**
* @brief Run a function after a period of time.
*
* @param delay Represent the period of time in seconds.
* @param cb The function to run.
* @return TimerId The ID of the timer.
*/
TimerId runAfter(double delay, const Func &cb);
TimerId runAfter(double delay, Func &&cb);
/**
* @brief Run a function after a period of time.
* @note Users could use chrono literals to represent a time duration
* For example:
* @code
runAfter(5s, task);
runAfter(10min, task);
@endcode
*/
TimerId runAfter(const std::chrono::duration<double> &delay, const Func &cb) {
return runAfter(delay.count(), cb);
}
TimerId runAfter(const std::chrono::duration<double> &delay, Func &&cb) {
return runAfter(delay.count(), std::move(cb));
}
/**
* @brief Repeatedly run a function every period of time.
*
* @param interval The duration in seconds.
* @param cb The function to run.
* @return TimerId The ID of the timer.
*/
TimerId runEvery(double interval, const Func &cb);
TimerId runEvery(double interval, Func &&cb);
/**
* @brief Repeatedly run a function every period of time.
* Users could use chrono literals to represent a time duration
* For example:
* @code
runEvery(5s, task);
runEvery(10min, task);
runEvery(0.1h, task);
@endcode
*/
TimerId runEvery(const std::chrono::duration<double> &interval,
const Func &cb) {
return runEvery(interval.count(), cb);
}
TimerId runEvery(const std::chrono::duration<double> &interval, Func &&cb) {
return runEvery(interval.count(), std::move(cb));
}
/**
* @brief Invalidate the timer identified by the given ID.
*
* @param id The ID of the timer.
*/
void invalidateTimer(TimerId id);
/**
* @brief Move the EventLoop to the current thread, this method must be
* called before the loop is running.
*
*/
void moveToCurrentThread();
/**
* @brief Update channel status. This method is usually used internally.
*
* @param chl
*/
void updateChannel(Channel *chl);
/**
* @brief Remove a channel from the event loop. This method is usually used
* internally.
*
* @param chl
*/
void removeChannel(Channel *chl);
/**
* @brief Return the index of the event loop.
*
* @return size_t
*/
size_t index() {
return index_;
}
/**
* @brief Set the index of the event loop.
*
* @param index
*/
void setIndex(size_t index) {
index_ = index;
}
/**
* @brief Return true if the event loop is running.
*
* @return true
* @return false
*/
bool isRunning() {
return looping_ && (!quit_);
}
/**
* @brief Check if the event loop is calling a function.
*
* @return true
* @return false
*/
bool isCallingFunctions() {
return callingFuncs_;
}
/**
* @brief Run functions when the event loop quits
*
* @param cb the function to run
* @note the function runs on the thread that quits the EventLoop
*/
void runOnQuit(Func &&cb);
void runOnQuit(const Func &cb);
private:
void abortNotInLoopThread();
void wakeup();
void wakeupRead();
bool looping_;
std::thread::id threadId_;
bool quit_;
std::unique_ptr<Poller> poller_;
ChannelList activeChannels_;
Channel *currentActiveChannel_;
bool eventHandling_;
MpscQueue<Func> funcs_;
std::unique_ptr<TimerQueue> timerQueue_;
MpscQueue<Func> funcsOnQuit_;
bool callingFuncs_{ false };
#ifdef __linux__
int wakeupFd_;
std::unique_ptr<Channel> wakeupChannelPtr_;
#elif defined _WIN32
#else
int wakeupFd_[2];
std::unique_ptr<Channel> wakeupChannelPtr_;
#endif
void doRunInLoopFuncs();
#ifdef _WIN32
size_t index_{ size_t(-1) };
#else
size_t index_{ std::numeric_limits<size_t>::max() };
#endif
EventLoop **threadLocalLoopPtr_;
};
} // namespace trantor

View File

@ -12,7 +12,7 @@
*
*/
#include <trantor/net/EventLoopThread.h>
#include "event_loop_thread.h"
#include "core/log/logger.h"
#ifdef __linux__
#include <sys/prctl.h>

View File

@ -0,0 +1,74 @@
/**
*
* @file EventLoopThread.h
* @author An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "event_loop.h"
#include <condition_variable>
#include <future>
#include <memory>
#include <mutex>
#include <thread>
namespace trantor {
/**
* @brief This class represents an event loop thread.
*
*/
class EventLoopThread {
protected:
EventLoopThread(const EventLoopThread &) = delete;
EventLoopThread &operator=(const EventLoopThread &) = delete;
// some uncopyable classes maybe support move constructor....
EventLoopThread(EventLoopThread &&) noexcept(true) = default;
EventLoopThread &operator=(EventLoopThread &&) noexcept(true) = default;
public:
explicit EventLoopThread(const std::string &threadName = "EventLoopThread");
~EventLoopThread();
/**
* @brief Wait for the event loop to exit.
* @note This method blocks the current thread until the event loop exits.
*/
void wait();
/**
* @brief Get the pointer of the event loop of the thread.
*
* @return EventLoop*
*/
EventLoop *getLoop() const {
return loop_;
}
/**
* @brief Run the event loop of the thread. This method doesn't block the
* current thread.
*
*/
void run();
private:
EventLoop *loop_;
std::string loopThreadName_;
void loopFuncs();
std::promise<EventLoop *> promiseForLoopPointer_;
std::promise<int> promiseForRun_;
std::promise<int> promiseForLoop_;
std::once_flag once_;
std::thread thread_;
};
} // namespace trantor

View File

@ -12,7 +12,8 @@
*
*/
#include <trantor/net/EventLoopThreadPool.h>
#include "event_loop_thread_pool.h"
using namespace trantor;
EventLoopThreadPool::EventLoopThreadPool(size_t threadNum,
const std::string &name) :

View File

@ -0,0 +1,95 @@
/**
*
* @file EventLoopThreadPool.h
* @author An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "event_loop_thread.h"
#include <memory>
#include <vector>
namespace trantor {
/**
* @brief This class represents a pool of EventLoopThread objects
*
*/
class EventLoopThreadPool {
protected:
EventLoopThreadPool(const EventLoopThreadPool &) = delete;
EventLoopThreadPool &operator=(const EventLoopThreadPool &) = delete;
// some uncopyable classes maybe support move constructor....
EventLoopThreadPool(EventLoopThreadPool &&) noexcept(true) = default;
EventLoopThreadPool &operator=(EventLoopThreadPool &&) noexcept(true) = default;
public:
EventLoopThreadPool() = delete;
/**
* @brief Construct a new event loop thread pool instance.
*
* @param threadNum The number of threads
* @param name The name of the EventLoopThreadPool object.
*/
EventLoopThreadPool(size_t threadNum,
const std::string &name = "EventLoopThreadPool");
/**
* @brief Run all event loops in the pool.
* @note This function doesn't block the current thread.
*/
void start();
/**
* @brief Wait for all event loops in the pool to quit.
*
* @note This function blocks the current thread.
*/
void wait();
/**
* @brief Return the number of the event loop.
*
* @return size_t
*/
size_t size() {
return loopThreadVector_.size();
}
/**
* @brief Get the next event loop in the pool.
*
* @return EventLoop*
*/
EventLoop *getNextLoop();
/**
* @brief Get the event loop in the `id` position in the pool.
*
* @param id The id of the first event loop is zero. If the id >= the number
* of event loops, nullptr is returned.
* @return EventLoop*
*/
EventLoop *getLoop(size_t id);
/**
* @brief Get all event loops in the pool.
*
* @return std::vector<EventLoop *>
*/
std::vector<EventLoop *> getLoops() const;
private:
std::vector<std::shared_ptr<EventLoopThread> > loopThreadVector_;
size_t loopIndex_;
};
} // namespace trantor

View File

@ -12,14 +12,14 @@
*
*/
#include "Poller.h"
#include "core/loops/poller.h"
#ifdef __linux__
#include "poller/EpollPoller.h"
#include "poller/epoll_poller.h"
#elif defined _WIN32
#include "Wepoll.h"
#include "poller/EpollPoller.h"
#include "poller/epoll_poller.h"
#else
#include "poller/KQueue.h"
#include "poller/kqueue.h"
#endif
using namespace trantor;
Poller *Poller::newPoller(EventLoop *loop) {

57
core/loops/poller.h Normal file
View File

@ -0,0 +1,57 @@
/**
*
* Poller.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "event_loop.h"
#include <map>
#include <memory>
namespace trantor {
class Channel;
#ifdef _WIN32
using EventCallback = std::function<void(uint64_t)>;
#endif
class Poller {
protected:
Poller(const Poller &) = delete;
Poller &operator=(const Poller &) = delete;
// some uncopyable classes maybe support move constructor....
Poller(Poller &&) noexcept(true) = default;
Poller &operator=(Poller &&) noexcept(true) = default;
public:
explicit Poller(EventLoop *loop) :
ownerLoop_(loop){};
virtual ~Poller() {
}
void assertInLoopThread() {
ownerLoop_->assertInLoopThread();
}
virtual void poll(int timeoutMs, ChannelList *activeChannels) = 0;
virtual void updateChannel(Channel *channel) = 0;
virtual void removeChannel(Channel *channel) = 0;
#ifdef _WIN32
virtual void postEvent(uint64_t event) = 0;
virtual void setEventCallback(const EventCallback &cb) = 0;
#endif
virtual void resetAfterFork() {
}
static Poller *newPoller(EventLoop *loop);
private:
EventLoop *ownerLoop_;
};
} // namespace trantor

View File

@ -12,9 +12,10 @@
*
*/
#include "EpollPoller.h"
#include "Channel.h"
#include "epoll_poller.h"
#include "core/log/logger.h"
#include "core/loops/channel.h"
#ifdef __linux__
#include <assert.h>
#include <poll.h>
@ -30,6 +31,7 @@
#include <iostream>
#define EPOLL_CLOEXEC _O_NOINHERIT
#endif
namespace trantor {
#if defined __linux__ || defined _WIN32

View File

@ -0,0 +1,61 @@
/**
*
* EpollPoller.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "core/loops/event_loop.h"
#include "core/loops/poller.h"
#if defined __linux__ || defined _WIN32
#include <map>
#include <memory>
using EventList = std::vector<struct epoll_event>;
#endif
namespace trantor {
class Channel;
class EpollPoller : public Poller {
public:
explicit EpollPoller(EventLoop *loop);
virtual ~EpollPoller();
virtual void poll(int timeoutMs, ChannelList *activeChannels) override;
virtual void updateChannel(Channel *channel) override;
virtual void removeChannel(Channel *channel) override;
#ifdef _WIN32
virtual void postEvent(uint64_t event) override;
virtual void setEventCallback(const EventCallback &cb) override {
eventCallback_ = cb;
}
#endif
private:
#if defined __linux__ || defined _WIN32
static const int kInitEventListSize = 16;
#ifdef _WIN32
void *epollfd_;
EventCallback eventCallback_{ [](uint64_t event) {} };
#else
int epollfd_;
#endif
EventList events_;
void update(int operation, Channel *channel);
#ifndef NDEBUG
using ChannelMap = std::map<int, Channel *>;
ChannelMap channels_;
#endif
void fillActiveChannels(int numEvents, ChannelList *activeChannels) const;
#endif
};
} // namespace trantor

View File

@ -1,13 +1,15 @@
#include "KQueue.h"
#include "Channel.h"
#include "kqueue.h"
#include "core/loops/channel.h"
#ifdef USE_KQUEUE
#include "core/log/logger.h"
#include <poll.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/types.h>
#include "core/log/logger.h"
#include <unistd.h>
#endif
namespace trantor {
#ifdef USE_KQUEUE
namespace {

View File

@ -0,0 +1,53 @@
/**
*
* KQueue.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/trantor
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
* Trantor
*
*/
#pragma once
#include "core/loops/event_loop.h"
#include "core/loops/poller.h"
#if (defined(__unix__) && !defined(__linux__)) || \
(defined(__APPLE__) && defined(__MACH__))
#define USE_KQUEUE
#include <memory>
#include <unordered_map>
#include <vector>
using EventList = std::vector<struct kevent>;
#endif
namespace trantor {
class Channel;
class KQueue : public Poller {
public:
explicit KQueue(EventLoop *loop);
virtual ~KQueue();
virtual void poll(int timeoutMs, ChannelList *activeChannels) override;
virtual void updateChannel(Channel *channel) override;
virtual void removeChannel(Channel *channel) override;
virtual void resetAfterFork() override;
private:
#ifdef USE_KQUEUE
static const int kInitEventListSize = 16;
int kqfd_;
EventList events_;
using ChannelMap = std::unordered_map<int, std::pair<int, Channel *> >;
ChannelMap channels_;
void fillActiveChannels(int numEvents, ChannelList *activeChannels) const;
void update(Channel *channel);
#endif
};
} // namespace trantor

View File

@ -12,9 +12,9 @@
*
*/
#include "Timer.h"
#include <trantor/net/EventLoop.h>
#include "timer.h"
#include "core/log/logger.h"
#include "core/loops/event_loop.h"
namespace trantor {
std::atomic<TimerId> Timer::timersCreated_ = ATOMIC_VAR_INIT(InvalidTimerId);

69
core/loops/timer.h Normal file
View File

@ -0,0 +1,69 @@
/**
*
* Timer.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include <trantor/net/callbacks.h>
#include <atomic>
#include <chrono>
#include <functional>
#include <iostream>
namespace trantor {
using TimerId = uint64_t;
using TimePoint = std::chrono::steady_clock::time_point;
using TimeInterval = std::chrono::microseconds;
class Timer {
protected:
Timer(const Timer &) = delete;
Timer &operator=(const Timer &) = delete;
// some uncopyable classes maybe support move constructor....
Timer(Timer &&) noexcept(true) = default;
Timer &operator=(Timer &&) noexcept(true) = default;
public:
Timer(const TimerCallback &cb,
const TimePoint &when,
const TimeInterval &interval);
Timer(TimerCallback &&cb,
const TimePoint &when,
const TimeInterval &interval);
~Timer() {
// std::cout<<"Timer unconstract!"<<std::endl;
}
void run() const;
void restart(const TimePoint &now);
bool operator<(const Timer &t) const;
bool operator>(const Timer &t) const;
const TimePoint &when() const {
return when_;
}
bool isRepeat() {
return repeat_;
}
TimerId id() {
return id_;
}
private:
TimerCallback callback_;
TimePoint when_;
const TimeInterval interval_;
const bool repeat_;
const TimerId id_;
static std::atomic<TimerId> timersCreated_;
};
} // namespace trantor

View File

@ -12,10 +12,10 @@
*
*/
#include <trantor/net/EventLoop.h>
#include "event_loop.h"
#include "Channel.h"
#include "TimerQueue.h"
#include "channel.h"
#include "timer_queue.h"
#ifdef __linux__
#include <sys/timerfd.h>
#endif

79
core/loops/timer_queue.h Normal file
View File

@ -0,0 +1,79 @@
/**
*
* TimerQueue.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "timer.h"
#include <trantor/net/callbacks.h>
#include <atomic>
#include <memory>
#include <queue>
#include <unordered_set>
namespace trantor {
// class Timer;
class EventLoop;
class Channel;
using TimerPtr = std::shared_ptr<Timer>;
struct TimerPtrComparer {
bool operator()(const TimerPtr &x, const TimerPtr &y) const {
return *x > *y;
}
};
class TimerQueue {
protected:
TimerQueue(const TimerQueue &) = delete;
TimerQueue &operator=(const TimerQueue &) = delete;
// some uncopyable classes maybe support move constructor....
TimerQueue(TimerQueue &&) noexcept(true) = default;
TimerQueue &operator=(TimerQueue &&) noexcept(true) = default;
public:
explicit TimerQueue(EventLoop *loop);
~TimerQueue();
TimerId addTimer(const TimerCallback &cb,
const TimePoint &when,
const TimeInterval &interval);
TimerId addTimer(TimerCallback &&cb,
const TimePoint &when,
const TimeInterval &interval);
void addTimerInLoop(const TimerPtr &timer);
void invalidateTimer(TimerId id);
#ifdef __linux__
void reset();
#else
int64_t getTimeout() const;
void processTimers();
#endif
protected:
EventLoop *loop_;
#ifdef __linux__
int timerfd_;
std::shared_ptr<Channel> timerfdChannelPtr_;
void handleRead();
#endif
std::priority_queue<TimerPtr, std::vector<TimerPtr>, TimerPtrComparer>
timers_;
bool callingExpiredTimers_;
bool insert(const TimerPtr &timePtr);
std::vector<TimerPtr> getExpired();
void reset(const std::vector<TimerPtr> &expired, const TimePoint &now);
std::vector<TimerPtr> getExpired(const TimePoint &now);
private:
std::unordered_set<uint64_t> timerIdSet_;
};
} // namespace trantor

View File

@ -25,7 +25,7 @@
#include <drogon/plugins/Plugin.h>
#include <drogon/utils/HttpConstraint.h>
#include <drogon/utils/Utilities.h>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include <trantor/net/Resolver.h>
#include <trantor/utils/NonCopyable.h>
#include <chrono>

View File

@ -19,7 +19,7 @@
#include <http/HttpTypes.h>
#include <drogon/drogon_callbacks.h>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include <trantor/utils/NonCopyable.h>
#include <functional>
#include <future>

View File

@ -18,7 +18,7 @@
#include <http/HttpResponse.h>
#include <http/HttpTypes.h>
#include <drogon/WebSocketConnection.h>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include <functional>
#include <memory>
#include <string>

View File

@ -14,7 +14,7 @@
#pragma once
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/net/inet_address.h"
#include "core/math/date.h"
#include "core/log/logger.h"

View File

@ -15,7 +15,7 @@
#pragma once
#include <assert.h>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/log/logger.h"
#include <atomic>
#include <deque>

View File

@ -20,7 +20,7 @@
#include <http/HttpRequest.h>
#include <drogon/utils/Utilities.h>
#include <stdio.h>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/net/inet_address.h"
#include "core/log/logger.h"
#include "core/containers/msg_buffer.h"

View File

@ -16,7 +16,7 @@
#include "CacheMap.h"
#include "Session.h"
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include <trantor/utils/NonCopyable.h>
#include <memory>
#include <mutex>

View File

@ -17,7 +17,7 @@
#include "impl_forwards.h"
#include <http/Cookie.h>
#include <drogon/HttpClient.h>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include <trantor/net/Resolver.h>
#include <trantor/net/TcpClient.h>
#include <list>

View File

@ -15,7 +15,7 @@
#pragma once
#include "impl_forwards.h"
#include <trantor/net/EventLoopThreadPool.h>
#include "core/loops/event_loop_thread_pool.h"
#include <trantor/net/callbacks.h>
#include <trantor/utils/NonCopyable.h>
#include <memory>

View File

@ -15,7 +15,7 @@
#pragma once
#include <sys/stat.h>
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <trantor/utils/NonCopyable.h>
#include <unordered_map>
#include <vector>

View File

@ -11,7 +11,7 @@
* Drogon
*
*/
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include <trantor/utils/NonCopyable.h>
#include <atomic>
#include <chrono>

View File

@ -16,7 +16,7 @@
#include "impl_forwards.h"
#include <drogon/WebSocketClient.h>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include <trantor/net/TcpClient.h>
#include <trantor/utils/NonCopyable.h>

View File

@ -18,7 +18,7 @@
#include <drogon/HttpAppFramework.h>
#include <drogon/drogon.h>
#include <drogon/drogon_test.h>
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <trantor/net/TcpClient.h>
#include <algorithm>

View File

@ -1,5 +1,5 @@
#include "PipeliningTest.h"
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include <atomic>
void PipeliningTest::asyncHandleHttpRequest(

View File

@ -1,7 +1,7 @@
#include <drogon/CacheMap.h>
#include <drogon/HttpAppFramework.h>
#include <drogon/drogon_test.h>
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <chrono>

View File

@ -1,314 +0,0 @@
/**
*
* @file Channel.h
* @author An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "core/log/logger.h"
#include <trantor/utils/NonCopyable.h>
#include <trantor/exports.h>
#include <functional>
#include <assert.h>
#include <memory>
namespace trantor
{
class EventLoop;
/**
* @brief This class is used to implement reactor pattern. A Channel object
* manages a socket fd. Users use a Channel object to receive write or read
* events on the socket it manages.
*
*/
class TRANTOR_EXPORT Channel : NonCopyable
{
public:
using EventCallback = std::function<void()>;
/**
* @brief Construct a new Channel instance.
*
* @param loop The event loop in which the channel works.
* @param fd The socket fd.
*/
Channel(EventLoop *loop, int fd);
/**
* @brief Set the read callback.
*
* @param cb The callback is called when read event occurs on the socket.
* @note One should call the enableReading() method to ensure that the
* callback would be called when some data is received on the socket.
*/
void setReadCallback(const EventCallback &cb)
{
readCallback_ = cb;
};
void setReadCallback(EventCallback &&cb)
{
readCallback_ = std::move(cb);
}
/**
* @brief Set the write callback.
*
* @param cb The callback is called when write event occurs on the socket.
* @note One should call the enableWriting() method to ensure that the
* callback would be called when the socket can be written.
*/
void setWriteCallback(const EventCallback &cb)
{
writeCallback_ = cb;
};
void setWriteCallback(EventCallback &&cb)
{
writeCallback_ = std::move(cb);
}
/**
* @brief Set the close callback.
*
* @param cb The callback is called when the socket is closed.
*/
void setCloseCallback(const EventCallback &cb)
{
closeCallback_ = cb;
}
void setCloseCallback(EventCallback &&cb)
{
closeCallback_ = std::move(cb);
}
/**
* @brief Set the error callback.
*
* @param cb The callback is called when an error occurs on the socket.
*/
void setErrorCallback(const EventCallback &cb)
{
errorCallback_ = cb;
}
void setErrorCallback(EventCallback &&cb)
{
errorCallback_ = std::move(cb);
}
/**
* @brief Set the event callback.
*
* @param cb The callback is called when any event occurs on the socket.
* @note If the event callback is set to the channel, any other callback
* wouldn't be called again.
*/
void setEventCallback(const EventCallback &cb)
{
eventCallback_ = cb;
}
void setEventCallback(EventCallback &&cb)
{
eventCallback_ = std::move(cb);
}
/**
* @brief Return the fd of the socket.
*
* @return int
*/
int fd() const
{
return fd_;
}
/**
* @brief Return the events enabled on the socket.
*
* @return int
*/
int events() const
{
return events_;
}
/**
* @brief Return the events that occurred on the socket.
*
* @return int
*/
int revents() const
{
return revents_;
}
/**
* @brief Check whether there is no event enabled on the socket.
*
* @return true
* @return false
*/
bool isNoneEvent() const
{
return events_ == kNoneEvent;
};
/**
* @brief Disable all events on the socket.
*
*/
void disableAll()
{
events_ = kNoneEvent;
update();
}
/**
* @brief Remove the socket from the poller in the event loop.
*
*/
void remove();
/**
* @brief Return the event loop.
*
* @return EventLoop*
*/
EventLoop *ownerLoop()
{
return loop_;
};
/**
* @brief Enable the read event on the socket.
*
*/
void enableReading()
{
events_ |= kReadEvent;
update();
}
/**
* @brief Disable the read event on the socket.
*
*/
void disableReading()
{
events_ &= ~kReadEvent;
update();
}
/**
* @brief Enable the write event on the socket.
*
*/
void enableWriting()
{
events_ |= kWriteEvent;
update();
}
/**
* @brief Disable the write event on the socket.
*
*/
void disableWriting()
{
events_ &= ~kWriteEvent;
update();
}
/**
* @brief Check whether the write event is enabled on the socket.
*
* @return true
* @return false
*/
bool isWriting() const
{
return events_ & kWriteEvent;
}
/**
* @brief Check whether the read event is enabled on the socket.
*
* @return true
* @return false
*/
bool isReading() const
{
return events_ & kReadEvent;
}
/**
* @brief Set and update the events enabled.
*
* @param events
*/
void updateEvents(int events)
{
events_ = events;
update();
}
/**
* @brief This method is used to ensure that the callback owner is valid
* when a callback is called.
*
* @param obj The callback owner. Usually, the owner is also the owner of
* the channel.
* @note The 'obj' is kept in a weak_ptr object, so this method does not
* cause a circular reference problem.
*/
void tie(const std::shared_ptr<void> &obj)
{
tie_ = obj;
tied_ = true;
}
static const int kNoneEvent;
static const int kReadEvent;
static const int kWriteEvent;
private:
friend class EventLoop;
friend class EpollPoller;
friend class KQueue;
void update();
void handleEvent();
void handleEventSafely();
int setRevents(int revt)
{
// LOG_TRACE<<"revents="<<revt;
revents_ = revt;
return revt;
};
int index()
{
return index_;
};
void setIndex(int index)
{
index_ = index;
};
EventLoop *loop_;
const int fd_;
int events_;
int revents_;
int index_;
bool addedToLoop_{false};
EventCallback readCallback_;
EventCallback writeCallback_;
EventCallback errorCallback_;
EventCallback closeCallback_;
EventCallback eventCallback_;
std::weak_ptr<void> tie_;
bool tied_;
};
} // namespace trantor

View File

@ -1,321 +0,0 @@
// Copyright 2010, Shuo Chen. All rights reserved.
// http://code.google.com/p/muduo/
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Shuo Chen (chenshuo at chenshuo dot com)
// Taken from Muduo and modified
// Copyright 2016, Tao An. All rights reserved.
// https://github.com/an-tao/trantor
//
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
// Author: Tao An
#pragma once
#include <trantor/utils/NonCopyable.h>
#include "core/math/date.h"
#include "core/containers/lock_free_queue.h"
#include <trantor/exports.h>
#include <thread>
#include <memory>
#include <vector>
#include <mutex>
#include <queue>
#include <functional>
#include <chrono>
#include <limits>
namespace trantor
{
class Poller;
class TimerQueue;
class Channel;
using ChannelList = std::vector<Channel *>;
using Func = std::function<void()>;
using TimerId = uint64_t;
enum
{
InvalidTimerId = 0
};
/**
* @brief As the name implies, this class represents an event loop that runs in
* a perticular thread. The event loop can handle network I/O events and timers
* in asynchronous mode.
* @note An event loop object always belongs to a separate thread, and there is
* one event loop object at most in a thread. We can call an event loop object
* the event loop of the thread it belongs to, or call that thread the thread of
* the event loop.
*/
class TRANTOR_EXPORT EventLoop : NonCopyable
{
public:
EventLoop();
~EventLoop();
/**
* @brief Run the event loop. This method will be blocked until the event
* loop exits.
*
*/
void loop();
/**
* @brief Let the event loop quit.
*
*/
void quit();
/**
* @brief Assertion that the current thread is the thread to which the event
* loop belongs. If the assertion fails, the program aborts.
*/
void assertInLoopThread()
{
if (!isInLoopThread())
{
abortNotInLoopThread();
}
};
#ifdef __linux__
/**
* @brief Make the timer queue works after calling the fork() function.
*
*/
void resetTimerQueue();
#endif
/**
* @brief Make the event loop works after calling the fork() function.
*
*/
void resetAfterFork();
/**
* @brief Return true if the current thread is the thread to which the event
* loop belongs.
*
* @return true
* @return false
*/
bool isInLoopThread() const
{
return threadId_ == std::this_thread::get_id();
};
/**
* @brief Get the event loop of the current thread. Return nullptr if there
* is no event loop in the current thread.
*
* @return EventLoop*
*/
static EventLoop *getEventLoopOfCurrentThread();
/**
* @brief Run the function f in the thread of the event loop.
*
* @param f
* @note If the current thread is the thread of the event loop, the function
* f is executed directly before the method exiting.
*/
void runInLoop(const Func &f);
void runInLoop(Func &&f);
/**
* @brief Run the function f in the thread of the event loop.
*
* @param f
* @note The difference between this method and the runInLoop() method is
* that the function f is executed after the method exiting no matter if the
* current thread is the thread of the event loop.
*/
void queueInLoop(const Func &f);
void queueInLoop(Func &&f);
/**
* @brief Run a function at a time point.
*
* @param time The time to run the function.
* @param cb The function to run.
* @return TimerId The ID of the timer.
*/
TimerId runAt(const Date &time, const Func &cb);
TimerId runAt(const Date &time, Func &&cb);
/**
* @brief Run a function after a period of time.
*
* @param delay Represent the period of time in seconds.
* @param cb The function to run.
* @return TimerId The ID of the timer.
*/
TimerId runAfter(double delay, const Func &cb);
TimerId runAfter(double delay, Func &&cb);
/**
* @brief Run a function after a period of time.
* @note Users could use chrono literals to represent a time duration
* For example:
* @code
runAfter(5s, task);
runAfter(10min, task);
@endcode
*/
TimerId runAfter(const std::chrono::duration<double> &delay, const Func &cb)
{
return runAfter(delay.count(), cb);
}
TimerId runAfter(const std::chrono::duration<double> &delay, Func &&cb)
{
return runAfter(delay.count(), std::move(cb));
}
/**
* @brief Repeatedly run a function every period of time.
*
* @param interval The duration in seconds.
* @param cb The function to run.
* @return TimerId The ID of the timer.
*/
TimerId runEvery(double interval, const Func &cb);
TimerId runEvery(double interval, Func &&cb);
/**
* @brief Repeatedly run a function every period of time.
* Users could use chrono literals to represent a time duration
* For example:
* @code
runEvery(5s, task);
runEvery(10min, task);
runEvery(0.1h, task);
@endcode
*/
TimerId runEvery(const std::chrono::duration<double> &interval,
const Func &cb)
{
return runEvery(interval.count(), cb);
}
TimerId runEvery(const std::chrono::duration<double> &interval, Func &&cb)
{
return runEvery(interval.count(), std::move(cb));
}
/**
* @brief Invalidate the timer identified by the given ID.
*
* @param id The ID of the timer.
*/
void invalidateTimer(TimerId id);
/**
* @brief Move the EventLoop to the current thread, this method must be
* called before the loop is running.
*
*/
void moveToCurrentThread();
/**
* @brief Update channel status. This method is usually used internally.
*
* @param chl
*/
void updateChannel(Channel *chl);
/**
* @brief Remove a channel from the event loop. This method is usually used
* internally.
*
* @param chl
*/
void removeChannel(Channel *chl);
/**
* @brief Return the index of the event loop.
*
* @return size_t
*/
size_t index()
{
return index_;
}
/**
* @brief Set the index of the event loop.
*
* @param index
*/
void setIndex(size_t index)
{
index_ = index;
}
/**
* @brief Return true if the event loop is running.
*
* @return true
* @return false
*/
bool isRunning()
{
return looping_ && (!quit_);
}
/**
* @brief Check if the event loop is calling a function.
*
* @return true
* @return false
*/
bool isCallingFunctions()
{
return callingFuncs_;
}
/**
* @brief Run functions when the event loop quits
*
* @param cb the function to run
* @note the function runs on the thread that quits the EventLoop
*/
void runOnQuit(Func &&cb);
void runOnQuit(const Func &cb);
private:
void abortNotInLoopThread();
void wakeup();
void wakeupRead();
bool looping_;
std::thread::id threadId_;
bool quit_;
std::unique_ptr<Poller> poller_;
ChannelList activeChannels_;
Channel *currentActiveChannel_;
bool eventHandling_;
MpscQueue<Func> funcs_;
std::unique_ptr<TimerQueue> timerQueue_;
MpscQueue<Func> funcsOnQuit_;
bool callingFuncs_{false};
#ifdef __linux__
int wakeupFd_;
std::unique_ptr<Channel> wakeupChannelPtr_;
#elif defined _WIN32
#else
int wakeupFd_[2];
std::unique_ptr<Channel> wakeupChannelPtr_;
#endif
void doRunInLoopFuncs();
#ifdef _WIN32
size_t index_{size_t(-1)};
#else
size_t index_{std::numeric_limits<size_t>::max()};
#endif
EventLoop **threadLocalLoopPtr_;
};
} // namespace trantor

View File

@ -1,72 +0,0 @@
/**
*
* @file EventLoopThread.h
* @author An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include <trantor/net/EventLoop.h>
#include <trantor/utils/NonCopyable.h>
#include <trantor/exports.h>
#include <mutex>
#include <thread>
#include <memory>
#include <condition_variable>
#include <future>
namespace trantor
{
/**
* @brief This class represents an event loop thread.
*
*/
class TRANTOR_EXPORT EventLoopThread : NonCopyable
{
public:
explicit EventLoopThread(const std::string &threadName = "EventLoopThread");
~EventLoopThread();
/**
* @brief Wait for the event loop to exit.
* @note This method blocks the current thread until the event loop exits.
*/
void wait();
/**
* @brief Get the pointer of the event loop of the thread.
*
* @return EventLoop*
*/
EventLoop *getLoop() const
{
return loop_;
}
/**
* @brief Run the event loop of the thread. This method doesn't block the
* current thread.
*
*/
void run();
private:
EventLoop *loop_;
std::string loopThreadName_;
void loopFuncs();
std::promise<EventLoop *> promiseForLoopPointer_;
std::promise<int> promiseForRun_;
std::promise<int> promiseForLoop_;
std::once_flag once_;
std::thread thread_;
};
} // namespace trantor

View File

@ -1,92 +0,0 @@
/**
*
* @file EventLoopThreadPool.h
* @author An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include <trantor/net/EventLoopThread.h>
#include <trantor/exports.h>
#include <vector>
#include <memory>
namespace trantor
{
/**
* @brief This class represents a pool of EventLoopThread objects
*
*/
class TRANTOR_EXPORT EventLoopThreadPool : NonCopyable
{
public:
EventLoopThreadPool() = delete;
/**
* @brief Construct a new event loop thread pool instance.
*
* @param threadNum The number of threads
* @param name The name of the EventLoopThreadPool object.
*/
EventLoopThreadPool(size_t threadNum,
const std::string &name = "EventLoopThreadPool");
/**
* @brief Run all event loops in the pool.
* @note This function doesn't block the current thread.
*/
void start();
/**
* @brief Wait for all event loops in the pool to quit.
*
* @note This function blocks the current thread.
*/
void wait();
/**
* @brief Return the number of the event loop.
*
* @return size_t
*/
size_t size()
{
return loopThreadVector_.size();
}
/**
* @brief Get the next event loop in the pool.
*
* @return EventLoop*
*/
EventLoop *getNextLoop();
/**
* @brief Get the event loop in the `id` position in the pool.
*
* @param id The id of the first event loop is zero. If the id >= the number
* of event loops, nullptr is returned.
* @return EventLoop*
*/
EventLoop *getLoop(size_t id);
/**
* @brief Get all event loops in the pool.
*
* @return std::vector<EventLoop *>
*/
std::vector<EventLoop *> getLoops() const;
private:
std::vector<std::shared_ptr<EventLoopThread>> loopThreadVector_;
size_t loopIndex_;
};
} // namespace trantor

View File

@ -8,7 +8,7 @@
#pragma once
#include <trantor/exports.h>
#include <memory>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/net/inet_address.h"
namespace trantor

View File

@ -13,7 +13,7 @@
#include "Connector.h"
#include "inner/TcpConnectionImpl.h"
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/log/logger.h"
#include <algorithm>

View File

@ -17,7 +17,7 @@
// Author: Tao An
#pragma once
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/net/inet_address.h"
#include <trantor/net/TcpConnection.h>
#include <trantor/exports.h>

View File

@ -14,7 +14,7 @@
#pragma once
#include <trantor/exports.h>
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/net/inet_address.h"
#include <trantor/utils/NonCopyable.h>
#include "core/containers/msg_buffer.h"

View File

@ -12,7 +12,7 @@
*
*/
#include "Acceptor.h"
#include "core/loops/acceptor.h"
#include "inner/TcpConnectionImpl.h"
#include <trantor/net/TcpServer.h>
#include "core/log/logger.h"

View File

@ -16,7 +16,7 @@
#include <trantor/net/callbacks.h>
#include <trantor/utils/NonCopyable.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThreadPool.h>
#include "core/loops/event_loop_thread_pool.h"
#include "core/net/inet_address.h"
#include <trantor/net/TcpConnection.h>
#include <trantor/utils/TimingWheel.h>

View File

@ -1,56 +0,0 @@
/**
*
* Acceptor.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include <trantor/net/EventLoop.h>
#include <trantor/utils/NonCopyable.h>
#include "core/net/socket.h"
#include "core/net/inet_address.h"
#include "Channel.h"
#include <functional>
namespace trantor
{
using NewConnectionCallback = std::function<void(int fd, const InetAddress &)>;
class Acceptor : NonCopyable
{
public:
Acceptor(EventLoop *loop,
const InetAddress &addr,
bool reUseAddr = true,
bool reUsePort = true);
~Acceptor();
const InetAddress &addr() const
{
return addr_;
}
void setNewConnectionCallback(const NewConnectionCallback &cb)
{
newConnectionCallback_ = cb;
};
void listen();
protected:
#ifndef _WIN32
int idleFd_;
#endif
Socket sock_;
InetAddress addr_;
EventLoop *loop_;
NewConnectionCallback newConnectionCallback_;
Channel acceptChannel_;
void readCallback();
};
} // namespace trantor

View File

@ -7,7 +7,7 @@
#include "AresResolver.h"
#include <ares.h>
#include <trantor/net/Channel.h>
#include "core/loops/channel.h"
#ifdef _WIN32
#include <winsock2.h>
#else

View File

@ -8,7 +8,7 @@
#pragma once
#include <trantor/net/Resolver.h>
#include <trantor/utils/NonCopyable.h>
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <map>
#include <memory>
#include <string.h>

View File

@ -13,7 +13,7 @@
*/
#include "Connector.h"
#include "Channel.h"
#include "core/loops/channel.h"
#include "core/net/socket.h"
using namespace trantor;

View File

@ -14,7 +14,7 @@
#pragma once
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/net/inet_address.h"
#include <atomic>
#include <memory>

View File

@ -1,54 +0,0 @@
/**
*
* Poller.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "NonCopyable.h"
#include "EventLoop.h"
#include <memory>
#include <map>
namespace trantor
{
class Channel;
#ifdef _WIN32
using EventCallback = std::function<void(uint64_t)>;
#endif
class Poller : NonCopyable
{
public:
explicit Poller(EventLoop *loop) : ownerLoop_(loop){};
virtual ~Poller()
{
}
void assertInLoopThread()
{
ownerLoop_->assertInLoopThread();
}
virtual void poll(int timeoutMs, ChannelList *activeChannels) = 0;
virtual void updateChannel(Channel *channel) = 0;
virtual void removeChannel(Channel *channel) = 0;
#ifdef _WIN32
virtual void postEvent(uint64_t event) = 0;
virtual void setEventCallback(const EventCallback &cb) = 0;
#endif
virtual void resetAfterFork()
{
}
static Poller *newPoller(EventLoop *loop);
private:
EventLoop *ownerLoop_;
};
} // namespace trantor

View File

@ -13,7 +13,7 @@
*/
#include "TcpConnectionImpl.h"
#include "Channel.h"
#include "core/loops/channel.h"
#include "core/net/socket.h"
#ifdef __linux__
#include <sys/sendfile.h>

View File

@ -1,68 +0,0 @@
/**
*
* Timer.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include <trantor/utils/NonCopyable.h>
#include <trantor/net/callbacks.h>
#include <functional>
#include <atomic>
#include <iostream>
#include <chrono>
namespace trantor
{
using TimerId = uint64_t;
using TimePoint = std::chrono::steady_clock::time_point;
using TimeInterval = std::chrono::microseconds;
class Timer : public NonCopyable
{
public:
Timer(const TimerCallback &cb,
const TimePoint &when,
const TimeInterval &interval);
Timer(TimerCallback &&cb,
const TimePoint &when,
const TimeInterval &interval);
~Timer()
{
// std::cout<<"Timer unconstract!"<<std::endl;
}
void run() const;
void restart(const TimePoint &now);
bool operator<(const Timer &t) const;
bool operator>(const Timer &t) const;
const TimePoint &when() const
{
return when_;
}
bool isRepeat()
{
return repeat_;
}
TimerId id()
{
return id_;
}
private:
TimerCallback callback_;
TimePoint when_;
const TimeInterval interval_;
const bool repeat_;
const TimerId id_;
static std::atomic<TimerId> timersCreated_;
};
} // namespace trantor

View File

@ -1,76 +0,0 @@
/**
*
* TimerQueue.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include <trantor/utils/NonCopyable.h>
#include <trantor/net/callbacks.h>
#include "Timer.h"
#include <queue>
#include <memory>
#include <atomic>
#include <unordered_set>
namespace trantor
{
// class Timer;
class EventLoop;
class Channel;
using TimerPtr = std::shared_ptr<Timer>;
struct TimerPtrComparer
{
bool operator()(const TimerPtr &x, const TimerPtr &y) const
{
return *x > *y;
}
};
class TimerQueue : NonCopyable
{
public:
explicit TimerQueue(EventLoop *loop);
~TimerQueue();
TimerId addTimer(const TimerCallback &cb,
const TimePoint &when,
const TimeInterval &interval);
TimerId addTimer(TimerCallback &&cb,
const TimePoint &when,
const TimeInterval &interval);
void addTimerInLoop(const TimerPtr &timer);
void invalidateTimer(TimerId id);
#ifdef __linux__
void reset();
#else
int64_t getTimeout() const;
void processTimers();
#endif
protected:
EventLoop *loop_;
#ifdef __linux__
int timerfd_;
std::shared_ptr<Channel> timerfdChannelPtr_;
void handleRead();
#endif
std::priority_queue<TimerPtr, std::vector<TimerPtr>, TimerPtrComparer>
timers_;
bool callingExpiredTimers_;
bool insert(const TimerPtr &timePtr);
std::vector<TimerPtr> getExpired();
void reset(const std::vector<TimerPtr> &expired, const TimePoint &now);
std::vector<TimerPtr> getExpired(const TimePoint &now);
private:
std::unordered_set<uint64_t> timerIdSet_;
};
} // namespace trantor

View File

@ -1,64 +0,0 @@
/**
*
* EpollPoller.h
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
#pragma once
#include "../Poller.h"
#include <trantor/utils/NonCopyable.h>
#include <trantor/net/EventLoop.h>
#if defined __linux__ || defined _WIN32
#include <memory>
#include <map>
using EventList = std::vector<struct epoll_event>;
#endif
namespace trantor
{
class Channel;
class EpollPoller : public Poller
{
public:
explicit EpollPoller(EventLoop *loop);
virtual ~EpollPoller();
virtual void poll(int timeoutMs, ChannelList *activeChannels) override;
virtual void updateChannel(Channel *channel) override;
virtual void removeChannel(Channel *channel) override;
#ifdef _WIN32
virtual void postEvent(uint64_t event) override;
virtual void setEventCallback(const EventCallback &cb) override
{
eventCallback_ = cb;
}
#endif
private:
#if defined __linux__ || defined _WIN32
static const int kInitEventListSize = 16;
#ifdef _WIN32
void *epollfd_;
EventCallback eventCallback_{[](uint64_t event) {}};
#else
int epollfd_;
#endif
EventList events_;
void update(int operation, Channel *channel);
#ifndef NDEBUG
using ChannelMap = std::map<int, Channel *>;
ChannelMap channels_;
#endif
void fillActiveChannels(int numEvents, ChannelList *activeChannels) const;
#endif
};
} // namespace trantor

View File

@ -1,55 +0,0 @@
/**
*
* KQueue.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/trantor
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
* Trantor
*
*/
#pragma once
#include "../Poller.h"
#include <trantor/utils/NonCopyable.h>
#include <trantor/net/EventLoop.h>
#if (defined(__unix__) && !defined(__linux__)) || \
(defined(__APPLE__) && defined(__MACH__))
#define USE_KQUEUE
#include <memory>
#include <unordered_map>
#include <vector>
using EventList = std::vector<struct kevent>;
#endif
namespace trantor
{
class Channel;
class KQueue : public Poller
{
public:
explicit KQueue(EventLoop *loop);
virtual ~KQueue();
virtual void poll(int timeoutMs, ChannelList *activeChannels) override;
virtual void updateChannel(Channel *channel) override;
virtual void removeChannel(Channel *channel) override;
virtual void resetAfterFork() override;
private:
#ifdef USE_KQUEUE
static const int kInitEventListSize = 16;
int kqfd_;
EventList events_;
using ChannelMap = std::unordered_map<int, std::pair<int, Channel *>>;
ChannelMap channels_;
void fillActiveChannels(int numEvents, ChannelList *activeChannels) const;
void update(Channel *channel);
#endif
};
} // namespace trantor

View File

@ -1,6 +1,6 @@
#include <trantor/net/TcpClient.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <string>
#include <iostream>
#include <atomic>

View File

@ -1,6 +1,6 @@
#include <trantor/net/TcpServer.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <string>
#include <iostream>
using namespace trantor;

View File

@ -1,6 +1,6 @@
#include <trantor/net/TcpServer.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <string>
#include <iostream>
using namespace trantor;

View File

@ -2,7 +2,7 @@
// Created by antao on 1/14/17.
//
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#ifndef _WIN32
#include <unistd.h>
#endif

View File

@ -1,4 +1,4 @@
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <iostream>
#include <atomic>
#include <future>

View File

@ -1,4 +1,4 @@
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <iostream>
#include <atomic>
#include <future>

View File

@ -1,6 +1,6 @@
#include <trantor/net/TcpClient.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <string>
#include <iostream>
#include <atomic>

View File

@ -1,6 +1,6 @@
#include <trantor/net/TcpServer.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <string>
#include <iostream>
using namespace trantor;

View File

@ -1,6 +1,6 @@
#include <trantor/net/TcpServer.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <string>
#include <iostream>
#include <thread>

View File

@ -1,6 +1,6 @@
#include <trantor/net/TcpClient.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <string>
#include <iostream>
#include <atomic>

View File

@ -1,6 +1,6 @@
#include <trantor/net/TcpServer.h>
#include "core/log/logger.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <string>
#include <iostream>
using namespace trantor;

View File

@ -1,4 +1,4 @@
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/log/logger.h"
#include <iostream>
#include <thread>

View File

@ -1,4 +1,4 @@
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/log/logger.h"
#include <iostream>
int main()

View File

@ -15,7 +15,7 @@
#pragma once
#include "TaskQueue.h"
#include <trantor/net/EventLoopThread.h>
#include "core/loops/event_loop_thread.h"
#include <trantor/exports.h>
#include <string>
#include <queue>

View File

@ -14,7 +14,7 @@
#pragma once
#include <trantor/net/EventLoop.h>
#include "core/loops/event_loop.h"
#include "core/log/logger.h"
#include <trantor/exports.h>
#include <map>