mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2025-02-20 15:14:26 +01:00
Move event loops from trantor to core.
This commit is contained in:
parent
6a29af9963
commit
9543341423
@ -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")
|
||||
|
@ -12,7 +12,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Acceptor.h"
|
||||
#include "acceptor.h"
|
||||
using namespace trantor;
|
||||
|
||||
#ifndef O_CLOEXEC
|
58
core/loops/acceptor.h
Normal file
58
core/loops/acceptor.h
Normal 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
|
@ -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
291
core/loops/channel.h
Normal 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
|
@ -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
313
core/loops/event_loop.h
Normal 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
|
@ -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>
|
74
core/loops/event_loop_thread.h
Normal file
74
core/loops/event_loop_thread.h
Normal 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
|
@ -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) :
|
95
core/loops/event_loop_thread_pool.h
Normal file
95
core/loops/event_loop_thread_pool.h
Normal 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
|
@ -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
57
core/loops/poller.h
Normal 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
|
@ -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
|
||||
|
61
core/loops/poller/epoll_poller.h
Normal file
61
core/loops/poller/epoll_poller.h
Normal 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
|
@ -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 {
|
53
core/loops/poller/kqueue.h
Normal file
53
core/loops/poller/kqueue.h
Normal 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
|
@ -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
69
core/loops/timer.h
Normal 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
|
@ -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
79
core/loops/timer_queue.h
Normal 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
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "PipeliningTest.h"
|
||||
#include <trantor/net/EventLoop.h>
|
||||
#include "core/loops/event_loop.h"
|
||||
#include <atomic>
|
||||
|
||||
void PipeliningTest::asyncHandleHttpRequest(
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include "Connector.h"
|
||||
#include "Channel.h"
|
||||
#include "core/loops/channel.h"
|
||||
#include "core/net/socket.h"
|
||||
|
||||
using namespace trantor;
|
||||
|
@ -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>
|
||||
|
@ -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
|
@ -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>
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <trantor/net/EventLoopThread.h>
|
||||
#include "core/loops/event_loop_thread.h"
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
#include <future>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <trantor/net/EventLoopThread.h>
|
||||
#include "core/loops/event_loop_thread.h"
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
#include <future>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <trantor/net/EventLoop.h>
|
||||
#include "core/loops/event_loop.h"
|
||||
#include "core/log/logger.h"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <trantor/net/EventLoop.h>
|
||||
#include "core/loops/event_loop.h"
|
||||
#include "core/log/logger.h"
|
||||
#include <iostream>
|
||||
int main()
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user