• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            CppExplore

            一切像霧像雨又像風(fēng)

              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              29 隨筆 :: 0 文章 :: 280 評(píng)論 :: 0 Trackbacks

            作者:CppExplore 網(wǎng)址:http://www.shnenglu.com/CppExplore/
            一、 基礎(chǔ)知識(shí)
            1、時(shí)間類型。
            Linux下常用的時(shí)間類型有4個(gè):time_t,struct timeval,struct timespec,struct tm。
            (1)time_t是一個(gè)長(zhǎng)整型,一般用來(lái)表示用1970年以來(lái)的秒數(shù)。
            (2)Struct timeval有兩個(gè)成員,一個(gè)是秒,一個(gè)是微妙。

            struct timeval {
                           
            long tv_sec;        /* seconds */
                           
            long tv_usec;  /* microseconds */
                   }
            ;

            (3)struct timespec有兩個(gè)成員,一個(gè)是秒,一個(gè)是納秒。

            struct timespec{
                                  time_t  tv_sec;         
            /* seconds */
                                  
            long    tv_nsec;        /* nanoseconds */
                          }
            ;

            (4)struct tm是直觀意義上的時(shí)間表示方法:

            struct tm {
                                  
            int     tm_sec;         /* seconds */
                                  
            int     tm_min;         /* minutes */
                                  
            int     tm_hour;        /* hours */
                                  
            int     tm_mday;        /* day of the month */
                                  
            int     tm_mon;         /* month */
                                  
            int     tm_year;        /* year */
                                  
            int     tm_wday;        /* day of the week */
                                  
            int     tm_yday;        /* day in the year */
                                  
            int     tm_isdst;       /* daylight saving time */
                          }
            ;

            2、 時(shí)間操作
            (1) 時(shí)間格式間的轉(zhuǎn)換函數(shù)
            主要是 time_t、struct tm、時(shí)間的字符串格式之間的轉(zhuǎn)換。看下面的函數(shù)參數(shù)類型以及返回值類型:

            char *asctime(const struct tm *tm);
            char *ctime(const time_t *timep);
            struct tm 
            *gmtime(const time_t *timep);
            struct tm 
            *localtime(const time_t *timep);
            time_t mktime(struct tm 
            *tm);

            gmtime和localtime的參數(shù)以及返回值類型相同,區(qū)別是前者返回的格林威治標(biāo)準(zhǔn)時(shí)間,后者是當(dāng)?shù)貢r(shí)間。
            (2) 獲取時(shí)間函數(shù)
            兩個(gè)函數(shù),獲取的時(shí)間類型看原型就知道了:

            time_t time(time_t *t);
            int gettimeofday(struct timeval *tv, struct timezone *tz);

            前者獲取time_t類型,后者獲取struct timeval類型,因?yàn)轭愋偷木壒剩罢咧荒芫_到秒,后者可以精確到微秒。
            二、 延遲函數(shù)
            主要的延遲函數(shù)有:sleep(),usleep(),nanosleep(),select(),pselect().

            unsigned int sleep(unsigned int seconds);
            void usleep(unsigned long usec);
            int nanosleep(const struct timespec *req, struct timespec *rem);
            int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout);
            int pselect(int   n,   fd_set   *readfds,  fd_set  *writefds,  fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);

            alarm函數(shù)是信號(hào)方式的延遲,這種方式不直觀,這里不說(shuō)了。
            僅通過(guò)函數(shù)原型中時(shí)間參數(shù)類型,可以猜測(cè)sleep可以精確到秒級(jí),usleep/select可以精確到微妙級(jí),nanosleep和pselect可以精確到納秒級(jí)。
            而實(shí)際實(shí)現(xiàn)中,linux上的nanosleep和alarm相同,都是基于內(nèi)核時(shí)鐘機(jī)制實(shí)現(xiàn),受linux內(nèi)核時(shí)鐘實(shí)現(xiàn)的影響,并不能達(dá)到納秒級(jí)的精度,man nanosleep也可以看到這個(gè)說(shuō)明,man里給出的精度是:Linux/i386上是10 ms ,Linux/Alpha上是1ms。
            這里有一篇文章http://blog.csdn.net/zhoujunyi/archive/2007/03/30/1546330.aspx,測(cè)試了不同延遲函數(shù)之間的精確度。文章給出的結(jié)論是linux上精度最高的是select,10ms級(jí)別。我在本機(jī)器測(cè)試select和pselect相當(dāng),都達(dá)到了1ms級(jí)的精度,精度高于文章中給出的10ms,sleep在秒級(jí)以上和usleep/nanosleep相當(dāng)。下面貼下我機(jī)器上1ms時(shí)候的測(cè)試結(jié)果,其他不貼了:

            sleep           1000          0      -1000 
            usleep           
            1000       2974       1974 
            nanosleep        
            1000       2990       1990 
            select           
            1000        991         -9 
            pselect           
            1000        990        -10 
            gettimeofday           
            1000       1000          0

            而使用gettimeofday循環(huán)不停檢測(cè)時(shí)間,可精確微秒級(jí),不過(guò)不適宜用來(lái)做定時(shí)器模塊。
            因此后面的定時(shí)期模塊將選擇select為延遲函數(shù)。
            三、 定時(shí)器模塊需求以及實(shí)現(xiàn)概述
            1、需求。從實(shí)現(xiàn)結(jié)果的角度說(shuō)來(lái),需求就是最終的使用方式。呵呵,不詳細(xì)描述需求了,先直接給出我實(shí)現(xiàn)的CTimer類的三個(gè)主要接口:

            Class CTimer{
            Public:
            CTimer(unsigned 
            int vinterval,void (*vfunc)(CTimer *,void *),void *vdata,TimerType vtype);
            void start();
            void stop();
            void reset(unsigned int vinterval);
            }
            ;

            使用定時(shí)器模塊的步驟如下:
            (1) 實(shí)例化一個(gè)CTimer,參數(shù)的含義依次是:vinterval間隔時(shí)間(單位ms),vfunc是時(shí)間到回調(diào)的函數(shù),vdata回調(diào)函數(shù)使用的參數(shù),vtype定時(shí)器的類型,分一次型和循環(huán)型兩種。
            (2) 調(diào)用start方法。
            (3) 必要的時(shí)候調(diào)用stop和reset。
            2、實(shí)現(xiàn)。簡(jiǎn)單描述下定時(shí)器模塊的實(shí)現(xiàn),有一個(gè)manager單例類保存所有CTimer對(duì)象,開(kāi)啟一線程運(yùn)行延遲函數(shù),每次延遲間隔到,掃描保存CTimer的容器,對(duì)每個(gè)CTimer對(duì)象執(zhí)行減少時(shí)間操作,減少到0則執(zhí)行回調(diào)函數(shù)。對(duì)一次性CTimer,超時(shí)則從容器中刪除,循環(huán)型的將間隔時(shí)間重置,不從容器中移除。
            CTimer的start執(zhí)行將對(duì)象插入到manager容器中操作;stop執(zhí)行將對(duì)象從manager容器中刪除的操作;reset執(zhí)行先刪除,重置間隔,然后再放到容器中,reset不改變CTimer的定時(shí)器類型屬性。
            四、 定時(shí)器模塊的數(shù)據(jù)結(jié)構(gòu)選擇
            Manager類的容器要頻繁進(jìn)行的操作涉及插入、刪除、查詢等。
            誤區(qū):(1)簡(jiǎn)單看,好象該容器要是有序的,方便插入刪除等,貌似紅黑樹(shù)比較合適。其實(shí)不然,插入刪除操作的頻率很低,最頻繁的還是每次時(shí)延到,對(duì)容器的掃描并做時(shí)間減少操作,紅黑樹(shù)在做順序掃描相對(duì)鏈表并沒(méi)什么優(yōu)勢(shì)。
            (2) 插入的時(shí)候依照順序鏈表的方式插入到合適的位置保持排序,以保證超時(shí)的對(duì)象都在鏈表的頭端。其實(shí)這也是沒(méi)必要的,每次時(shí)延到,對(duì)每一個(gè)對(duì)象都要做時(shí)間減少操作,因此不管是有序還是無(wú)序,都是一次掃描就執(zhí)行完下面操作:減少時(shí)間、判斷是否超時(shí),是則執(zhí)行回調(diào),繼續(xù)判斷是什么類型,一次型的則執(zhí)行完就移除,循環(huán)型則執(zhí)行完直接重置間隔就可。
            因此,只需要能快速插入頭、刪除結(jié)點(diǎn)、遍歷就好。我的實(shí)現(xiàn)直接使用BSD內(nèi)核中的數(shù)據(jù)結(jié)構(gòu)LIST,插入頭、刪除時(shí)間復(fù)雜度都是1,遍歷就不說(shuō)了。linux下/usr/include/sys下有頭文件queue.h里也有LIST結(jié)構(gòu)以及操作的定義。貌似linux下的少了遍歷宏:

            #define LIST_FOREACH(var, head, field)     \
             
            for((var) = LIST_FIRST(head);     \
                 (var)
            != LIST_END(head);     \
                 (var) 
            = LIST_NEXT(var, field))

            五、 詳細(xì)實(shí)現(xiàn)
            這里帖出主要的代碼,請(qǐng)重點(diǎn)關(guān)注CTimerManager:: process方法,不再詳細(xì)說(shuō)了。需要詳細(xì)的全部代碼,可來(lái)信索取,整體代碼很簡(jiǎn)單,就兩個(gè)類。

            class CTimer
            {
            friend 
            class CTimerManager;
            public:
                typedef 
            enum
                
            {
                    TIMER_IDLE
            =0,  //start前以及手動(dòng)調(diào)用stop后的狀態(tài)
                    TIMER_ALIVE,  //在manager的list里時(shí)候的狀態(tài)
                    TIMER_TIMEOUT  //超時(shí)后被移除的狀態(tài),循環(huán)型的沒(méi)有
                }
            TimerState;
                typedef 
            enum
                
            {
                    TIMER_ONCE
            =0,  //一次型
                    TIMER_CIRCLE   //循環(huán)型
                }
            TimerType;
                CTimer(unsigned 
            int vinterval,void (*vfunc)(CTimer *,void *),void *vdata,TimerType vtype);
                
            void start();
                
            void stop();
                
            void reset(unsigned int vinterval);
                
            ~CTimer();
            private:
                unsigned 
            int id_;     //測(cè)試用
                unsigned int m_interval;  //間隔,不變
                unsigned int m_counter;  //開(kāi)始設(shè)置為interval,隨延遲時(shí)間到,減少
                TimerState m_state;      //狀態(tài)
                TimerType m_type;        //類型
                void (*m_func)(CTimer *,void *);//回調(diào)函數(shù)
                void * m_data;  //回調(diào)函數(shù)參數(shù)
                LIST_ENTRY(CTimer) entry_;  //LIST的使用方式
            }
            ;
            /*構(gòu)造函數(shù)*/
            CTimer::CTimer(unsigned 
            int vinterval,void (*vfunc)(CTimer *,void *),void *vdata,TimerType vtype):

                m_interval(vinterval),m_counter(vinterval),
                m_state(TIMER_IDLE),m_type(vtype),
                m_func(vfunc),m_data(vdata)
            {}
            /*開(kāi)始定時(shí)器*/
            void CTimer::start()
            {
                CTimerManager::instance()
            ->add_timer(this);
            }

            /*停止定時(shí)器*/
            void CTimer::stop()
            {
                CTimerManager::instance()
            ->remove_timer(this);
            }

            /*reset定時(shí)器*/
            void CTimer::reset(unsigned int vinterval)
            {
                CTimerManager::instance()
            ->remove_timer(this);
                m_counter
            =m_interval=vinterval;
                CTimerManager::instance()
            ->add_timer(this);
            }

            /*析構(gòu)函數(shù),stop操作不能省略,避免delete前忘記stop*/
            CTimer::
            ~CTimer()
            {
                
            if(m_state==TIMER_ALIVE)
                    stop();
            }

            CTimerManager的:

            class CTimerManager
            {
            public:
                
                typedef 
            enum
                
            {
                    TIMER_MANAGER_STOP
            =0,
                    TIMER_MANAGER_START
                }
            TimerManagerState;
                
                
            static CTimerManager * instance();
                
            void add_timer(CTimer * vtimer);//線程安全的add
                void remove_timer(CTimer * vtimer);//線程安全的remove
                void start();  //開(kāi)始process線程
                void stop();  //停止process線程
                void dump();
            protected:
                
            static void * process(void *); //實(shí)際的定時(shí)器時(shí)間延遲線程
            private:    
                
            void add_timer_(CTimer * vtimer);//非線程安全的add
                void remove_timer_(CTimer * vtimer);//非線程安全的remove
                
                CTimerManager();
                
            static pthread_mutex_t m_mutex;
                
            static CTimerManager * m_instance;
                
                TimerManagerState m_state;
                LIST_HEAD(,CTimer) list_;  
            //LIST使用方式

                
            static unsigned int mark;  //測(cè)試,配合dump
            }
            ;
            /*singlton的double-check實(shí)現(xiàn)*/
            CTimerManager 
            * CTimerManager::instance()
            {
                
            if(m_instance==NULL)
                
            {
                    pthread_mutex_lock(
            &m_mutex);
                    
            if(m_instance==NULL)
                    
            {
                        m_instance
            =new CTimerManager();
                    }

                    pthread_mutex_unlock(
            &m_mutex);
                }

                
            return m_instance;
            }

            /*process必須static,不能操作非static屬性,因此傳遞this指針*/
            void CTimerManager:: start()
            {
                     if(m_state==TIMER_MANAGER_STOP){
                m_state
            =TIMER_MANAGER_START;
                pthread_t pid;
                pthread_create(
            &pid,0,process,this);
                  }
            }

            /*定時(shí)器模塊延遲時(shí)間線程*/
            void * CTimerManager:: process(void * arg)
            {
                pthread_detach(pthread_self());

                CTimerManager 
            *manage=(CTimerManager *)arg;

                CTimer 
            *item;
                struct timeval start,end;
                unsigned 
            int delay;
                
                struct timeval tm;
                gettimeofday(
            &end,0);
            /*使用狀態(tài)控制線程運(yùn)行,進(jìn)而容易實(shí)現(xiàn)stop,也可以使用pthread_cancel粗暴的停止,需要考慮暫停點(diǎn)等問(wèn)題*/
                
            while(manage->m_state==TIMER_MANAGER_START)
                
            {
                    tm.tv_sec
            =0;
                    tm.tv_usec
            =DEFULT_INTERVAL*1000;
                    start.tv_sec
            =end.tv_sec;
                    start.tv_usec
            =end.tv_usec;
            /*不同系統(tǒng)的延遲函數(shù)精度不同,如果需要替換為其他延遲函數(shù),這附近修改下就好*/
                    
            while(select(0,0,0,0,&tm)<0&&errno==EINTR);
                    gettimeofday(
            &end,0);

                    delay
            =(end.tv_sec-start.tv_sec)*1000+(end.tv_usec-start.tv_usec)/1000;
                    pthread_mutex_lock(
            &manage->m_mutex);

                    LIST_FOREACH(item, 
            &(manage->list_), entry_)
                    
            {
                        item
            ->m_counter<delay?item->m_counter=0:item->m_counter-=delay;
                        
            if(item->m_counter==0)
                        
            {
                            
            if(item->m_func)
                            item
            ->m_func(item,item->m_data);

                            
            if(item->m_type==CTimer::TIMER_ONCE)
                            
            {
            /*一次型的,超時(shí),移除,并狀態(tài)CTimer::TIMER_TIMEOUT*/
                                manage
            ->remove_timer_(item);
                                item
            ->m_state=CTimer::TIMER_TIMEOUT;
                            }

                            
            else if(item->m_type==CTimer::TIMER_CIRCLE)
                            
            {
            /*循環(huán)型的,重置counter就好*/
                                item
            ->m_counter=item->m_interval;
                            }

                        }

                    }


                    pthread_mutex_unlock(
            &manage->m_mutex);
                }

            }



            六、 討論
            (1)精度問(wèn)題。精度高,實(shí)時(shí)性高,但要求select等待的時(shí)間縮短,進(jìn)而增加對(duì)LIST結(jié)構(gòu)的掃描操作。精度低,實(shí)時(shí)性差,但會(huì)增加定時(shí)器線程的睡眠時(shí)間,減少對(duì)cpu的占用。一般的應(yīng)用系統(tǒng),應(yīng)該盡量降低精度,避免不必要的掃描,對(duì)具體系統(tǒng)可考察所用到的所有定時(shí)器的實(shí)際間隔,在允許的情況下,盡量降低精度,可通過(guò)修改代碼中的宏實(shí)現(xiàn)。為了降低定時(shí)器線程對(duì)cpu的占有時(shí)間,甚有更為粗獷型的定時(shí)器模塊實(shí)現(xiàn)為將延遲時(shí)間取list中最小的那個(gè)間隔,保證每次延遲時(shí)間到都有回調(diào)。
            (2)加鎖區(qū)域問(wèn)題。本文中的定時(shí)器模塊實(shí)現(xiàn),將定時(shí)器對(duì)象的時(shí)間減少以及函數(shù)回調(diào)的執(zhí)行等再同一個(gè)臨界區(qū)內(nèi)執(zhí)行,而有的定時(shí)器模塊實(shí)現(xiàn)是在加鎖區(qū)域執(zhí)行“時(shí)間減少”操作,將減少到0的對(duì)象放到另一個(gè)超時(shí)鏈表中,解鎖后再單獨(dú)掃描超時(shí)鏈表執(zhí)行回調(diào)操作。很明顯,后者縮短了加鎖時(shí)間,能及時(shí)響應(yīng)其他的線程的定時(shí)器對(duì)象的start以及stop操作。但是后者對(duì)定時(shí)器操作的時(shí)序性有誤差,直觀反應(yīng)就是可能在定時(shí)器執(zhí)行了stop操作以后,仍然會(huì)有超時(shí)回調(diào)發(fā)生,特別是回調(diào)參數(shù)是指針的情況,可能引起難以發(fā)現(xiàn)的bug,增加調(diào)試?yán)щy。在衡量?jī)烧叩睦缀螅疚牟捎醚娱L(zhǎng)加鎖時(shí)間以保證操作的時(shí)序性。因此,在實(shí)際的使用,回調(diào)函數(shù)應(yīng)盡快返回,另一方面,盡量減少系統(tǒng)內(nèi)使用的定時(shí)器數(shù)目,這個(gè)主要原因是延遲時(shí)間到要掃描LIST,哪種方式都避免不了。

            七、使用示例

            #include "timer_manager.h"
            #include 
            <stdio.h>
            #include 
            <unistd.h>
            #include 
            <stdlib.h>
            void func(CTimer * timer, void *data)
            {
                printf(
            "hi,%d\n",(int
            )(data));
            }

            /*隨便寫(xiě)的,湊合著看吧。沒(méi)有CTimerManager::instance()->stop();也沒(méi)new對(duì)象。定時(shí)器對(duì)象可多次start和stop,使用上對(duì)暴露的接口沒(méi)有任何的契約式限制,可隨意調(diào)用*/
            int main()
            {
                CTimerManager::instance()
            ->
            start();
                CTimer a(
            1000,func,(void *)1
            ,CTimer::TIMER_CIRCLE);
                CTimer a1(
            2000,func,(void *)11
            ,CTimer::TIMER_ONCE);
                CTimer a2(
            3000,func,(void *)12
            ,CTimer::TIMER_ONCE);
                CTimer a3(
            1000,func,(void *)13
            ,CTimer::TIMER_ONCE);
                
                a.start();
                a1.start();
                a2.start();
                a3.start();
                a.start();
                a1.start();
                a2.start();
                a3.start();

                sleep(
            1
            );
                CTimerManager::instance()
            ->
            dump();
                sleep(
            1
            );
                CTimerManager::instance()
            ->
            dump();
                a.reset(
            2000
            );
                a1.stop();
                a3.stop();

                sleep(
            10
            );
                
            return 0
            ;
            }

            八、后記
            昨晚寫(xiě)好文章,不知為何無(wú)故丟失大半,郁悶。今早醒來(lái),感覺(jué)還是有點(diǎn)地方要修改,:在start定時(shí)器線程的時(shí)候,傳入精度和誤差補(bǔ)償,一是根據(jù)實(shí)際需要調(diào)整精確度,二是彌補(bǔ)延遲函數(shù)的稍許誤差,以具有更好的伸縮性和精確度。本文旨在說(shuō)明定時(shí)器模塊的內(nèi)部實(shí)現(xiàn)機(jī)制,詳細(xì)細(xì)節(jié)不再修改了。
            posted on 2008-04-02 23:19 cppexplore 閱讀(12982) 評(píng)論(31)  編輯 收藏 引用

            評(píng)論

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器 2008-04-02 23:33 Colin
            精度是個(gè)問(wèn)題啊。。  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器 2008-04-02 23:49 cppexplore
            @Colin
            你可真快啊,我有個(gè)習(xí)慣:把寫(xiě)的丟失,中途會(huì)提交,然后再修改再提交直到結(jié)束。最后寫(xiě)完,就已經(jīng)有回復(fù)了,呵呵。
            精度問(wèn)題,只能在系統(tǒng)能力之內(nèi)盡量了,一般的應(yīng)用server非實(shí)時(shí)性很強(qiáng)的系統(tǒng)需要不了微秒級(jí)的精度,我的實(shí)際應(yīng)用秒級(jí)夠了。
              回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器 2008-04-03 00:04 Colin
            @cppexplore
            睡覺(jué)前看了一下。

            以前在bsd下做過(guò)一個(gè)性能測(cè)試程序,就為精度問(wèn)題頭痛了很久。。
              回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器 2008-04-03 00:08 cppexplore
            @Colin
            呵呵,你的精度要求太高了。零點(diǎn)了,該睡了。8888  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器[未登錄](méi) 2008-04-03 14:07 創(chuàng)
            收藏.
              回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器 2008-04-03 16:40 kw
            每次都循環(huán)整個(gè)鏈表,效率似乎不高吧。   回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器 2008-04-03 16:45 cppexplore
            @kw
            呵呵,想了下,真是不高啊。
            直接保存gettimeoftime()+interval的時(shí)間做間隔,并在LIST中排序應(yīng)該是最好的方法。  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器 2008-04-03 16:55 eXile
            不知老兄有沒(méi)有研究過(guò)boost::asio的定時(shí)器定現(xiàn), 好象用的也是select  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】系統(tǒng)設(shè)計(jì)之 定時(shí)器(一)[未登錄](méi) 2008-04-03 21:59 cppexplore
            @eXile
            第三方庫(kù)中的定時(shí)器實(shí)現(xiàn)還沒(méi)看呢,以后有時(shí)間整理下。最近是不準(zhǔn)備研究了。  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2008-11-25 13:40 卡通服裝
            要求都好高  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2008-11-27 18:50 Song
            Hi, 可以發(fā)一份源碼給我嗎?

            leezjs[at]gmail.com

            謝謝  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2009-04-15 13:11 包裝機(jī)
            這個(gè)要求不算高吧  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2009-07-27 12:59 套袋收縮機(jī)
            路過(guò),走走  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2009-08-04 21:21 farman
            看完很有收獲,寫(xiě)的非常好,贊一個(gè)!
            提點(diǎn)意見(jiàn),建議定時(shí)器隊(duì)列不要用動(dòng)態(tài)內(nèi)存的鏈表,最好限制一下系統(tǒng)中最大定時(shí)器個(gè)數(shù)。  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2009-08-26 11:46 四海游魚(yú)
            可以發(fā)一份兒給我嗎?
            我的郵箱是 zshuming@yahoo.cn  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2009-08-31 17:44 shiqyn
            不錯(cuò),支持樓主。  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2009-12-27 16:31 難得糊涂
            好像已經(jīng)過(guò)了一年了,請(qǐng)問(wèn)還能發(fā)一份么,謝謝
            usetowork@163.com  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2010-07-20 14:04 Plocklsh
            又過(guò)了半年了,還能把源碼發(fā)一份給我嘛,謝謝了,416573704@qq.com  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一)[未登錄](méi) 2010-08-30 10:21 by
            是的,排序LIST之后,只要進(jìn)行一次判斷就行了,就不用循環(huán)判斷了。  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2012-03-08 13:30 aiolia
            guyaping1234@163.com,還可以發(fā)一份源碼嗎??  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2012-07-12 15:51 maimai
            maimai2009@126.com
            還可以發(fā)一份源碼嗎??
            謝謝了!  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一)[未登錄](méi) 2012-07-26 16:43 rpg_kiss
            您好!rpg_kill@foxmail.com
            能發(fā)一份源代碼嗎,謝謝!  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2012-12-09 20:33 ZeroClock
            你的代碼寫(xiě)得很漂亮。
            能發(fā)份原碼給我欣賞學(xué)習(xí)下嗎?
            353230424@qq.com
            謝謝  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2012-12-12 11:06 lala
            能給我發(fā)一份源代碼
            laba1022@yahoo.com.cn
            謝謝  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一)[未登錄](méi) 2012-12-13 12:00 gary
            lb2421428@126.com 望能提供代碼研究  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2012-12-21 14:48 arbin
            arbin00@gmail.com 謝謝  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2012-12-23 09:38 cppexplore
            當(dāng)年寫(xiě)的這么一個(gè)垃圾實(shí)現(xiàn), 大家就不要再繼續(xù)留言了 呵呵  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2013-07-03 17:37 詎訌
            三年了啊。三年了。哈哈  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2014-10-21 17:26 rqf
            給我一個(gè)啊,r187@foxmail.com  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一) 2014-10-21 17:30 rqf
            謝謝拉  回復(fù)  更多評(píng)論
              

            # re: 【原創(chuàng)】技術(shù)系列之 定時(shí)器(一)[未登錄](méi) 2014-10-23 14:37 cppexplore
            @rqf
            說(shuō)實(shí)話,本文本質(zhì)很垃圾  回復(fù)  更多評(píng)論
              


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            东方aⅴ免费观看久久av| 亚洲午夜精品久久久久久浪潮 | 一本大道久久东京热无码AV| 精品久久久久久国产三级| 亚洲精品国产第一综合99久久| 亚洲精品99久久久久中文字幕| 久久精品国产亚洲AV香蕉| 亚洲色欲久久久综合网| 草草久久久无码国产专区| 久久性精品| 国产成人久久AV免费| 久久综合色之久久综合| 久久久久高潮毛片免费全部播放| 国产午夜电影久久| 亚洲AV无码一区东京热久久| 久久久久久亚洲精品不卡| 久久99热只有频精品8| 欧美成人免费观看久久| 97久久精品人人澡人人爽| 久久水蜜桃亚洲av无码精品麻豆 | 精品免费久久久久久久| 久久99精品久久久久久噜噜| 色欲综合久久躁天天躁蜜桃| 亚洲国产日韩欧美久久| 免费国产99久久久香蕉| 久久亚洲精品国产精品| 久久无码国产专区精品| 欧美午夜A∨大片久久| 精品久久久久久无码国产| 国产精品久久久久…| 久久精品国产亚洲AV无码麻豆 | 狠狠色综合网站久久久久久久高清 | 无码人妻久久一区二区三区 | 人妻无码αv中文字幕久久| 久久精品免费全国观看国产| 亚洲人成网站999久久久综合| 久久婷婷五月综合97色直播| 久久精品视屏| 性做久久久久久久久浪潮| 99久久99久久精品国产片果冻| 四虎国产精品免费久久|