Repository: voidccc/mini-muduo
Branch: master
Commit: f2d743b8ddc8
Files: 40
Total size: 36.1 KB
Directory structure:
gitextract_jb13i3cx/
├── Acceptor.cc
├── Acceptor.h
├── BlockingQueue.h
├── Buffer.cc
├── Buffer.h
├── Channel.cc
├── Channel.h
├── Condition.h
├── CurrentThread.h
├── Declear.h
├── Define.h
├── EchoServer.cc
├── EchoServer.h
├── Epoll.cc
├── Epoll.h
├── EventLoop.cc
├── EventLoop.h
├── IAcceptorCallback.h
├── IChannelCallback.h
├── IMuduoUser.h
├── IRun.h
├── Makefile
├── Mutex.h
├── README.md
├── Task.cc
├── Task.h
├── TcpConnection.cc
├── TcpConnection.h
├── TcpServer.cc
├── TcpServer.h
├── Thread.cc
├── Thread.h
├── ThreadPool.cc
├── ThreadPool.h
├── Timer.h
├── TimerQueue.cc
├── TimerQueue.h
├── Timestamp.cc
├── Timestamp.h
└── main.cc
================================================
FILE CONTENTS
================================================
================================================
FILE: Acceptor.cc
================================================
//author voidccc
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include "Acceptor.h"
#include "Channel.h"
#include "IAcceptorCallback.h"
#include "EventLoop.h"
#include <iostream>
using namespace std;
Acceptor::Acceptor(EventLoop* pLoop)
:_listenfd(-1)
,_pSocketAChannel(NULL)
,_pCallback(NULL)
,_pLoop(pLoop)
{}
Acceptor::~Acceptor()
{}
void Acceptor::start()
{
_listenfd = createAndListen();
_pSocketAChannel = new Channel(_pLoop, _listenfd); // Memory Leak !!!
_pSocketAChannel->setCallback(this);
_pSocketAChannel->enableReading();
}
int Acceptor::createAndListen()
{
int on = 1;
_listenfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in servaddr;
fcntl(_listenfd, F_SETFL, O_NONBLOCK); //no-block io
setsockopt(_listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(11111);
if(-1 == bind(_listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))
{
cout << "bind error, errno:" << errno << endl;
}
if(-1 == listen(_listenfd, MAX_LISTENFD))
{
cout << "listen error, errno:" << errno << endl;
}
return _listenfd;
}
void Acceptor::handleRead()
{
int connfd;
struct sockaddr_in cliaddr;
socklen_t clilen = sizeof(struct sockaddr_in);
connfd = accept(_listenfd, (sockaddr*)&cliaddr, (socklen_t*)&clilen);
if(connfd > 0)
{
cout << "new connection from "
<< "[" << inet_ntoa(cliaddr.sin_addr)
<< ":" << ntohs(cliaddr.sin_port) << "]"
<< " new socket fd:" << connfd
<< endl;
}
else
{
cout << "accept error, connfd:" << connfd
<< " errno:" << errno << endl;
}
fcntl(connfd, F_SETFL, O_NONBLOCK); //no-block io
_pCallback->newConnection(connfd);
}
void Acceptor::handleWrite()
{
}
void Acceptor::setCallback(IAcceptorCallback* pCallback)
{
_pCallback = pCallback;
}
================================================
FILE: Acceptor.h
================================================
//author voidccc
#ifndef ACCEPTOR_H
#define ACCEPTOR_H
#include "Declear.h"
#include "Define.h"
#include "IChannelCallback.h"
class Acceptor : public IChannelCallback
{
public:
Acceptor(EventLoop* pLoop);
~Acceptor();
void start();
void setCallback(IAcceptorCallback* pCallback);
virtual void handleRead();
virtual void handleWrite();
private:
int createAndListen();
int _listenfd;
Channel* _pSocketAChannel;
IAcceptorCallback* _pCallback;
EventLoop* _pLoop;
};
#endif
================================================
FILE: BlockingQueue.h
================================================
//author voidccc
#ifndef BLOCKINGQUEUE_H
#define BLOCKINGQUEUE_H
#include <deque>
#include "Condition.h"
#include "Mutex.h"
using namespace std;
template<class T>
class BlockingQueue
{
public:
BlockingQueue()
:_cond(_mutex)
{}
void put(const T& one)
{
MutexLockGuard lock(_mutex);
_queue.push_back(one);
_cond.notify();
}
T take()
{
MutexLockGuard lock(_mutex);
while(_queue.empty())
{
_cond.wait();
}
T front(_queue.front());
_queue.pop_front();
return front;
}
private:
deque<T> _queue;
MutexLock _mutex;
Condition _cond;
};
#endif
================================================
FILE: Buffer.cc
================================================
//author voidccc
#include "Buffer.h"
Buffer::Buffer()
{}
Buffer::~Buffer()
{}
const char* Buffer::peek()
{
return _buf.c_str();
}
int Buffer::readableBytes()
{
return static_cast<int>(_buf.size());
}
void Buffer::retrieve(int len)
{
_buf = _buf.substr(len, _buf.size());
}
void Buffer::append(const string& data)
{
_buf.append(data);
}
string Buffer::retrieveAllAsString()
{
return retrieveAsString(readableBytes());
}
string Buffer::retrieveAsString(size_t len)
{
string result(peek(), len);
retrieve(len);
return result;
}
================================================
FILE: Buffer.h
================================================
//author voidccc
#ifndef BUFFER_H
#define BUFFER_H
#include <string>
using namespace std;
class Buffer
{
public:
Buffer();
~Buffer();
const char* peek();
int readableBytes();
void retrieve(int len);
void append(const string& buf);
string retrieveAllAsString();
string retrieveAsString(size_t len);
private:
string _buf;
};
#endif
================================================
FILE: Channel.cc
================================================
//author voidccc
#include <sys/epoll.h>
#include "Channel.h"
#include "IChannelCallback.h"
#include "EventLoop.h"
#include <iostream>
using namespace std;
Channel::Channel(EventLoop* pLoop, int sockfd)
:_sockfd(sockfd)
,_events(0)
,_revents(0)
,_index(-1)
,_pCallback(NULL)
,_pLoop(pLoop)
{
}
void Channel::setCallback(IChannelCallback* pCallback)
{
_pCallback = pCallback;
}
void Channel::setRevents(int revents)
{
_revents = revents;
}
void Channel::setIndex(int index)
{
_index = index;
}
void Channel::handleEvent()
{
if(_revents & EPOLLIN)
{
_pCallback->handleRead();
}
if(_revents & EPOLLOUT)
{
_pCallback->handleWrite();
}
}
void Channel::enableReading()
{
_events |= EPOLLIN;
update();
}
void Channel::enableWriting()
{
_events |= EPOLLOUT;
update();
}
void Channel::disableWriting()
{
_events &= ~EPOLLOUT;
update();
}
bool Channel::isWriting()
{
return _events & EPOLLOUT;
}
void Channel::update()
{
_pLoop->update(this);
}
int Channel::getEvents()
{
return _events;
}
int Channel::getfd()
{
return _sockfd;
}
int Channel::getIndex()
{
return _index;
}
================================================
FILE: Channel.h
================================================
//author voidccc
#ifndef CHANNEL_H
#define CHANNEL_H
#include "Declear.h"
class Channel
{
public:
Channel(EventLoop* pLoop, int sockfd);
~Channel();
void setCallback(IChannelCallback* pCallback);
void handleEvent();
void setRevents(int revent);
void setIndex(int index);
void enableReading();
void enableWriting();
void disableWriting();
bool isWriting();
int getEvents();
int getfd();
int getIndex();
private:
void update();
int _sockfd;
int _events;
int _revents;
int _index;
IChannelCallback* _pCallback;
EventLoop* _pLoop;
};
#endif
================================================
FILE: Condition.h
================================================
//author voidccc
#ifndef CONDITION_H
#define CONDITION_H
#include <pthread.h>
#include "Mutex.h"
class Condition
{
public:
Condition(MutexLock& mutex)
:_mutex(mutex)
{
pthread_cond_init(&_condid, NULL);
}
~Condition()
{
pthread_cond_destroy(&_condid);
}
void wait()
{
pthread_cond_wait(&_condid, _mutex.getPthreadMutex());
}
void notify()
{
pthread_cond_signal(&_condid);
}
void notifyAll()
{
pthread_cond_broadcast(&_condid);
}
private:
MutexLock& _mutex;
pthread_cond_t _condid;
};
#endif
================================================
FILE: CurrentThread.h
================================================
//author voidccc
#ifndef CURRENTTHREAD_H
#define CURRENTTHREAD_H
#include <unistd.h>
#include <sys/syscall.h>
namespace CurrentThread
{
extern __thread int t_cachedTid;
inline void cacheTid()
{
t_cachedTid = static_cast<int>(::syscall(SYS_gettid));
}
inline int tid()
{
if(t_cachedTid == 0)
{
cacheTid();
}
return t_cachedTid;
}
}
#endif
================================================
FILE: Declear.h
================================================
//author voidccc
#ifndef DECLEAR_H
#define DECLEAR_H
class IChannelCallback;
class IAcceptorCallback;
class Channel;
class Acceptor;
class TcpConnection;
class EventLoop;
class Epoll;
class IMuduoUser;
class Buffer;
class TimerQueue;
class Timestamp;
class IRun0;
class IRun2;
class Timer;
class Task;
class Thread;
class ThreadPool;
#endif
================================================
FILE: Define.h
================================================
//author voidccc
#ifndef DEFINE_H
#define DEFINE_H
#define MAX_LINE 100
#define MAX_EVENTS 500
#define MAX_LISTENFD 5
#endif
================================================
FILE: EchoServer.cc
================================================
//author voidccc
#include "EchoServer.h"
#include "TcpConnection.h"
#include "EventLoop.h"
#include "CurrentThread.h"
#include "Task.h"
#include <iostream>
#define MESSAGE_LENGTH 8
EchoServer::EchoServer(EventLoop* pLoop)
:_pLoop(pLoop)
,_pServer(pLoop)
,_timer(-1)
,_index(0)
{
_pServer.setCallback(this);
}
EchoServer::~EchoServer()
{}
void EchoServer::start()
{
_pServer.start();
_threadpool.start(3);
}
void EchoServer::onConnection(TcpConnection* pCon)
{
cout << "onConnection" << endl;
}
void EchoServer::onMessage(TcpConnection* pCon, Buffer* pBuf)
{
while(pBuf->readableBytes() > MESSAGE_LENGTH)
{
string message = pBuf->retrieveAsString(MESSAGE_LENGTH);
Task task(this, message, pCon);
_threadpool.addTask(task);
}
}
void EchoServer::onWriteComplate(TcpConnection* pCon)
{
cout << "onWriteComplate" << endl;
}
//run in different therad
void EchoServer::run2(const string& str, void* tcp)
{
//IO blocking task or CPU busy task
cout << "fib(30) = " << fib(30) << " tid = " << CurrentThread::tid() << endl;
((TcpConnection*)tcp)->send(str + "\n");
}
//fib is short for Fibonacci, fib is a CPU busy method
int EchoServer::fib(int n)
{
return (n == 1 || n == 2) ? 1 : (fib(n-1) + fib(n-2));
}
================================================
FILE: EchoServer.h
================================================
//author voidccc
#ifndef ECHOSERVER_H
#define ECHOSERVER_H
#include "IMuduoUser.h"
#include "IRun.h"
#include "TcpServer.h"
#include "ThreadPool.h"
class EchoServer : public IMuduoUser
, public IRun2
{
public:
EchoServer(EventLoop* pLoop);
~EchoServer();
void start();
virtual void onConnection(TcpConnection* pCon);
virtual void onMessage(TcpConnection* pCon, Buffer* pBuf);
virtual void onWriteComplate(TcpConnection* pCon);
virtual void run2(const string& str, void* tcp);
private:
int fib(int n);
EventLoop* _pLoop;
TcpServer _pServer;
ThreadPool _threadpool;
int _timer;
int _index;
};
#endif
================================================
FILE: Epoll.cc
================================================
//author voidccc
#include <errno.h>
#include "Epoll.h"
#include "Channel.h"
#include "Define.h"
#include <iostream>
using namespace std;
const int kNew = -1;
const int kAdded = 1;
Epoll::Epoll()
{
_epollfd = ::epoll_create(1);
if (_epollfd <= 0)
cout << "epoll_create error, errno:" << _epollfd << endl;
}
Epoll::~Epoll()
{}
void Epoll::poll(vector<Channel*>* pChannels)
{
int fds = ::epoll_wait(_epollfd, _events, MAX_EVENTS, -1);
if(fds == -1)
{
cout << "epoll_wait error, errno:" << errno << endl;
return;
}
for(int i = 0; i < fds; i++)
{
Channel* pChannel = static_cast<Channel*>(_events[i].data.ptr);
pChannel->setRevents(_events[i].events);
pChannels->push_back(pChannel);
}
}
void Epoll::update(Channel* pChannel)
{
int index = pChannel->getIndex();
if(index == kNew)
{
struct epoll_event ev;
ev.data.ptr = pChannel;
ev.events = pChannel->getEvents();
int fd = pChannel->getfd();
pChannel->setIndex(kAdded);
::epoll_ctl(_epollfd, EPOLL_CTL_ADD, fd, &ev);
}
else
{
struct epoll_event ev;
ev.data.ptr = pChannel;
ev.events = pChannel->getEvents();
int fd = pChannel->getfd();
::epoll_ctl(_epollfd, EPOLL_CTL_MOD, fd, &ev);
}
}
================================================
FILE: Epoll.h
================================================
//author voidccc
#ifndef EPOLL_H
#define EPOLL_H
#include <sys/epoll.h>
#include "Declear.h"
#include "Define.h"
#include <vector>
using namespace std;
class Epoll
{
public:
Epoll();
~Epoll();
void poll(vector<Channel*>* pChannels);
void update(Channel* pChannel);
private:
int _epollfd;
struct epoll_event _events[MAX_EVENTS];
};
#endif
================================================
FILE: EventLoop.cc
================================================
//author voidccc
#include <sys/eventfd.h>
#include "EventLoop.h"
#include "Channel.h"
#include "Epoll.h"
#include "TimerQueue.h"
#include "Timestamp.h"
#include "Task.h"
#include "CurrentThread.h"
#include <iostream>
using namespace std;
EventLoop::EventLoop()
:_quit(false)
,_callingPendingFunctors(false)
,_pPoller(new Epoll()) // Memory Leak !!!
,_threadId(CurrentThread::tid())
,_pTimerQueue(new TimerQueue(this)) // Memory Leak!!!
{
_eventfd = createEventfd();
_pEventfdChannel = new Channel(this, _eventfd); // Memory Leak !!!
_pEventfdChannel->setCallback(this);
_pEventfdChannel->enableReading();
}
EventLoop::~EventLoop()
{}
void EventLoop::loop()
{
while(!_quit)
{
vector<Channel*> channels;
_pPoller->poll(&channels);
vector<Channel*>::iterator it;
for(it = channels.begin(); it != channels.end(); ++it)
{
(*it)->handleEvent();
}
doPendingFunctors();
}
}
void EventLoop::update(Channel* pChannel)
{
_pPoller->update(pChannel);
}
void EventLoop::queueInLoop(Task& task)
{
{
MutexLockGuard guard(_mutex);
_pendingFunctors.push_back(task);
}
if(!isInLoopThread() || _callingPendingFunctors)
{
wakeup();
}
}
void EventLoop::runInLoop(Task& task)
{
if(isInLoopThread())
{
task.doTask();
}
else
{
queueInLoop(task);
}
}
void EventLoop::wakeup()
{
uint64_t one = 1;
ssize_t n = ::write(_eventfd, &one, sizeof one);
if (n != sizeof one)
{
cout << "EventLoop::wakeup() writes " << n << " bytes instead of 8" << endl;
}
}
int EventLoop::createEventfd()
{
int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if (evtfd < 0)
{
cout << "Failed in eventfd" << endl;
}
return evtfd;
}
void EventLoop::handleRead()
{
uint64_t one = 1;
ssize_t n = ::read(_eventfd, &one, sizeof one);
if (n != sizeof one)
{
cout << "EventEventLoop::handleRead() reads " << n << " bytes instead of 8" << endl;
}
}
void EventLoop::handleWrite()
{}
void EventLoop::doPendingFunctors()
{
vector<Task> tempRuns;
_callingPendingFunctors = true;
{
MutexLockGuard guard(_mutex);
tempRuns.swap(_pendingFunctors);
}
vector<Task>::iterator it;
for(it = tempRuns.begin(); it != tempRuns.end(); ++it)
{
it->doTask();
}
_callingPendingFunctors = false;
}
int EventLoop::runAt(Timestamp when, IRun0* pRun)
{
return _pTimerQueue->addTimer(pRun, when, 0.0);
}
int EventLoop::runAfter(double delay, IRun0* pRun)
{
return _pTimerQueue->addTimer(pRun, Timestamp::nowAfter(delay), 0.0);
}
int EventLoop::runEvery(double interval, IRun0* pRun)
{
return _pTimerQueue->addTimer(pRun, Timestamp::nowAfter(interval), interval);
}
void EventLoop::cancelTimer(int timerId)
{
_pTimerQueue->cancelTimer(timerId);
}
bool EventLoop::isInLoopThread()
{
return _threadId == CurrentThread::tid();
}
================================================
FILE: EventLoop.h
================================================
//author voidccc
#ifndef EVENTLOOP_H
#define EVENTLOOP_H
#include "Declear.h"
#include "IChannelCallback.h"
#include "Task.h"
#include "Mutex.h"
#include <vector>
using namespace std;
class EventLoop : public IChannelCallback
{
public:
EventLoop();
~EventLoop();
void loop();
void update(Channel* pChannel);
void queueInLoop(Task& task);
void runInLoop(Task& task);
int runAt(Timestamp when, IRun0* pRun);
int runAfter(double delay, IRun0* pRun);
int runEvery(double interval, IRun0* pRun);
void cancelTimer(int timerfd);
bool isInLoopThread();
virtual void handleRead();
virtual void handleWrite();
private:
void wakeup();
int createEventfd();
void doPendingFunctors();
bool _quit;
bool _callingPendingFunctors;
Epoll* _pPoller;
int _eventfd;
const pid_t _threadId;
Channel* _pEventfdChannel;
MutexLock _mutex;
vector<Task> _pendingFunctors;
TimerQueue* _pTimerQueue;
};
#endif
================================================
FILE: IAcceptorCallback.h
================================================
//author voidccc
#ifndef IACCEPTORCALLBACK_H
#define IACCEPTORCALLBACK_H
class IAcceptorCallback
{
public:
virtual void newConnection(int sockfd) = 0;
};
#endif
================================================
FILE: IChannelCallback.h
================================================
//author voidccc
#ifndef ICHANNELCALLBACK_H
#define ICHANNELCALLBACK_H
class IChannelCallback
{
public:
virtual void handleRead() = 0;
virtual void handleWrite() = 0;
};
#endif
================================================
FILE: IMuduoUser.h
================================================
//author voidccc
#ifndef IMUDUOUSER_H
#define IMUDUOUSER_H
#include "Declear.h"
#include <string>
using namespace std;
class IMuduoUser
{
public:
virtual void onConnection(TcpConnection* pCon) = 0;
virtual void onMessage(TcpConnection* pCon, Buffer* pBuf) = 0;
virtual void onWriteComplate(TcpConnection* pCon) = 0;
};
#endif
================================================
FILE: IRun.h
================================================
//author voidccc
#ifndef IRUN_H
#define IRUN_H
#include <string>
using namespace std;
class IRun0
{
public:
virtual void run0() = 0;
};
class IRun2
{
public:
virtual void run2(const string& str, void* param) = 0;
};
#endif
================================================
FILE: Makefile
================================================
#####################################
# Copyright (c) 1997 George Foot (george.foot@merton.ox.ac.uk)
# # All rights reserved.
# ######################################
# #目标(可执行文档)名称,库(譬如stdcx,iostr,mysql等),头文件路径
DESTINATION := mini-muduo
LIBS := pthread
INCLUDES := .
RM := rm -f
#C,CC或CPP文件的后缀
PS=cc
# GNU Make的隐含变量定义
CC=g++
CPPFLAGS = -g -Wall -O3 -march=native
CPPFLAGS += $(addprefix -I,$(INCLUDES))
CPPFLAGS += -MMD
#以下部分无需修改
SOURCE := $(wildcard *.$(PS))
OBJS := $(patsubst %.$(PS),%.o,$(SOURCE))
DEPS := $(patsubst %.o,%.d,$(OBJS))
MISSING_DEPS := $(filter-out $(wildcard $(DEPS)),$(DEPS))
MISSING_DEPS_SOURCES := $(wildcard $(patsubst %.d,%.$(PS),$(MISSING_DEPS)))
.PHONY : all deps objs clean rebuild
all : $(DESTINATION)
deps : $(DEPS)
$(CC) -MM -MMD $(SOURCE)
objs : $(OBJS)
clean :
@$(RM) *.o
@$(RM) *.d
@$(RM) $(DESTINATION)
rebuild: clean all
ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS) :
@$(RM) $(patsubst %.d,%.o,$@)
endif
-include $(DEPS)
$(DESTINATION) : $(OBJS)
$(CC) -o $(DESTINATION) $(OBJS) $(addprefix -l,$(LIBS))
#结束
================================================
FILE: Mutex.h
================================================
//author voidccc
#ifndef MUTEX_H
#define MUTEX_H
#include <pthread.h>
class MutexLock
{
public:
MutexLock()
{
pthread_mutex_init(&_mutexid, NULL);
}
~MutexLock()
{
pthread_mutex_destroy(&_mutexid);
}
void lock()
{
pthread_mutex_lock(&_mutexid);
}
void unlock()
{
pthread_mutex_unlock(&_mutexid);
}
pthread_mutex_t* getPthreadMutex()
{
return &_mutexid;
}
private:
pthread_mutex_t _mutexid;
};
class MutexLockGuard
{
public:
MutexLockGuard(MutexLock& mutex)
:_mutex(mutex)
{
_mutex.lock();
}
~MutexLockGuard()
{
_mutex.unlock();
}
private:
MutexLock& _mutex;
};
#endif
================================================
FILE: README.md
================================================
mini-muduo
==========
a mini implementation of muduo
tags:
v0.01
1 epoll example
v0.02
1 Add TcpServer, TcpServer is the first object in code.
v0.03
1 Add Channel, Channel is the observer of socket fd.
2 Add IChannelCallback, move event handler from epoll loop to a callback function in TcpServer.
v0.04
1 Add Acceptor, Acceptor is the observer of listening socket fd.
2 Add TcpConnection, TcpConnection is the observer of read/write socket fd.
v0.05
1 Add EventLoop, EventLoop is the wrapper of "for" loop.
2 Add Epoll, Epoll is the wrapper of epoll file descriptor.
v0.06
1 Add EchoServer, EchoServer is the user of mini-muduo library.
v0.07
1 Add input/output buffer.
v0.08
1 Add input/output buffer.(Buffer and onWriteComplate)
v0.09
1 Add Timer.
v0.10
1 Better naming convention
v0.11
1 remove muti-thread specific code
2 32-bit/64-bit support
v0.12
1 Foundations of multi-thread
================================================
FILE: Task.cc
================================================
#include "Task.h"
#include "IRun.h"
Task::Task(IRun0* func)
:_func0(func)
,_func2(NULL)
,_param(NULL)
{
}
Task::Task(IRun2* func, const string& str, void* param)
:_func0(NULL)
,_func2(func)
,_str(str)
,_param(param)
{
}
void Task::doTask()
{
if(_func0) {
_func0->run0();
} else {
_func2->run2(_str, _param);
}
}
================================================
FILE: Task.h
================================================
//author voidccc
#ifndef TASK_H
#define TASK_H
#include "Declear.h"
#include <string>
class Task
{
public:
Task(IRun0* func);
Task(IRun2* func, const std::string& str, void* param);
void doTask();
private:
IRun0* _func0;
IRun2* _func2;
std::string _str;
void* _param;
};
#endif
================================================
FILE: TcpConnection.cc
================================================
//author voidccc
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "TcpConnection.h"
#include "Channel.h"
#include "EventLoop.h"
#include "Define.h"
#include "IMuduoUser.h"
#include "Task.h"
#include <string.h> //for bzero
#include <iostream>
using namespace std;
TcpConnection::TcpConnection(int sockfd, EventLoop* pLoop)
:_sockfd(sockfd)
,_pLoop(pLoop)
,_pUser(NULL)
{
_pSocketChannel = new Channel(_pLoop, _sockfd); // Memory Leak !!!
_pSocketChannel->setCallback(this);
_pSocketChannel->enableReading();
}
TcpConnection::~TcpConnection()
{}
void TcpConnection::handleRead()
{
int sockfd = _pSocketChannel->getfd();
int readlength;
char line[MAX_LINE];
if(sockfd < 0)
{
cout << "EPOLLIN sockfd < 0 error " << endl;
return;
}
bzero(line, MAX_LINE);
if((readlength = read(sockfd, line, MAX_LINE)) < 0)
{
if(errno == ECONNRESET)
{
cout << "ECONNREST closed socket fd:" << sockfd << endl;
close(sockfd);
}
}
else if(readlength == 0)
{
cout << "read 0 closed socket fd:" << sockfd << endl;
close(sockfd);
}
else
{
string linestr(line, readlength);
_inBuf.append(linestr);
_pUser->onMessage(this, &_inBuf);
}
}
void TcpConnection::handleWrite()
{
int sockfd = _pSocketChannel->getfd();
if(_pSocketChannel->isWriting())
{
int n = ::write(sockfd, _outBuf.peek(), _outBuf.readableBytes());
if( n > 0)
{
cout << "write " << n << " bytes data again" << endl;
_outBuf.retrieve(n);
if(_outBuf.readableBytes() == 0)
{
_pSocketChannel->disableWriting(); //remove EPOLLOUT
Task task(this);
_pLoop->queueInLoop(task); //invoke onWriteComplate
}
}
}
}
void TcpConnection::send(const string& message)
{
if(_pLoop->isInLoopThread())
{
sendInLoop(message);
}
else
{
Task task(this, message, this);
_pLoop->runInLoop(task);
}
}
void TcpConnection::sendInLoop(const string& message)
{
int n = 0;
if(_outBuf.readableBytes() == 0)
{
n = ::write(_sockfd, message.c_str(), message.size());
if(n < 0)
cout << "write error" << endl;
if(n == static_cast<int>(message.size()))
{
Task task(this);
_pLoop->queueInLoop(task); //invoke onWriteComplate
}
}
if( n < static_cast<int>(message.size()))
{
_outBuf.append(message.substr(n, message.size()));
if(!_pSocketChannel->isWriting())
{
_pSocketChannel->enableWriting(); //add EPOLLOUT
}
}
}
void TcpConnection::connectEstablished()
{
if(_pUser)
_pUser->onConnection(this);
}
void TcpConnection::setUser(IMuduoUser* user)
{
_pUser = user;
}
void TcpConnection::run0()
{
_pUser->onWriteComplate(this);
}
void TcpConnection::run2(const string& message, void* param)
{
sendInLoop(message);
}
================================================
FILE: TcpConnection.h
================================================
//author voidccc
#ifndef TCPCONNECTION_H
#define TCPCONNECTION_H
#include "Declear.h"
#include "IChannelCallback.h"
#include "Buffer.h"
#include "IRun.h"
#include <string>
using namespace std;
class TcpConnection : public IChannelCallback
, public IRun0
, public IRun2
{
public:
TcpConnection(int sockfd, EventLoop* pLoop);
~TcpConnection();
void send(const string& message);
void sendInLoop(const string& message);
void connectEstablished();
void setUser(IMuduoUser* pUser);
void setCallback(IAcceptorCallback* pCallback);
virtual void handleRead();
virtual void handleWrite();
virtual void run0();
virtual void run2(const string& message, void* param);
private:
int _sockfd;
Channel* _pSocketChannel;
EventLoop* _pLoop;
IMuduoUser* _pUser;
Buffer _inBuf;
Buffer _outBuf;
};
#endif
================================================
FILE: TcpServer.cc
================================================
//author voidccc
#include <errno.h>
#include "TcpServer.h"
#include "Channel.h"
#include "Acceptor.h"
#include "TcpConnection.h"
#include <vector>
TcpServer::TcpServer(EventLoop* pLoop)
:_pAcceptor(NULL)
,_pLoop(pLoop)
,_pUser(NULL)
{
}
TcpServer::~TcpServer()
{
}
void TcpServer::start()
{
_pAcceptor = new Acceptor(_pLoop); // Memory Leak !!!
_pAcceptor->setCallback(this);
_pAcceptor->start();
}
void TcpServer::newConnection(int sockfd)
{
TcpConnection* tcp = new TcpConnection(sockfd, _pLoop); // Memory Leak !!!
_connections[sockfd] = tcp;
tcp->setUser(_pUser);
tcp->connectEstablished();
}
void TcpServer::setCallback(IMuduoUser* user)
{
_pUser = user;
}
================================================
FILE: TcpServer.h
================================================
//author voidccc
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <sys/epoll.h>
#include "Declear.h"
#include "Define.h"
#include "IAcceptorCallback.h"
#include "IMuduoUser.h"
#include <map>
using namespace std;
class TcpServer : public IAcceptorCallback
{
public:
TcpServer(EventLoop* pLoop);
~TcpServer();
void start();
void setCallback(IMuduoUser* pUser);
virtual void newConnection(int sockfd);
private:
struct epoll_event _events[MAX_EVENTS];
map<int, TcpConnection*> _connections;
Acceptor* _pAcceptor;
EventLoop* _pLoop;
IMuduoUser* _pUser;
};
#endif
================================================
FILE: Thread.cc
================================================
//author voidccc
#include "Thread.h"
#include <unistd.h>
#include <sys/syscall.h>
#include <pthread.h>
namespace CurrentThread
{
__thread int t_cachedTid = 0;
}
void* globalRun(void* arg)
{
((Task*)arg)->doTask();
return 0;
}
Thread::Thread(Task& task)
:_task(task)
{ }
void Thread::start()
{
pthread_t t;
::pthread_create(&t, NULL, globalRun, &_task);
}
pid_t Thread::gettid()
{
return static_cast<pid_t>(::syscall(SYS_gettid));
}
================================================
FILE: Thread.h
================================================
//author voidccc
#ifndef THREAD_H
#define THREAD_H
#include "Declear.h"
#include "Task.h"
class Thread
{
public:
Thread(Task& task);
void start();
pid_t gettid();
private:
Task _task;
};
#endif
================================================
FILE: ThreadPool.cc
================================================
//author voidccc
#include "ThreadPool.h"
#include "Thread.h"
ThreadPool::ThreadPool() { }
void ThreadPool::start(int numThreads)
{
_threads.reserve(numThreads);
for(int i = 0 ; i < numThreads; i++)
{
Task task(this);
Thread* p = new Thread(task);
_threads.push_back(p);
p->start();
}
}
//virtual for Thread
void ThreadPool::addTask(Task& task)
{
_tasks.put(task);
}
//virtual for Thread class
void ThreadPool::run0()
{
runInThread();
}
void ThreadPool::runInThread()
{
while(true)
{
_tasks.take().doTask();
}
}
================================================
FILE: ThreadPool.h
================================================
//author voidccc
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include "Declear.h"
#include "BlockingQueue.h"
#include "Task.h"
#include "IRun.h"
#include <vector>
using namespace std;
class ThreadPool : public IRun0
{
public:
ThreadPool();
void start(int numThreads);
void addTask(Task& task);
virtual void run0();
private:
void runInThread();
BlockingQueue<Task> _tasks;
vector<Thread*> _threads;
};
#endif
================================================
FILE: Timer.h
================================================
#ifndef TIMER_H
#define TIMER_H
#include "Declear.h"
#include "IRun.h"
class Timer
{
public:
Timer(Timestamp stamp, IRun0* pRun, double interval)
:_stamp(stamp)
,_id(stamp)
,_pRun0(pRun)
,_interval(interval)
{}
Timestamp getStamp()
{
return _stamp;
}
Timestamp getId()
{
return _id;
}
void timeout()
{
_pRun0->run0();
}
bool isRepeat()
{
return _interval > 0.0;
}
void moveToNext()
{
_stamp = Timestamp::nowAfter(_interval);
}
private:
Timestamp _stamp;
Timestamp _id;
IRun0* _pRun0;
double _interval;//seconds
};
#endif
================================================
FILE: TimerQueue.cc
================================================
//author voidccc
#include <sys/timerfd.h>
#include <inttypes.h>
#include <stdio.h>
#include <strings.h>
#include "TimerQueue.h"
#include "Channel.h"
#include "EventLoop.h"
#include "Timestamp.h"
#include "Timer.h"
#include "Task.h"
#include <iostream>
#include <string>
using namespace std;
#define UINTPTR_MAX 0xffffffff
TimerQueue::TimerQueue(EventLoop *pLoop)
:_timerfd(createTimerfd())
,_pLoop(pLoop)
,_pTimerfdChannel(new Channel(_pLoop, _timerfd)) // Memory Leak !!!
{
_pTimerfdChannel->setCallback(this);
_pTimerfdChannel->enableReading();
}
TimerQueue::~TimerQueue()
{
::close(_timerfd);
}
void TimerQueue::run2(const string& str, void* timer)
{
if(str == "addtimer")
{
doAddTimer((Timer*)timer);
}
else if(str == "canceltimer")
{
doCancelTimer((Timer*)timer);
}
else { }
}
void TimerQueue::doAddTimer(Timer* pTimer)
{
bool earliestChanged = insert(pTimer);
if(earliestChanged)
{
resetTimerfd(_timerfd, pTimer->getStamp());
}
}
void TimerQueue::doCancelTimer(Timer* pTimer)
{
Entry e(pTimer->getId(), pTimer);
TimerList::iterator it;
for(it = _pTimers.begin(); it != _pTimers.end(); ++it)
{
if(it->second == pTimer)
{
_pTimers.erase(it);
break;
}
}
}
///////////////////////////////////////
/// Add a timer to the system
/// @param pRun: callback interface
/// @param when: time
/// @param interval:
/// 0 = happen only once, no repeat
/// n = happen after the first time every n seconds
/// @return the process unique id of the timer
long TimerQueue::addTimer(IRun0* pRun, Timestamp when, double interval)
{
Timer* pAddTimer = new Timer(when, pRun, interval); //Memory Leak !!!
string str("addTimer");
Task task(this, str, pAddTimer);
_pLoop->queueInLoop(task);
return (long)(pAddTimer);
}
void TimerQueue::cancelTimer(long timerId)
{
Timer* pCancel = (Timer*)(timerId);
string str("canceltimer");
Task task(this, str, pCancel);
_pLoop->queueInLoop(task);
}
void TimerQueue::handleRead()
{
Timestamp now(Timestamp::now());
readTimerfd(_timerfd, now);
vector<Entry> expired = getExpired(now);
vector<Entry>::iterator it;
for(it = expired.begin(); it != expired.end(); ++it)
{
it->second->timeout();
}
reset(expired, now);
}
void TimerQueue::handleWrite()
{}
int TimerQueue::createTimerfd()
{
int timerfd = ::timerfd_create(CLOCK_MONOTONIC,
TFD_NONBLOCK | TFD_CLOEXEC);
if(timerfd < 0)
{
cout << "failed in timerfd_create" << endl;
}
return timerfd;
}
std::vector<TimerQueue::Entry> TimerQueue::getExpired(Timestamp now)
{
std::vector<Entry> expired;
Entry sentry(now, reinterpret_cast<Timer*>(UINTPTR_MAX));
TimerList::iterator end = _pTimers.lower_bound(sentry);
copy(_pTimers.begin(), end, back_inserter(expired));
_pTimers.erase(_pTimers.begin(), end);
return expired;
}
void TimerQueue::readTimerfd(int timerfd, Timestamp now)
{
uint64_t howmany;
ssize_t n = ::read(timerfd, &howmany, sizeof(howmany));
if (n != sizeof(howmany))
{
cout << "Timer::readTimerfd() error " << endl;
}
}
void TimerQueue::reset(const vector<Entry>& expired, Timestamp now)
{
vector<Entry>::const_iterator it;
for(it = expired.begin(); it != expired.end(); ++it)
{
if(it->second->isRepeat())
{
it->second->moveToNext();
insert(it->second);
}
}
Timestamp nextExpire;
if(!_pTimers.empty())
{
nextExpire = _pTimers.begin()->second->getStamp();
}
if(nextExpire.valid())
{
resetTimerfd(_timerfd, nextExpire);
}
}
void TimerQueue::resetTimerfd(int timerfd, Timestamp stamp)
{
struct itimerspec newValue;
struct itimerspec oldValue;
bzero(&newValue, sizeof(newValue));
bzero(&oldValue, sizeof(oldValue));
newValue.it_value = howMuchTimeFromNow(stamp);
int ret = ::timerfd_settime(timerfd, 0, &newValue, &oldValue);
if(ret)
{
cout << "timerfd_settime error" << endl;
}
}
bool TimerQueue::insert(Timer* pTimer)
{
bool earliestChanged = false;
Timestamp when = pTimer->getStamp();
TimerList::iterator it = _pTimers.begin();
if(it == _pTimers.end() || when < it->first)
{
earliestChanged = true;
}
pair<TimerList::iterator, bool> result
= _pTimers.insert(Entry(when, pTimer));
if(!(result.second))
{
cout << "_pTimers.insert() error " << endl;
}
return earliestChanged;
}
struct timespec TimerQueue::howMuchTimeFromNow(Timestamp when)
{
int64_t microseconds = when.microSecondsSinceEpoch()
- Timestamp::now().microSecondsSinceEpoch();
if (microseconds < 100)
{
microseconds = 100;
}
struct timespec ts;
ts.tv_sec = static_cast<time_t>(
microseconds / Timestamp::kMicroSecondsPerSecond);
ts.tv_nsec = static_cast<long>(
(microseconds % Timestamp::kMicroSecondsPerSecond) * 1000);
return ts;
}
================================================
FILE: TimerQueue.h
================================================
// author voidccc
#ifndef TIMERQUEUE_H
#define TIMERQUEUE_H
#include "Declear.h"
#include "IChannelCallback.h"
#include "IRun.h"
#include "Timestamp.h"
#include <vector>
#include <set>
using namespace std;
class TimerQueue : public IChannelCallback
, public IRun2
{
public:
TimerQueue(EventLoop* pLoop);
~TimerQueue();
void doAddTimer(Timer* timer);
void doCancelTimer(Timer* timer);
long addTimer(IRun0* pRun,
Timestamp when,
double interval);
void cancelTimer(long timerId);
virtual void run2(const string& str, void* timer);
virtual void handleRead();
virtual void handleWrite();
private:
typedef std::pair<Timestamp, Timer*> Entry;
typedef std::set<Entry> TimerList;
int createTimerfd();
vector<TimerQueue::Entry> getExpired(Timestamp now);
void readTimerfd(int timerfd, Timestamp now);
void reset(const vector<Entry>& expired, Timestamp now);
void resetTimerfd(int timerfd, Timestamp stamp);
bool insert(Timer* pItem);
struct timespec howMuchTimeFromNow(Timestamp when);
int _timerfd;
TimerList _pTimers;
EventLoop* _pLoop;
Channel* _pTimerfdChannel;
};
#endif
================================================
FILE: Timestamp.cc
================================================
//author voidccc
#include <sys/time.h>
#include <stdio.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#undef __STDC_FORMAT_MACROS
#include "Timestamp.h"
#include <iostream>
Timestamp::Timestamp(double microSeconds)
:_microSecondsSinceEpoch(microSeconds)
{}
Timestamp::~Timestamp()
{}
bool Timestamp::valid()
{
return _microSecondsSinceEpoch > 0;
}
int64_t Timestamp::microSecondsSinceEpoch()
{
return _microSecondsSinceEpoch;
}
string Timestamp::toString() const
{
char buf[32] = {0};
int64_t seconds = _microSecondsSinceEpoch / kMicroSecondsPerSecond;
int64_t microseconds = _microSecondsSinceEpoch % kMicroSecondsPerSecond;
snprintf(buf, sizeof(buf)-1, "%" PRId64 ".%06" PRId64 "", seconds, microseconds);
return buf;
}
Timestamp Timestamp::now()
{
return Timestamp(Timestamp::nowMicroSeconds());
}
Timestamp Timestamp::nowAfter(double seconds)
{
return Timestamp(Timestamp::nowMicroSeconds() + kMicroSecondsPerSecond * seconds);
}
double Timestamp::nowMicroSeconds()
{
struct timeval tv;
gettimeofday(&tv, NULL);
int64_t seconds = tv.tv_sec;
return seconds * kMicroSecondsPerSecond + tv.tv_usec;
}
bool operator<(Timestamp l, Timestamp r)
{
return l.microSecondsSinceEpoch() < r.microSecondsSinceEpoch();
}
bool operator==(Timestamp l, Timestamp r)
{
cout << "operator ==" << endl;
return l.microSecondsSinceEpoch() == r.microSecondsSinceEpoch();
}
================================================
FILE: Timestamp.h
================================================
//author voidccc
#ifndef TIMESTAMP_H
#define TIMESTAMP_H
#include <sys/types.h>
#include <string>
using namespace std;
class Timestamp
{
public:
Timestamp(double microSeconds = 0.0);
~Timestamp();
bool valid();
int64_t microSecondsSinceEpoch();
string toString() const;
static Timestamp now();
static Timestamp nowAfter(double seconds);
static double nowMicroSeconds();
static const int kMicroSecondsPerSecond = 1000 * 1000;
private:
int64_t _microSecondsSinceEpoch;
};
bool operator <(Timestamp l, Timestamp r);
bool operator ==(Timestamp l, Timestamp r);
#endif
================================================
FILE: main.cc
================================================
//author voidccc
#include "TcpServer.h"
#include "EventLoop.h"
#include "EchoServer.h"
int main(int args, char** argv)
{
EventLoop loop;
EchoServer echoserver(&loop);
echoserver.start();
loop.loop();
return 0;
}
gitextract_jb13i3cx/ ├── Acceptor.cc ├── Acceptor.h ├── BlockingQueue.h ├── Buffer.cc ├── Buffer.h ├── Channel.cc ├── Channel.h ├── Condition.h ├── CurrentThread.h ├── Declear.h ├── Define.h ├── EchoServer.cc ├── EchoServer.h ├── Epoll.cc ├── Epoll.h ├── EventLoop.cc ├── EventLoop.h ├── IAcceptorCallback.h ├── IChannelCallback.h ├── IMuduoUser.h ├── IRun.h ├── Makefile ├── Mutex.h ├── README.md ├── Task.cc ├── Task.h ├── TcpConnection.cc ├── TcpConnection.h ├── TcpServer.cc ├── TcpServer.h ├── Thread.cc ├── Thread.h ├── ThreadPool.cc ├── ThreadPool.h ├── Timer.h ├── TimerQueue.cc ├── TimerQueue.h ├── Timestamp.cc ├── Timestamp.h └── main.cc
SYMBOL INDEX (46 symbols across 26 files) FILE: Acceptor.cc type sockaddr_in (line 37) | struct sockaddr_in type sockaddr (line 44) | struct sockaddr type sockaddr_in (line 59) | struct sockaddr_in type sockaddr_in (line 60) | struct sockaddr_in FILE: Acceptor.h function class (line 9) | class Acceptor : public IChannelCallback FILE: BlockingQueue.h function put (line 18) | void put(const T& one) function T (line 25) | T take() FILE: Buffer.cc function string (line 31) | string Buffer::retrieveAllAsString() function string (line 36) | string Buffer::retrieveAsString(size_t len) FILE: Buffer.h function class (line 8) | class Buffer FILE: Channel.h function class (line 7) | class Channel FILE: Condition.h function class (line 8) | class Condition FILE: CurrentThread.h function namespace (line 8) | namespace CurrentThread FILE: Epoll.cc type epoll_event (line 46) | struct epoll_event type epoll_event (line 55) | struct epoll_event FILE: Epoll.h function class (line 13) | class Epoll FILE: EventLoop.h function class (line 13) | class EventLoop : public IChannelCallback FILE: IAcceptorCallback.h function class (line 5) | class IAcceptorCallback FILE: IChannelCallback.h function class (line 5) | class IChannelCallback FILE: IMuduoUser.h function class (line 9) | class IMuduoUser FILE: IRun.h function class (line 9) | class IRun0 function class (line 15) | class IRun2 FILE: Mutex.h function class (line 7) | class MutexLock function class (line 35) | class MutexLockGuard FILE: Task.h function class (line 8) | class Task FILE: TcpServer.h function class (line 15) | class TcpServer : public IAcceptorCallback FILE: Thread.cc type CurrentThread (line 8) | namespace CurrentThread function pid_t (line 29) | pid_t Thread::gettid() FILE: Thread.h function class (line 8) | class Thread FILE: ThreadPool.h function class (line 13) | class ThreadPool : public IRun0 FILE: Timer.h function class (line 8) | class Timer function Timestamp (line 21) | Timestamp getId() function timeout (line 25) | void timeout() function isRepeat (line 30) | bool isRepeat() function moveToNext (line 35) | void moveToNext() FILE: TimerQueue.cc type itimerspec (line 170) | struct itimerspec type itimerspec (line 171) | struct itimerspec type timespec (line 201) | struct timespec type timespec (line 209) | struct timespec FILE: TimerQueue.h type std (line 35) | typedef std::set<Entry> TimerList; type timespec (line 43) | struct timespec FILE: Timestamp.cc function string (line 30) | string Timestamp::toString() const function Timestamp (line 39) | Timestamp Timestamp::now() function Timestamp (line 44) | Timestamp Timestamp::nowAfter(double seconds) type timeval (line 51) | struct timeval FILE: main.cc function main (line 7) | int main(int args, char** argv)
Condensed preview — 40 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (41K chars).
[
{
"path": "Acceptor.cc",
"chars": 2037,
"preview": "//author voidccc\n\n#include <arpa/inet.h>\n#include <fcntl.h>\n#include <errno.h>\n\n#include \"Acceptor.h\"\n#include \"Channel."
},
{
"path": "Acceptor.h",
"chars": 569,
"preview": "//author voidccc\n#ifndef ACCEPTOR_H\n#define ACCEPTOR_H\n\n#include \"Declear.h\"\n#include \"Define.h\"\n#include \"IChannelCallb"
},
{
"path": "BlockingQueue.h",
"chars": 786,
"preview": "//author voidccc\n#ifndef BLOCKINGQUEUE_H\n#define BLOCKINGQUEUE_H\n\n#include <deque>\n#include \"Condition.h\"\n#include \"Mute"
},
{
"path": "Buffer.cc",
"chars": 566,
"preview": "//author voidccc\n\n#include \"Buffer.h\"\n\nBuffer::Buffer()\n{}\n\nBuffer::~Buffer()\n{}\n\nconst char* Buffer::peek()\n{\n retur"
},
{
"path": "Buffer.h",
"chars": 413,
"preview": "//author voidccc\n#ifndef BUFFER_H\n#define BUFFER_H\n\n#include <string>\nusing namespace std;\n\nclass Buffer\n{\n public:\n "
},
{
"path": "Channel.cc",
"chars": 1189,
"preview": "//author voidccc\n\n#include <sys/epoll.h>\n\n#include \"Channel.h\"\n#include \"IChannelCallback.h\"\n#include \"EventLoop.h\"\n\n#in"
},
{
"path": "Channel.h",
"chars": 708,
"preview": "//author voidccc\n#ifndef CHANNEL_H\n#define CHANNEL_H\n\n#include \"Declear.h\"\n\nclass Channel\n{\n public:\n Channel("
},
{
"path": "Condition.h",
"chars": 728,
"preview": "//author voidccc\n#ifndef CONDITION_H\n#define CONDITION_H\n\n#include <pthread.h>\n#include \"Mutex.h\"\n\nclass Condition\n{\n "
},
{
"path": "CurrentThread.h",
"chars": 422,
"preview": "//author voidccc\n#ifndef CURRENTTHREAD_H\n#define CURRENTTHREAD_H \n\n#include <unistd.h>\n#include <sys/syscall.h>\n\nnamespa"
},
{
"path": "Declear.h",
"chars": 343,
"preview": "//author voidccc\n#ifndef DECLEAR_H\n#define DECLEAR_H\n\nclass IChannelCallback;\nclass IAcceptorCallback;\nclass Channel;\ncl"
},
{
"path": "Define.h",
"chars": 127,
"preview": "//author voidccc\n#ifndef DEFINE_H\n#define DEFINE_H\n\n#define MAX_LINE 100\n#define MAX_EVENTS 500\n#define MAX_LISTENFD 5\n\n"
},
{
"path": "EchoServer.cc",
"chars": 1296,
"preview": "//author voidccc\n\n#include \"EchoServer.h\"\n#include \"TcpConnection.h\"\n#include \"EventLoop.h\"\n#include \"CurrentThread.h\"\n#"
},
{
"path": "EchoServer.h",
"chars": 673,
"preview": "//author voidccc\n#ifndef ECHOSERVER_H\n#define ECHOSERVER_H\n\n#include \"IMuduoUser.h\"\n#include \"IRun.h\"\n#include \"TcpServe"
},
{
"path": "Epoll.cc",
"chars": 1341,
"preview": "//author voidccc\n\n#include <errno.h>\n\n#include \"Epoll.h\"\n#include \"Channel.h\"\n#include \"Define.h\"\n\n#include <iostream>\nu"
},
{
"path": "Epoll.h",
"chars": 367,
"preview": "//author voidccc\n#ifndef EPOLL_H\n#define EPOLL_H\n\n#include <sys/epoll.h>\n\n#include \"Declear.h\"\n#include \"Define.h\"\n\n#inc"
},
{
"path": "EventLoop.cc",
"chars": 3026,
"preview": "//author voidccc\n\n#include <sys/eventfd.h>\n\n#include \"EventLoop.h\"\n#include \"Channel.h\"\n#include \"Epoll.h\"\n#include \"Tim"
},
{
"path": "EventLoop.h",
"chars": 1092,
"preview": "//author voidccc\n#ifndef EVENTLOOP_H\n#define EVENTLOOP_H\n\n#include \"Declear.h\"\n#include \"IChannelCallback.h\"\n#include \"T"
},
{
"path": "IAcceptorCallback.h",
"chars": 176,
"preview": "//author voidccc\n#ifndef IACCEPTORCALLBACK_H \n#define IACCEPTORCALLBACK_H\n\nclass IAcceptorCallback\n{\n public:\n "
},
{
"path": "IChannelCallback.h",
"chars": 199,
"preview": "//author voidccc\n#ifndef ICHANNELCALLBACK_H\n#define ICHANNELCALLBACK_H\n\nclass IChannelCallback\n{\n public:\n vir"
},
{
"path": "IMuduoUser.h",
"chars": 357,
"preview": "//author voidccc\n#ifndef IMUDUOUSER_H\n#define IMUDUOUSER_H\n\n#include \"Declear.h\"\n#include <string>\nusing namespace std;\n"
},
{
"path": "IRun.h",
"chars": 252,
"preview": "//author voidccc\n#ifndef IRUN_H\n#define IRUN_H\n\n#include <string>\n\nusing namespace std;\n\nclass IRun0\n{\n public:\n "
},
{
"path": "Makefile",
"chars": 1064,
"preview": "#####################################\n# Copyright (c) 1997 George Foot (george.foot@merton.ox.ac.uk)\n# # All rights rese"
},
{
"path": "Mutex.h",
"chars": 892,
"preview": "//author voidccc\n#ifndef MUTEX_H\n#define MUTEX_H\n\n#include <pthread.h>\n\nclass MutexLock\n{\n public:\n MutexLock("
},
{
"path": "README.md",
"chars": 898,
"preview": "mini-muduo\n==========\na mini implementation of muduo\n\ntags:\n\nv0.01\n1 epoll example\n\nv0.02\n1 Add TcpServer, TcpServer is "
},
{
"path": "Task.cc",
"chars": 374,
"preview": "#include \"Task.h\"\n\n#include \"IRun.h\"\n\nTask::Task(IRun0* func)\n :_func0(func)\n ,_func2(NULL)\n ,_param(NULL)\n{\n\n}"
},
{
"path": "Task.h",
"chars": 346,
"preview": "//author voidccc\n#ifndef TASK_H\n#define TASK_H \n\n#include \"Declear.h\"\n#include <string>\n\nclass Task\n{\n public:\n "
},
{
"path": "TcpConnection.cc",
"chars": 3133,
"preview": "//author voidccc\n\n#include <errno.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <fcntl.h>\n\n#include \"TcpCon"
},
{
"path": "TcpConnection.h",
"chars": 976,
"preview": "//author voidccc\n#ifndef TCPCONNECTION_H\n#define TCPCONNECTION_H\n\n#include \"Declear.h\"\n#include \"IChannelCallback.h\"\n#in"
},
{
"path": "TcpServer.cc",
"chars": 714,
"preview": "//author voidccc\n\n#include <errno.h>\n\n#include \"TcpServer.h\"\n#include \"Channel.h\"\n#include \"Acceptor.h\"\n#include \"TcpCon"
},
{
"path": "TcpServer.h",
"chars": 651,
"preview": "//author voidccc\n#ifndef TCPSERVER_H\n#define TCPSERVER_H\n\n#include <sys/epoll.h>\n\n#include \"Declear.h\"\n#include \"Define."
},
{
"path": "Thread.cc",
"chars": 465,
"preview": "//author voidccc\n#include \"Thread.h\"\n\n#include <unistd.h>\n#include <sys/syscall.h>\n#include <pthread.h>\n\nnamespace Curre"
},
{
"path": "Thread.h",
"chars": 237,
"preview": "//author voidccc\n#ifndef THREAD_H\n#define THREAD_H\n\n#include \"Declear.h\"\n#include \"Task.h\"\n\nclass Thread\n{\n public:\n "
},
{
"path": "ThreadPool.cc",
"chars": 593,
"preview": "//author voidccc\n\n#include \"ThreadPool.h\"\n#include \"Thread.h\"\n\nThreadPool::ThreadPool() { }\n\nvoid ThreadPool::start(int "
},
{
"path": "ThreadPool.h",
"chars": 474,
"preview": "//author voidccc\n#ifndef THREADPOOL_H\n#define THREADPOOL_H\n\n#include \"Declear.h\"\n#include \"BlockingQueue.h\"\n#include \"Ta"
},
{
"path": "Timer.h",
"chars": 810,
"preview": "#ifndef TIMER_H\n#define TIMER_H\n\n#include \"Declear.h\"\n\n#include \"IRun.h\"\n\nclass Timer\n{\n public:\n Timer(Timest"
},
{
"path": "TimerQueue.cc",
"chars": 5120,
"preview": "//author voidccc\n\n#include <sys/timerfd.h>\n#include <inttypes.h>\n#include <stdio.h>\n#include <strings.h>\n\n#include \"Time"
},
{
"path": "TimerQueue.h",
"chars": 1309,
"preview": "// author voidccc\n#ifndef TIMERQUEUE_H\n#define TIMERQUEUE_H\n\n#include \"Declear.h\"\n#include \"IChannelCallback.h\"\n#include"
},
{
"path": "Timestamp.cc",
"chars": 1431,
"preview": "//author voidccc\n\n#include <sys/time.h>\n#include <stdio.h>\n#define __STDC_FORMAT_MACROS\n#include <inttypes.h>\n#undef __S"
},
{
"path": "Timestamp.h",
"chars": 608,
"preview": "//author voidccc\n#ifndef TIMESTAMP_H\n#define TIMESTAMP_H\n\n#include <sys/types.h>\n#include <string>\nusing namespace std;\n"
},
{
"path": "main.cc",
"chars": 234,
"preview": "//author voidccc\n\n#include \"TcpServer.h\"\n#include \"EventLoop.h\"\n#include \"EchoServer.h\"\n\nint main(int args, char** argv)"
}
]
About this extraction
This page contains the full source code of the voidccc/mini-muduo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 40 files (36.1 KB), approximately 10.4k tokens, and a symbol index with 46 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.