/* * ===================================================================================== * * Filename: request_base.h * * Description: request_base class definition. * * Version: 1.0 * Created: 09/08/2018 * Revision: none * Compiler: gcc * * Author: zhulin, shzhulin3@jd.com * Company: JD.com, Inc. * * ===================================================================================== */ #ifndef __H_TTC_REQUEST_TEMP_H__ #define __H_TTC_REQUEST_TEMP_H__ #include #include #include "lqueue.h" #include "log.h" #include "timerlist.h" template class CTaskPipe; class CPollThread; template class CTaskOneWayDispatcher { public: CPollThread *owner; public: inline CTaskOneWayDispatcher(CPollThread *p=NULL) : owner(p) {} virtual inline ~CTaskOneWayDispatcher(){} virtual void TaskNotify(T) = 0; inline CPollThread *OwnerThread(void) { return owner; } inline void AttachThread(CPollThread *thread){ if(owner==NULL) owner = thread; } }; template class CTaskDispatcher : public CTaskOneWayDispatcher { public: inline CTaskDispatcher(CPollThread *p=NULL) : CTaskOneWayDispatcher(p) {} virtual inline ~CTaskDispatcher(){} }; template class CReplyDispatcher { public: inline CReplyDispatcher() {} virtual inline ~CReplyDispatcher() {} virtual void ReplyNotify(T *) = 0; }; template class CRequestOutput: private CTimerObject { private: CPollThread *owner; CTaskDispatcher *proc; CLinkQueue queue; typename CLinkQueue::allocator allocator; protected: int queueDisabled; private: inline virtual void TimerNotify(void) { T *p; while((p=queue.Pop()) != NULL) TaskNotify(p); } public: inline CRequestOutput(CPollThread *o) : owner(o), proc(NULL), queue(&allocator), queueDisabled(0) //reply(NULL) {} inline ~CRequestOutput() {} inline CPollThread *OwnerThread(void) { return owner; } inline void BindDispatcher(CTaskDispatcher *out) { if(owner == out->OwnerThread()) { proc = out; } else { CTaskPipe *tp = new CTaskPipe(); tp->BindDispatcher(this, out); } } inline void TaskNotify(T *p) { proc->TaskNotify(p); } inline void IndirectNotify(T *p) { if(queueDisabled) TaskNotify(p); else { queue.Push(p); AttachReadyTimer(owner); } } inline CTaskDispatcher *GetDispatcher(void) { return proc; } inline void DisableQueue(void) { queueDisabled = 1; } }; template class CTaskReplyList { public: CReplyDispatcher *proc[maxcount]; int count; public: inline CTaskReplyList(void) {count=0;}; inline virtual ~CTaskReplyList(void) {}; inline void Clean() { memset(proc, 0, sizeof(CReplyDispatcher *) * maxcount); count = 0; } inline void CopyReplyPath(CTaskReplyList * org) { memcpy(proc, org->proc, sizeof(CReplyDispatcher *) * maxcount); count = org->count; } inline int Push(CReplyDispatcher *p) { if(count>=maxcount) return -1; proc[count++] = p; return 0; } inline CReplyDispatcher *Pop(void) { return count==0 ? NULL : proc[--count]; } inline void Dump(void) { for(int i=0; i *proc) { if(proc==NULL) static_cast(this)->Panic("PushReplyDispatcher: dispatcher is NULL, check your code"); else if(Push(proc) != 0) static_cast(this)->Panic("PushReplyDispatcher: push queue failed, possible memory exhausted"); } inline void ReplyNotify(void) { CReplyDispatcher *proc = Pop(); if(proc==NULL) static_cast(this)->Panic("ReplyNotify: no more dispatcher, possible double reply"); else proc->ReplyNotify(static_cast(this)); } void Panic(const char *msg); }; template void CTaskReplyList::Panic(const char *msg) { log_crit("Internal Error Encountered: %s", msg); } #endif