#ifndef _THREADWORK_H_
#define _THREADWORK_H_
#pragma once  
struct cdata
{ 
    struct impl;
    struct impl *_impl;

    volatile long _refcount;
    cdata();
    void* __stdcall operator new(size_t size);
    void  __stdcall operator delete(void *p);
}; 
class iexcute
{
public:
    virtual cdata* doproc(cdata*) = 0;  
};
class istream :virtual public iexcute
{
public:
    virtual ~istream(){}  
};
class ifilter :virtual public iexcute
{
public:
    virtual ~ifilter(){}
};
class ireport :virtual public iexcute
{
public:
    virtual ~ireport(){}
};

class threadworker
{  
public:
    class impl;
    threadworker();
    ~threadworker();
    void setup(
        int /*0>=: 使用win线程池减少执行时间,<-100:不使用任何线程,其他值:filter,report中的函数使用新线程*/
    );
    void apply(istream *[] ,ifilter*[] ,ireport*[] );  // 可以多次使用这个函数加入新的处理步骤。
    void submit(
        long flag = 0/*使用win线程时,对filter(n:flag>>8),report(n:flag>>16)向线程池提交方式进行调整,
                     当队列有缓存并且缓存数量不大于n时提交任务,
                     stream(flag&0x1)线程是否不以向线程池提交任务的方式使用*/
    );
    void submit(cdata * = nullptr);
private:
    impl * _impl;
};
#endif /*_THREADWORK_H_*/

//cpp file

#include "threadworker.h"
#include <windows.h> 

#include <stddef.h>
#include <condition_variable>
#include <mutex> 
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>  
#include <thread>
#include <future> 
#include <mutex>
#include <queue>
#include <atomic>
#include <iostream> 

#define TRACE_PIPE printf
#define TRACE_PIPE
#define USE_MMPOOL 

/*内存函数:Copyright*/
/*
The author of this software is David R.Hanson.

Copyright(c) 1994, 1995, 1996, 1997 by David R.Hanson.All Rights Reserved.

Permission to use, copy, modify, and distribute this software for any
purpose, subject to the provisions described below, without fee is
hereby granted, provided that this entire notice is included in all
copies of any software that is or includes a copy or modification of
this software and in all copies of the supporting documentation for
such software.

THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
WARRANTY.IN PARTICULAR, THE AUTHOR DOES MAKE ANY REPRESENTATION OR
WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR
ITS FITNESS FOR ANY PARTICULAR PURPOSE.

David Hanson / drh@microsoft.com / http://www.research.microsoft.com/~drh/
$Id: CPYRIGHT, v 1.2 1997 / 11 / 04 22 : 31 : 40 drh Exp $
 */
 /*  */
#define THRESHOLD 400
#define hash(p, t) (((unsigned long)(p)>>3) & \
    (sizeof (t)/sizeof ((t)[0])-1))
#define NDESCRIPTORS 512
#define NALLOC ((4096 + sizeof (union align) - 1)/ \
    (sizeof (union align)))*(sizeof (union align))
class newmem
{
    union align
    {
#ifdef MAXALIGN
        char pad[MAXALIGN];
#else
        int i;
        long l;
        long *lp;
        void *p;
        void(*fp)(void);
        float f;
        double d;
        long double ld;
#endif
    };
    class newarena
    {
        struct arena
        {
            arena * prev;
            char * avail;
            char * limit;
        };
        union header
        {
            struct arena b;
            union align a;
        };
        arena * _arena;
        arena * _freechunks;
        int _nfree;
    public:
        newarena() :_arena(new arena())
        {
            _arena->prev = nullptr;
            _arena->limit = _arena->avail = nullptr;
        }
        ~newarena()
        {
            free();
            delete _arena;
        }
        void* alloc(long nbytes)
        {
            nbytes = ((nbytes + sizeof(union align) - 1) /
                (sizeof(union align)))*(sizeof(union align));
            while (nbytes > _arena->limit - _arena->avail) {
                arena* ptr;
                char *limit;
                if ((ptr = _freechunks) != NULL) {
                    _freechunks = _freechunks->prev;
                    _nfree--;
                    limit = ptr->limit;
                }
                else
                {
                    long m = sizeof(union header) + nbytes + 10 * 1024;
                    ptr = reinterpret_cast<arena*> (malloc(m));
                    limit = (char *)ptr + m;
                }
                *ptr = *_arena;
                _arena->avail = (char *)((union header *)ptr + 1);
                _arena->limit = limit;
                _arena->prev = ptr;
            }
            _arena->avail += nbytes;
            return _arena->avail - nbytes;
        }
        void free()
        {
            while (_arena->prev) {
                struct arena tmp = *_arena->prev;
                if (_nfree < THRESHOLD) {
                    _arena->prev->prev = _freechunks;
                    _freechunks = _arena->prev;
                    _nfree++;
                    _freechunks->limit = _arena->limit;
                }
                else
                    delete _arena->prev;
                *_arena = tmp;
            }
            assert(_arena->limit == NULL);
            assert(_arena->avail == NULL);
        }
    }_arena;
    
    struct descriptor 
    {
        struct descriptor *free;
        struct descriptor *link;
        const void *ptr;
        long size;
        const char *file;
        int line;
    } *htab[2048];
    struct descriptor freelist = { &freelist };
    struct descriptor *avail;
    int nleft;
    std::mutex _mutex; 
    void *resize(void *ptr, long nbytes) 
    {
        struct descriptor *bp = 0;
        void *newptr;
        assert(ptr);
        assert(nbytes > 0);
#ifdef MAXALIGN
        if ((((unsigned long)ptr) &~(MAXALIGN - 1)) != 0
#else
        if (((unsigned long)ptr) % (sizeof(union align)) != 0
#endif
            || (bp = find(ptr)) == NULL || bp->free)
            throw std::exception("Allocation Failed");
            newptr = alloc(nbytes);
            memcpy(newptr, ptr,
                nbytes < bp->size ? nbytes : bp->size);
            free(ptr);
            return newptr;
    }
    void *calloc(long count, long nbytes) 
    {
        void *ptr;
        assert(count > 0);
        assert(nbytes > 0);
        ptr = alloc(count*nbytes);
        memset(ptr, '\0', count*nbytes);
        return ptr;
    }
    struct descriptor *dalloc(void *ptr, long size) 
    {
        if (nleft <= 0) {
            avail = (struct descriptor *)_arena.alloc(NDESCRIPTORS * sizeof(*avail));
            if (avail == NULL)
                return NULL;
            nleft = NDESCRIPTORS;
        }
        avail->ptr = ptr;
        avail->size = size;
        avail->free = avail->link = NULL;
        nleft--;
        return avail++;
    }  
    descriptor *find(const void *ptr) {
        struct descriptor *bp = htab[hash(ptr, htab)];
        while (bp && bp->ptr != ptr)
            bp = bp->link;
        return bp;
    } 
    newmem() :avail(nullptr), nleft(0) {}
public: 
    static newmem& get()
    { 
        static newmem _newmem;
        return _newmem;
    }
    void* alloc(long nbytes)
    {
        std::lock_guard<std::mutex> guard(_mutex); 
        struct descriptor *bp = 0;
        void *ptr;
        assert(nbytes > 0);
#ifdef MAXALIGN
        nbytes = (nbytes + MAXALIGN - 1) & ~(MAXALIGN - 1);
#else
        nbytes = ((nbytes + sizeof(union align) - 1) /
            (sizeof(union align)))*(sizeof(union align));
#endif

        for (bp = freelist.free; bp; bp = bp->free) {
            if (bp->size > nbytes) {
                bp->size -= nbytes;
                ptr = (char *)bp->ptr + bp->size;
                if ((bp = dalloc(ptr, nbytes)) != NULL) {
                    unsigned h = hash(ptr, htab);
                    bp->link = htab[h];
                    htab[h] = bp;
                    return ptr;
                }
                else
                {
                    throw std::exception("Allocation Failed");
                }
            }
            if (bp == &freelist) {
                struct descriptor *newptr = 0;
                if ((ptr = _arena.alloc(nbytes + NALLOC)) == NULL
                    || (newptr = dalloc(ptr, nbytes + NALLOC)) == NULL)
                {
                    throw std::exception("Allocation Failed");
                }
                newptr->free = freelist.free;
                freelist.free = newptr;
            }
        }
        assert(0);
        return NULL; 
    }
    void free(void *ptr)
    { 
        if (ptr)
        {
            struct descriptor *bp = 0;
            if (((unsigned long)ptr) % (sizeof(union align)) != 0
                || (bp = find(ptr)) == NULL || bp->free)
                throw std::exception("Allocation Failed");
            bp->free = freelist.free;
            freelist.free = bp;
        } 
    }
}; 
struct cdata::impl
{
    std::atomic_long _refcount;
    impl() { std::atomic_init(&_refcount, 0); }
};
cdata::cdata() :_refcount(1), _impl(new cdata::impl()){}
void* __stdcall cdata::operator new(size_t size)
{  
#ifdef USE_MMPOOL
    return newmem::get().alloc(size);
#else
    return malloc(size);
#endif
}
void  __stdcall cdata::operator delete(void *p)
{    
#ifdef USE_MMPOOL
    newmem::get().free(p);
#else
    free(p);
#endif
}
class singlylist
{
    typedef struct
    {
        SLIST_ENTRY entry;
        cdata* data;
        void* __stdcall operator new(size_t size)
        {
            assert(sizeof(singlylist::_titem) == size);
            return _aligned_malloc(size, MEMORY_ALLOCATION_ALIGNMENT);
        }
        void __stdcall operator delete(void *p)
        {
            _aligned_free(p);
        }
    }_titem, *_ptitem;
    PSLIST_HEADER plist; 
public:  
    long count(){ 
        return QueryDepthSList(plist); 
    }
    cdata* lockedput (cdata* data){
        _ptitem pitem = new _titem();
        assert(pitem);
        pitem->data = data;
        PSLIST_ENTRY entry = InterlockedPushEntrySList(plist, &pitem->entry);
        pitem = reinterpret_cast<_ptitem>(entry);
         
        return pitem ?pitem->data:nullptr;
    }
    cdata* lockedget(){ 
        PSLIST_ENTRY entry = InterlockedPopEntrySList(plist);
        _ptitem pitem = reinterpret_cast<_ptitem>(entry); 
        if (pitem)
        {
            cdata* data = pitem->data;
            delete pitem; 
            return data;
        }
        else
            return nullptr;
    }
    singlylist(){
        plist = (PSLIST_HEADER)_aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
        assert(plist);
        InitializeSListHead(plist);
    }
    ~singlylist(){
        InterlockedFlushSList(plist);
        _aligned_free(plist);
    }
};
class linkptr
{
    void * _list;
    int _offset;
public:
    linkptr(int offset) :_list(nullptr), _offset(offset){}
    void push(void* p)
    {
        *pptr(p) = _list;
        _list = p;
    }
    void pop(void* p)
    {
        _list = *pptr(p);
    }
    void* get()
    {
        return _list;
    }
    void* next(void *p){return *pptr(p); }
    void** pptr(void* p) const
    {
        return (void**)((char*)(p) + _offset);
    }
};
template<class T>
class linktype : private linkptr
{
public:
    linktype(int offset = 0) : linkptr(offset){}
    void push(T* p)
    {
        linkptr::push(p);
    } 
    T* next(T* p)
    {
        return (T*)(linkptr::next(p));
    }
    T* get()
    {
        return (T*)(linkptr::get());
    }
    void pop(T* p)
    {
        return linkptr::pop((T*)p);
    }
    operator T*()
    {
        return (T*)(linkptr::get());
    }
};
template<class T>
class list
{
    T* _current;
public: 
    list() :_current(nullptr){}
    void push(T* p)
    {
        p->rest = _current;
        _current = p;
    }
    T* next(T* p)
    {
        return p->rest;
    }  
    void pop(T *p)
    {
        _current = p->rest;
    }
    operator T*()
    {
        return _current;
    }
}; 
class threadworker::impl
{
public:
    virtual ~impl() {
    }
    virtual void apply(istream* stream[], ifilter* filter[], ireport* report[])
    {
    }
    virtual void start(long flag)
    {
    } 
    virtual void start(cdata* d)
    {
    }
    };
namespace  submit
{ 
#ifdef __cplusplus
#define $(T) _##T
#else
#define $(T) T
#endif
#define NEXTPTR(p,_,q) do{ p##->##_= q; }while(0)
#define LINKPTR(p,_,q) do{ p##->##_= q; q = p; }while(0) 

#define T SubmitThread_T

    typedef struct $(SubmitThread_T) *T;
    typedef struct cdata *data;
    typedef struct $(pump) *pump;
    typedef void* vptr;
    typedef data(*vfun)(data, vptr); 
 
    struct $(pump) {
        pump _rest;
        pump _next;
        struct t {
            struct t * _next;
            vfun*_pfun;
            vptr _vptr;
        }*_vfun;
        long _flag;
        const char* _name;
    };      
    class lockedlist {
        std::condition_variable cv;
        std::mutex mt;
        std::queue<data> queue;
    public:
        void put(data d) {
            std::lock_guard<std::mutex> l(mt);
            queue.push(d);
            cv.notify_one();
        }
        data get(void) {
            std::unique_lock<std::mutex> l(mt);
            cv.wait(l, [this] {return !queue.empty(); });
            data d = queue.front();
            queue.pop();
            return d;
        }
    };
    class submitnode { 
        submitnode *_root, *_rest, *_next; 
    public:
        const char *_name;
        submitnode() :_root(nullptr), _rest(nullptr), _next(nullptr), _name("node") {}
        virtual ~submitnode() { 
            free(_rest);
        }
        void free(submitnode * next) {
            for (auto * t = next; t; ) {
                auto* d = t;
                t = t->_next;
                delete d;
            }
        }
        void rest(submitnode * rest) {
            LINKPTR(rest, _next, _rest);
            rest->_root = this;
        }
        void root(submitnode * root) {
            _root = root;
        }
        void next(submitnode * next) {
            _next = next;
        } 
        virtual void done(data d) {
            assert(_root);
            _root->done(d);
        }
        virtual void pump(data d) {   
            return _next ? _next->pipe(d) : _root ? _root->pump(d):__nop();
        }
        virtual void tick(data d) { 
            for (auto * t = _rest; t; t = t->_next)
                t->tick(d);
        }
        virtual data todo(data d) {
            for (auto * t = _rest; t; t = t->_next)
                 d = t->todo(d);
            return d;
        }
        virtual data pipe(data d){
            submitnode::tick(d); 
            return submitnode::todo(d);
        }
    };
    class submitunit : public submitnode{
        vfun _vfun;
        vptr _vptr;
    public:
        submitunit(vfun fun, vptr ptr) :_vfun(fun), _vptr(ptr) { _name = ("unit");}
        virtual data todo(data d) {
            return _vfun(d, _vptr);
        }
    };
    class submitwork : public submitnode{
    protected:
        virtual ~submitwork() {}
        virtual data work(data d) {
            d = pipe(d);
            done(d);
            return d;
        }
        virtual data todo(data d) {
            return work(d);
        }
    public:
        submitwork() { _name = "work"; }
        void applyf(vfun fun, vptr ptr) {
            rest(new submitunit(fun, ptr));
        }
    };
    class submitmain : public submitwork{
        std::future<void> _fature;
        lockedlist &_list;
        virtual void main() {
            for (data d; work(d = _list.get());) ;
        }
        static void __stdcall submit(submitmain* _thisptr) {
            _thisptr->main();
        }
    public:
        submitmain(lockedlist& l) :_list(l), _fature(std::async(&submitmain::submit, this)) { }
        ~submitmain() { 
            _fature.get();   
        }
    };
    class submittodo : public submitnode{
        submitnode * _node;
    private:
        void node(submitnode * node) {
            node->next(_node);
            _node = node; 
            _node->root(this);
        }
        void done(data d) { 
            submitnode::pump(d);
        } 
        virtual void pump(data d) {                                       
            _node->todo(d);
        }
        virtual data todo(data d) {
            pump(d);
            return d;
        }
        virtual submitwork * getsubmit() {
            return new submitwork();
        }
    public:
        submittodo() :_node(nullptr) { _name = "todo"; }
        virtual ~submittodo() {
            free(_node);
        }
        virtual void applyf(vfun* fun, vptr ptr) {
            for (submitwork * m; *fun; ++fun) {
                m = getsubmit();
                m->applyf(*fun, ptr);
                node(m);
            }
        }
    };
    class submitcont : public submittodo{
        virtual data todo(data d) {
            return submitnode::todo(d);
        }
    };
    class submititem : public submittodo {
        lockedlist _list;
        virtual void tick(data d) {
            if (!d || ++d->_impl->_refcount > 0) {
                return;
            }
            assert(0);
        }
        virtual void done(data d) {
            if (!d || --d->_impl->_refcount <= 0){
                return submitnode::pump(d);
            } 
        }
        virtual data todo(data d) {
            _list.put(d);
            return d;
        }
    private:
        virtual submitwork * getsubmit() {
            return new submitmain(_list);
        }
    };
    class produceobj{
        int _number_hardware;
        int _number_id;
        produceobj() :_number_hardware(std::thread::hardware_concurrency()), _number_id(0){
        }
    public:
        static produceobj& factory() {
            static produceobj _producer;
            return _producer;
        }
        void closethread() { 
            _number_hardware = 0;
        }
        submittodo* newitem(bool only1) {
            return  only1 ? 1 < ++_number_id && _number_id <= _number_hardware ? new submititem() : new submittodo() : new submitcont();
        }
    };
    struct $(SubmitThread_T) {
        submitnode* _link; 
        submitnode* tonode(pump p) {
            if (p->_vfun) {
                submittodo * m = produceobj::factory().newitem(!p->_rest);
                auto * i = p->_vfun; 
                do {
                    m->applyf(i->_pfun, i->_vptr); 
                    //del
                    auto * t = i;
                    i = i->_next;
                    delete t->_pfun;
                    delete t;
                }
                while (i);
                p->_vfun = nullptr;
                return m;
            }
            else {
                return new submitnode();
            }
        }
        submitnode* applyf(pump p) {
            submitnode * r = tonode(p);
            r->_name = p->_name;
            for (auto * i = p->_rest; i;) {
                r->rest(applyf(i));
                //del
                auto * t = i;
                i = i->_next; 
                delete t;
            }
            p->_rest = nullptr;
            return r;
        }
    public:
        $(SubmitThread_T)(int count) : _link(new submitnode[count]){
            for(int i = 1 ; i < count; ++i)
                _link[i - 1].next(&_link[i]);
        }
        ~$(SubmitThread_T)() { 
            delete [] _link;
        }
        void apply(pump p,int i) {
            _link[i].rest(applyf(p));
        }
        void pipe(data d) {
            _link[0].pipe(d);
        }
    };
    class impl : public threadworker::impl{
        T _mgr; 
        static data streamfun(data d, vptr p){
            return ((istream*)p)->doproc(d);
        }
        static data filterfun(data d, vptr p) {
            return ((ifilter*)p)->doproc(d);
        }
        static data reportfun(data d, vptr p) {
            return ((ireport*)p)->doproc(d);
        }
    public:
        impl() {
            _mgr = new $(SubmitThread_T)(3);
        }
        ~impl() { 
            delete _mgr;
        }
        void start(long) {
            _mgr->pipe(nullptr);
        }
        void start(data d) {
            _mgr->pipe(d);
        }
        void apply(istream* stream[], ifilter* filter[], ireport* report[]){
            if (stream) {
                pump p = new $(pump)();
                p = new $(pump)();
                p->_rest = nullptr;
                p->_next = nullptr; 
                p->_flag = 0L;
                p->_name = "stream";
                for (; *stream; stream++) { 
                    istream* i = *stream;
                    {
                        $(pump)::t *f = new $(pump)::t;
                        f->_pfun = new vfun[2];
                        f->_pfun[0] = streamfun;
                        f->_pfun[1] = nullptr;
                        f->_vptr = i;
                        f->_next = p->_vfun;
                        p->_vfun = f;
                    }
                }
                _mgr->apply(p,0);
            }
            if (filter) { 
                    pump p = new $(pump)();
                    p = new $(pump)();
                    p->_rest = nullptr;
                    p->_next = nullptr;
                    p->_flag = 0L; 
                    p->_name = "filter";
                    for (; *filter; filter++) {
                        ifilter* i = *filter;
                        {
                            $(pump)::t *f = new $(pump)::t;
                            f->_pfun = new vfun[2];
                            f->_pfun[0] = filterfun;
                            f->_pfun[1] = nullptr;
                            f->_vptr = i;
                            f->_next = p->_vfun;
                            p->_vfun = f;
                        }
                    } 
                _mgr->apply(p, 1);
            }
            if (report) { 
                pump p = new $(pump)();
                p = new $(pump)();
                p->_rest = nullptr;
                p->_next = nullptr;
                p->_flag = 0L;
                p->_name = "report";
                for (; *report; report++) { 
                    ireport* i = *report;
                    {
                        $(pump)::t *f = new $(pump)::t;
                        f->_pfun = new vfun[2];
                        f->_pfun[0] = reportfun;
                        f->_pfun[1] = nullptr;
                        f->_vptr = i;
                        f->_next = p->_vfun;
                        p->_vfun = f;
                    }
                } 
                _mgr->apply(p, 2);
            }
        }
    }; 
#undef T  
}

class submitimpl : public threadworker::impl
{
    friend class threadworker; 
    long _refcount;
    HANDLE _exitevent;  
    class idatapipe
    { 
    protected:
        idatapipe * _datapipe; 
        long _flag;
    public:
        virtual void pipe(cdata * d) { delete d; } 
        virtual void setp(idatapipe * pipe) { _datapipe = pipe; }
        virtual idatapipe * getp() { return _datapipe; };
        void setflag(long flag) {_flag = flag;}
    }; 
    template <typename T> 
    class worksubmit : public idatapipe  
    { 
    public:
        worksubmit * next;
    protected:
        struct node
        {
            node* rest;
            T* t;
            node(T* d) :t(d) {}
        }; 
        list<node> _nodelist;    
        PTP_WORK _tpwk;
        virtual const char* name(){ return ""; }
    public:
        worksubmit()
        {  
            _tpwk = CreateThreadpoolWork(main, this, NULL); 
        }
        ~worksubmit()
        { 
            CloseThreadpoolWork(_tpwk); 
        }  
        virtual void push(T *t)
        {
            _nodelist.push(new node(t));
        }
        virtual void pipe(cdata * d) 
        {  
        } 
        static void __stdcall main(PTP_CALLBACK_INSTANCE instance, PVOID vptr, PTP_WORK tpwk)
        {
             ((worksubmit*)vptr)->run(instance, tpwk);
        }
        virtual void run(PTP_CALLBACK_INSTANCE , PTP_WORK ) = 0;
    
    };
    class mainstream : public idatapipe 
    {
        class workstream : public worksubmit<istream>
        {
            virtual const char* name() { return "name:stream"; }
            virtual void run(PTP_CALLBACK_INSTANCE instance, PTP_WORK tpwk)
            {
                assert(tpwk == _tpwk);
                
                long flag = _flag & 0xFF;
                if(flag & 1)
                    CallbackMayRunLong(instance);
                _forever:
                    for (node* n = _nodelist; n ; n = _nodelist.next(n)){
                        if (cdata * d = n->t->doproc(_locklist.lockedget()))
                            TRACE_PIPE("stream doproc \n"), _datapipe->pipe(d);
                        else
                            return (void)TRACE_PIPE("stream exit \n");
                    }
                    if (flag & 1)
                        goto _forever;
                    else
                        SubmitThreadpoolWork(tpwk);
            }
            singlylist &_locklist;
        public:
            workstream(singlylist & sl) : _locklist(sl){}  
            void start(){
                SubmitThreadpoolWork(_tpwk);;
            }
        };
        linktype<workstream> _workstream;
        singlylist _locklist;
        long _refcount;
    public:
        mainstream() : _workstream(offsetof(workstream, next)), _refcount(0){ }
        virtual idatapipe * getp(){
            return this;
        };
        void pipe(cdata * d)
        {  
            assert(_refcount);
            if (InterlockedDecrement(&d->_refcount) == 0)
            {
                InterlockedExchange(&d->_refcount, 1);
                _locklist.lockedput(d);
            }
        }
        void push(istream* streams[])
        {
            ++_refcount;
            workstream * ws = new workstream(_locklist);
            ws->setp(_datapipe);
            while (*streams)
                ws->push(*streams++);
            _workstream.push(ws); 
        }
        void start()
        {
            for (workstream* n = _workstream; n; n = _workstream.next(n))
                n->start();
        }
        void setflag(long flag) { 
            for (workstream* n = _workstream; n; n = _workstream.next(n))
                n->setflag(flag);
        }
    }_twkstream;
    class mainfilter : public idatapipe
    { 
        class parallel : public idatapipe
        {
        public:
            parallel * next;
        private:
            class workfilter : public worksubmit<ifilter>
            {
                virtual const char* name() { return "name:filter"; }
                virtual void run(PTP_CALLBACK_INSTANCE instance, PTP_WORK tpwk)
                {
                    assert(tpwk == _tpwk);
                    while (cdata * d = _locklist.lockedget())
                    {
                        for (node* n = _nodelist; n; n = _nodelist.next(n))
                            d = n->t->doproc(d) 
                            ;
                        if (d)
                            TRACE_PIPE("filter doproc \n"), _datapipe->pipe(d);
                         
                    } 
                }
                singlylist _locklist;
            public:
                workfilter()
                {}
                virtual idatapipe * getp()
                {
                    return this;
                }
                virtual void pipe(cdata * d)
                {  
                    switch (_flag)
                    {
                    case 0:
                        if (nullptr == _locklist.lockedput(d))
                            SubmitThreadpoolWork(_tpwk);
                        break;
                    default:
                    {
                        long count = _locklist.count();
                        _locklist.lockedput(d);
                        if (0 < count && count <= _flag)
                            SubmitThreadpoolWork(_tpwk);
                    }
                    break;
                    } 
                }
            };
        public:
            parallel() : _parallel(offsetof(workfilter, next)),_refcount(0){}
            void setflag(long flag) {
                for (workfilter* n = _parallel; n; n = _parallel.next(n))
                    n->setflag(flag);
            }
            void push(ifilter *t)
            {
                ++_refcount;
                workfilter * wf = new workfilter(); 
                wf->push(t);
                _parallel.push(wf); 
            }
            virtual idatapipe * getp() 
            {
                return this;
            }
            virtual void setp(idatapipe * pipe)
            {
                idatapipe::setp(pipe);
                for (workfilter* n = _parallel; n; n = _parallel.next(n))
                    n->setp(pipe);
            }
            virtual void pipe(cdata * d)
            {  
                if (!_refcount)
                    _datapipe->pipe(d);
                else if (InterlockedDecrement(&d->_refcount) == 0)
                {
                    InterlockedExchange(&d->_refcount, _refcount);
                    for (workfilter* n = _parallel; n; n = _parallel.next(n))
                        n->pipe(d);
                }
            }
        private:
            linktype<workfilter> _parallel;
            long _refcount;
        }_twkfilter; 
        linktype<parallel> _workfilter;
        long _refcount;
    public:
        mainfilter():_workfilter(offsetof(parallel, next)), _refcount(0)
        {
            _workfilter.push(&_twkfilter);
        }   
        void setflag(long flag) {
            for (parallel* n = _workfilter; n; n = _workfilter.next(n))
                n->setflag((flag>>8) & 0xFF);
        }
        virtual idatapipe * getp() 
        { 
            return _twkfilter.getp();
        }; 
        virtual void setp(idatapipe * pipe)
        {
            idatapipe::setp(pipe); 
            _workfilter.get()->setp(_datapipe);
        }
        void push(ifilter* filters[])
        {  
            if (++_refcount > 1)
            {
                parallel * wf = new parallel();
                _workfilter.get()->setp(wf); 
                _workfilter.push(wf); 
            } 
            while (*filters) 
                _workfilter.get()->push(*filters++);  
            _workfilter.get()->setp(_datapipe);
        }
    }_twkfilter;
    class mainreport : public idatapipe
    {
        class workreport : public worksubmit<ireport>
        {
            virtual const char* name() { return "name:report"; } 
            virtual void run(PTP_CALLBACK_INSTANCE instance, PTP_WORK tpwk){
                assert(tpwk == _tpwk);
                while (cdata * d = _locklist.lockedget())
                {
                    for (node* n = _nodelist; n; n = _nodelist.next(n)) 
                        d = n->t->doproc(d)
                        ;  
                    if (d)
                        TRACE_PIPE("report doproc \n"), _datapipe->pipe(d);
                }
            }
            singlylist _locklist;
        public:
            workreport(){} 
            virtual void pipe(cdata * d)
            { 
                switch (_flag)
                {
                case 0:
                    if (nullptr == _locklist.lockedput(d))
                        SubmitThreadpoolWork(_tpwk);
                    break;
                default:  
                {
                    long count = _locklist.count();
                    _locklist.lockedput(d);
                    if(0 < count && count <= _flag)
                        SubmitThreadpoolWork(_tpwk);
                } 
                break;
                }
            }
        };
        linktype<workreport> _workreport;
        singlylist _locklist; 
        long _refcount;
    public:
        mainreport() : _workreport(offsetof(workreport, next)), _refcount(0)
        {
        }
        void setflag(long flag) {
            for (workreport* n = _workreport; n; n = _workreport.next(n))
                n->setflag((flag>>16) & 0xFF);
        }
        virtual idatapipe * getp()
        {
            return this;
        };
        void pipe(cdata * d)
        {  
            if (!_refcount)
                _datapipe->pipe(d);
            else if (InterlockedDecrement(&d->_refcount) == 0)
            {
                InterlockedExchange(&d->_refcount, _refcount);
                for (workreport* n = _workreport; n; n = _workreport.next(n))
                    n->pipe(d);
            }
        }
        void push(ireport* reports[])
        {
            ++_refcount;
            workreport * wr = new workreport();
            wr->setp(_datapipe); 
            while (*reports)
                wr->push(*reports++);
            _workreport.push(wr);
        } 
    }_twkreport;

    submitimpl()
        : _twkstream()
        , _twkfilter()
        , _twkreport()
    {
        _twkstream.setp(_twkfilter.getp());
        _twkfilter.setp(_twkreport.getp());
        _twkreport.setp(_twkstream.getp()); 
    } 
    void apply(istream* stream[], ifilter* filter[], ireport* report[])
    { 
        if (report)
            _twkreport.push(report);
        if (filter)
            _twkfilter.push(filter);
        if (stream)
            _twkstream.push(stream);
    }
    void start(long flag)
    {
        _twkreport.setflag(flag);
        _twkfilter.setflag(flag);
        _twkstream.setflag(flag);
        _twkstream.start();
    }
};
threadworker::threadworker()
    : _impl (nullptr)
{ 
}  
void threadworker::setup(int i) {
    _impl = i < 0 ? (threadworker::impl*)new submit::impl()
                  : (threadworker::impl*)new submitimpl();
    if (i < -100) {
        submit::produceobj::factory().closethread();
    }
}
threadworker::~threadworker()
{ 
    delete _impl;
} 
void threadworker::apply(istream* stream[], ifilter* filter[], ireport* report[])
{
    _impl->apply(stream, filter, report);
} 
void threadworker::submit(long flag)
{
    _impl->start(flag);
}
void threadworker::submit(cdata * d)
{
    _impl->start(d);
}

 

posted on 2019-08-14 16:16  静观海月  阅读(286)  评论(0编辑  收藏  举报