异步处理框架样例代码

来源:互联网 发布:ncbi数据库下载 编辑:程序博客网 时间:2024/06/01 10:35
/**
 * 服务线程使用Lazy?
 * RUNNING  初始化状态
 * @e-mail: horatii@163.com
 */


/**
 * usage:
 * class MyEventProcessor : public EventProcessor {
 * public:
 *     MyEventProcessor() {}
 *
 * protected:
 *     virtual void reject(const EventPtr& event) {
 *         // event->xxxx
 *     }
 *
 *     virtual void handle(const EventPtr& event) {
 *         // event->xxxx;
 *     }
 *     virtual void ignoe(const EventPtr& event) {
 *        // event->xxxxx;
 *     }
 * };
 *
 */
class EventProcessor : public Runable {
public:
    enum {RUNNING = 0, SHUTDOWN = 1, STOPED = 2}
    
    EventProcessor() : status (RUNNING), thread(new InterruptableThread(this)) {
        
    }


    void process(const EventPtr& event) {
        if (status > RUNNING) {
            reject(event);
        } else {            
            eventQueue.offer(event);
        }
    }




    void shutdown()
    {   
        //
        // 防止多次调用
        //
        while (true) {
            long s = status;
            if (s != RUNNING) break;
            // 如果不等,status的状态已经被改变
            if (s != ::InerlockedCompareAndExchange(&status, SHUTDOWN, s))
                continue;


            thread.interrupt();
            thread.await();


            std::list<EventPtr> events;
            eventQueue.drianTo(events);
            foreach(auto event : events) {
                ignore(event);
            }


            status = STOPED;
        }
    }




protected:
    // template methods
    virtual void reject(const EventPtr& event) {
        //
    }


    virtual void ignore(const EventPtr& event) {
        //
    }


    virtual void handle(const EventPtr& event) {
        //
    }




public:
    // overide Runable
    void run() {
        while (true) {
            try {
                // 阻塞直到有Event被加入或者线程退出触发InterruptedException
                EventPtr event = eventQueue.take();
                handle(event);
            } catch (InterruptedException& ignore) {
                break;
            }
        }
    }




private:
    volatile long status;


    EventQueue eventQueue;
    std::tr1::shared_ptr<InterruptableThread> thread;
};


class EventQueue {
public:
    EventQueue() {}


    /**
     * 放入队列一个Event
     */
    void offer(const EventPtr& event) {
        ReenterantLock::ScopeLock scopeLock(lock);
        if (!waiters.empty()) {
            WaiterPtr waiter = waiters.front();
            waiters.pop_front();
            waiter.setResult(event);
            waiter->signal();
        } else {
            events.push_back(event);
        }
    }


    /**
     * 从当前的队列中取出一个元素,如果当前队列为空则阻塞当前线程
     * 直到有新的Event被加入队列或者当前线程被终止
     */
    EventPtr take() throw(InterruptedException, SystemtErrorException) {
        //
        // 多线程事物的原子性
        //
        WaiterPtr waiter;
        {
            ReenterantLock::ScopeLock scopeLock(lock);
            if (!events.empty()) {
                EventPtr event = events.front();
                events.pop_front();
            } else {
                waiter.reset(new WaiterPtr);
            }
        }


        waiter.await();
        return waiter.getResult();
    }




private:
    // 与thread相关联
    class Waiter {
    public:
        Waiter() {
            eventHandle = ::CreateEvent(NULL, FALSE, TRUE, NULL);
        }


        void signal() {
            ::SetEvent(eventHandle);
        }


        void await() throw(InterruptedException) {
            HANDLE intteruptHandle = ThreadTable::currentThreadInterruptEventHandle();
            HANDLE handles[2];
            handles[0] = eventHandle;
            handles[1] = intteruptHandle;


#define MUTEX_SIGNAL            WAIT_OBJECT_0
#define INTERRUPT_EVENT_SIGNAL  (WAIT_OBJECT_0 + 1)
            DWORD ret = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
            switch (ret) {
            case MUTEX_SIGNAL:
                return;
            case INTERRUPT_EVENT_SIGNAL:
                throw InterruptedException();
            default:
                throw SystemtErrorException(::GetLastError());
            }
        }


        void setResult(const EventPtr& result) {
            this->result = result;
        }


        EventPtr getResult() const {
            return result;
        }


    private:
        EventPtr result;
        HANDLE eventHandle;
    };




    ReenterantLock lock;
    std::queue<EventPtr> events;


    typedef std::tr1::shared_ptr<Waiter> WaiterPtr;
    std::queue<WaiterPtr> waiters;
};


// 可以改用 CritialSection 来实现
class ReenterantLock {
public:
    ReenterantLock() {
        mutexHandle = ::CreateMutex(NULL, NULL, NULL);
    }


    void lock() {
        ::WaitForSingleObject(mutexHandle);
    }


    void unlock() {
        ::ReleaseMutex(mutexHandle);
    }


    class ScopeLock {
    public:
        ScopeLock(ReenterantLock& lock) : l(lock) {
            l.lock();
        }
        ~ScopeLock() {
            l.unlock();
        }
    private:
        ReenterantLock l;
    };


private:
    HANDLE mutexHandle;
};


class InterruptableThread {
public:
    InterruptableThread(const RunablePtr& runable)
    : runable(runable)
    {
        interruptEventHandle  = ::CreateEvent(NULL, FALSE, TRUE, NULL);
        threadHandle = ::CreateThread(NULL, 0,0, ThreadPro, this, 0);


        ThreadTable::add(this);
    }


    ~InterruptableThread()
    {
        ThreadTable::remove(this);


        ::CloseHandle(interruptEventHandle);
        ::CloseHandle(threadHandle);
    }


    void interrupt()
    {
        ::SetEvent(interruptEventHandle);
    }


    void await()
    {
        ::WaitForSingleObject(threadHandle, INFINITE);
    }


    int getId() const {
        return id;
    }


    HANDLE getInterruptEventHandle() const {
        return interruptEventHandle;
    }


    int loop() {
        try {
            runable->run();   
        } catch (InterruptedException& interrupted) {
            return -1;
        } catch (SystemtErrorException& error) {
            return -1;
        } catch (...) {
            return -1;
        }


        return 0;
    }


private:
    static DWORD WINAPI ThreadPro(LPVOID lpargs) {
        InterruptableThread* pThis = lpargs;
        return pThis->loop();
    }


    int id;
    RunablePtr runable;
    HANDLE threadHandle;
    HANDLE interruptEventHandle;
};


class ThreadTable {
public:
    static void add(const InterruptableThread* ptr) {
        ReenterantLock::ScopeLock scopeLock(lock);
        threadMap.insert(std::make_pair(ptr->getId(), ptr));
    }


    static void remove(const InterruptableThread* ptr) {
        ReenterantLock::ScopeLock scopeLock(lock);
        threadMap.remove(ptr->getId());
    }


    static HANDLE currentThreadInterruptEventHandle() {
        InterruptableThread* thread = currentThread();
        return thread->getInterruptEventHandle();
    }
    static InterruptableThread* currentThread() {
        int id = GetCurrentThreadId();
        return getThread(id);
    }


    static InterruptableThread* getThread(int id) {
        ReenterantLock::ScopeLock scopeLock(lock);
        return threadMap[id];
    }


private:
    static ReenterantLock lock;
    static std::map<int ,InterruptableThread*> threadMap;
};
0 0
原创粉丝点击