亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

利用ace的ACE_Task等類實現線程池的方法詳解

2020-01-26 16:01:58
字體:
來源:轉載
供稿:網友
本代碼應該是ace自帶的例子了,但是我覺得是非常好的,于是給大家分享一下。
注釋非常詳細啊。
頭文件
復制代碼 代碼如下:

#ifndef THREAD_POOL_H
#define THREAD_POOL_H
/* In order to implement a thread pool, we have to have an object that
   can create a thread.  The ACE_Task<> is the basis for doing just
   such a thing.  */
#include "ace/Task.h"
//add by ychen 20070714 below
#include "ace/Mutex.h"
//add by ychen 20070714 above
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
/* We need a forward reference for ACE_Event_Handler so that our
   enqueue() method can accept a pointer to one.  */

class ACE_Event_Handler;
/* Although we modified the rest of our program to make use of the
   thread pool implementation, if you look closely you'll see that the
   changes were rather minor.  The "ACE way" is generally to create a
   helper object that abstracts away the details not relevant to your
   application.  That's what I'm trying to do here by creating the
   Thread_Pool object.  */
class Thread_Pool : public ACE_Task<ACE_MT_SYNCH>
{
public:
  typedef ACE_Task<ACE_MT_SYNCH> inherited;
  /* Provide an enumeration for the default pool size.  By doing this,
    other objects can use the value when they want a default.  */
  enum size_t
  {
    default_pool_size_ = 1
  };
  // Basic constructor
  Thread_Pool (void);
  /* Opening the thread pool causes one or more threads to be
    activated.  When activated, they all execute the svc() method
    declared below.  */
  int open (int pool_size = default_pool_size_);
  /* Some compilers will complain that our open() above attempts to
    override a virtual function in the baseclass.  We have no
    intention of overriding that method but in order to keep the
    compiler quiet we have to add this method as a pass-thru to the
    baseclass method.  */
  virtual int open (void *void_data)
  {
    return inherited::open (void_data);
  }
  /*
   */
  virtual int close (u_long flags = 0);
  /* To use the thread pool, you have to put some unit of work into
    it.  Since we're dealing with event handlers (or at least their
    derivatives), I've chosen to provide an enqueue() method that
    takes a pointer to an ACE_Event_Handler.  The handler's
    handle_input() method will be called, so your object has to know
    when it is being called by the thread pool.  */
  int enqueue (ACE_Event_Handler *handler);
  /* Another handy ACE template is ACE_Atomic_Op<>.  When
    parameterized, this allows is to have a thread-safe counting
    object.  The typical arithmetic operators are all internally
    thread-safe so that you can share it across threads without
    worrying about any contention issues.  */
    typedef ACE_Atomic_Op<ACE_Mutex, int> counter_t;

protected:
  /* Our svc() method will dequeue the enqueued event handler objects
    and invoke the handle_input() method on each.  Since we're likely
    running in more than one thread, idle threads can take work from
    the queue while other threads are busy executing handle_input() on
    some object.  */
  int svc (void);
  /* We use the atomic op to keep a count of the number of threads in
    which our svc() method is running.  This is particularly important
    when we want to close() it down!  */
  counter_t active_threads_;
};
#endif /* THREAD_POOL_H */

實現文件
復制代碼 代碼如下:

// thread_pool.cpp,v 1.9 1999/09/22 03:13:42 jcej Exp
#include "thread_pool.h"
/* We need this header so that we can invoke handle_input() on the
   objects we dequeue.  */
#include "ace/Event_Handler.h"
/* All we do here is initialize our active thread counter.  */
Thread_Pool::Thread_Pool (void)
  : active_threads_ (0)
{
}
/* Our open() method is a thin disguise around the ACE_Task<>
   activate() method.  By hiding activate() in this way, the users of
   Thread_Pool don't have to worry about the thread configuration
   flags.  */
int
Thread_Pool::open (int pool_size)
{
  return this->activate (THR_NEW_LWP|THR_DETACHED, pool_size);
}
/* Closing the thread pool can be a tricky exercise.  I've decided to
   take an easy approach and simply enqueue a secret message for each
   thread we have active.  */
int
Thread_Pool::close (u_long flags)
{
  ACE_UNUSED_ARG(flags);
  /* Find out how many threads are currently active */
  int counter = active_threads_.value ();
  /* For each one of the active threads, enqueue a "null" event
    handler.  Below, we'll teach our svc() method that "null" means
    "shutdown".  */
  while (counter--)
    this->enqueue (0);
  /* As each svc() method exits, it will decrement the active thread
    counter.  We just wait here for it to reach zero.  Since we don't
    know how long it will take, we sleep for a quarter of a second
    between tries.  */
  while (active_threads_.value ())
    ACE_OS::sleep (ACE_Time_Value (0, 250000));
  return(0);
}
/* When an object wants to do work in the pool, it should call the
   enqueue() method.  We introduce the ACE_Message_Block here but,
   unfortunately, we seriously misuse it.  */
int
Thread_Pool::enqueue (ACE_Event_Handler *handler)
{
  /* An ACE_Message_Block is a chunk of data.  You put them into an
    ACE_Message_Queue.  ACE_Task<> has an ACE_Message_Queue built in.
    In fact, the parameter to ACE_Task<> is passed directly to
    ACE_Message_Queue.  If you look back at our header file you'll see
    that we used ACE_MT_SYNCH as the parameter indicating that we want
    MultiThread Synch safety.  This allows us to safely put
    ACE_Message_Block objects into the message queue in one thread and
    take them out in another.  */
  /* An ACE_Message_Block wants to have char* data.  We don't have
    that.  We could cast our ACE_Event_Handler* directly to a char*
    but I wanted to be more explicit.  Since casting pointers around
    is a dangerous thing, I've gone out of my way here to be very
    clear about what we're doing.
    First: Cast the handler pointer to a void pointer.  You can't do
    any useful work on a void pointer, so this is a clear message that
    we're making the pointer unusable.
    Next: Cast the void pointer to a char pointer that the ACE_Message_Block will accept.  */
  void *v_data = (void *) handler;
  char *c_data = (char *) v_data;
  ACE_Message_Block *mb;
  /* Construct a new ACE_Message_Block.  For efficiency, you might
    want to preallocate a stack of these and reuse them.  For
    simplicity, I'll just create what I need as I need it.  */
  ACE_NEW_RETURN (mb,
                  ACE_Message_Block (c_data),
                  -1);
  /* Our putq() method is a wrapper around one of the enqueue methods
    of the ACE_Message_Queue that we own.  Like all good methods, it
    returns -1 if it fails for some reason.  */
  if (this->putq (mb) == -1)
    {
      /* Another trait of the ACE_Message_Block objects is that they
        are reference counted.  Since they're designed to be passed
        around between various objects in several threads we can't
        just delete them whenever we feel like it.  The release()
        method is similar to the destroy() method we've used
        elsewhere.  It watches the reference count and will delete the
        object when possible.  */
      mb->release ();
      return -1;
    }
  return 0;
}
/* The "guard" concept is very powerful and used throughout
   multi-threaded applications.  A guard normally does some operation
   on an object at construction and the "opposite" operation at
   destruction.  For instance, when you guard a mutex (lock) object,
   the guard will acquire the lock on construction and release it on
   destruction.  In this way, your method can simply let the guard go
   out of scope and know that the lock is released.
   Guards aren't only useful for locks however.  In this application
   I've created two guard objects for quite a different purpose.  */
/* The Counter_Guard is constructed with a reference to the thread
   pool's active thread counter.  The guard increments the counter
   when it is created and decrements it at destruction.  By creating
   one of these in svc(), I know that the counter will be decremented
   no matter how or where svc() returns.  */
class Counter_Guard
{
public:
  Counter_Guard (Thread_Pool::counter_t &counter)
    : counter_ (counter)
  {
    ++counter_;
  }
  ~Counter_Guard (void)
  {
    --counter_;
  }
protected:
  Thread_Pool::counter_t &counter_;
};
/* My Message_Block_Guard is also a little non-traditional.  It
   doesn't do anything in the constructor but it's destructor ensures
   that the message block's release() method is called.  This is a
   cheap way to prevent a memory leak if I need an additional exit
   point in svc().  */
class Message_Block_Guard
{
public:
  Message_Block_Guard (ACE_Message_Block *&mb)
    : mb_ (mb)
  {
  }
  ~Message_Block_Guard (void)
  {
    mb_->release ();
  }
protected:
  ACE_Message_Block *&mb_;
};
/* Now we come to the svc() method.  As I said, this is being executed
   in each thread of the Thread_Pool.  Here, we pull messages off of
   our built-in ACE_Message_Queue and cause them to do work.  */
int
Thread_Pool::svc (void)
{
  /* The getq() method takes a reference to a pointer.  So... we need
    a pointer to give it a reference to.  */
  ACE_Message_Block *mb;
  /* Create the guard for our active thread counter object.  No matter
    where we choose to return() from svc(), we now know that the
    counter will be decremented.  */
  Counter_Guard counter_guard (active_threads_);
  /* Get messages from the queue until we have a failure.  There's no
    real good reason for failure so if it happens, we leave
    immediately.  */
  while (this->getq (mb) != -1)
    {
      /* A successful getq() will cause "mb" to point to a valid
        refernce-counted ACE_Message_Block.  We use our guard object
        here so that we're sure to call the release() method of that
        message block and reduce it's reference count.  Once the count
        reaches zero, it will be deleted.  */
      Message_Block_Guard message_block_guard (mb);
      /* As noted before, the ACE_Message_Block stores it's data as a
        char*.  We pull that out here and later turn it into an
        ACE_Event_Handler* */
      char *c_data = mb->base ();
      /* We've chosen to use a "null" value as an indication to leave.
        If the data we got from the queue is not null then we have
        some work to do.  */
      if (c_data)
        {
          /* Once again, we go to great lengths to emphasize the fact
            that we're casting pointers around in rather impolite
            ways.  We could have cast the char* directly to an
            ACE_Event_Handler* but then folks might think that's an OK
            thing to do.
            (Note: The correct way to use an ACE_Message_Block is to
            write data into it.  What I should have done was create a
            message block big enough to hold an event handler pointer
            and then written the pointer value into the block.  When
            we got here, I would have to read that data back into a
            pointer.  While politically correct, it is also a lot of
            work.  If you're careful you can get away with casting
            pointers around.)  */
          void *v_data = (void *) c_data;
          ACE_Event_Handler *handler = (ACE_Event_Handler *) v_data;
          /* Now that we finally have an event handler pointer, invoke
            it's handle_input() method.  Since we don't know it's
            handle, we just give it a default.  That's OK because we
            know that we're not using the handle in the method anyway.  */
          if (handler->handle_input (ACE_INVALID_HANDLE) == -1)
            {
              /* Tell the handler that it's time to go home.  The
                "normal" method for shutting down a handler whose
                handler failed is to invoke handle_close().  This will
                take care of cleaning it up for us.  Notice how we use
                the handler's get_handle() method to populate it's
                "handle" parameter.  Convenient isn't it?  */
              handler->handle_close (handler->get_handle (), 0);
              /* Also notice that we don't exit the svc() method here!
                The first time I did this, I was exiting.  After a few
                clients disconnect you have an empty thread pool.
                Hard to do any more work after that...  */
            }
        }
      else
        /* If we get here, we were given a message block with "null"
           data.  That is our signal to leave, so we return(0) to
           leave gracefully.  */
          return 0;  // Ok, shutdown request
      // message_block_guard goes out of scope here and releases the
      // message_block instance.
    }
  return 0;
}

其中,對其中類中的兩個變量使用了管理的思想。Counter_Guard類和Message_Block_Guard 類分別對其進行了管理。
因為ACE_Task類是使用了ACE_message_block 進行對消息的封裝。因此使用類,防止了內存的泄漏。
ACE_Event_Handler  是事件句柄,類似于操作符。當我們處理的時候,對其進行處理。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品视频1区| 日韩av在线直播| 92看片淫黄大片看国产片| 国产一区二区三区毛片| 国内精久久久久久久久久人| 久久久www成人免费精品| 91精品在线观看视频| 日韩精品视频中文在线观看| 亚洲欧洲在线免费| 欧美最猛黑人xxxx黑人猛叫黄| 91色在线观看| 欧美视频在线观看免费| 成人免费大片黄在线播放| 精品国产一区久久久| 日韩亚洲欧美中文高清在线| 中文欧美日本在线资源| 亚洲美女免费精品视频在线观看| 91精品国产91久久久久久最新| 久久精品国产成人精品| 亚洲精品视频免费在线观看| 另类视频在线观看| 欧美老妇交乱视频| 欧美日本高清一区| 国产精品99蜜臀久久不卡二区| 国产极品精品在线观看| 久久久噜噜噜久久中文字免| 日韩电影中文字幕在线| 亚洲欧美精品一区| 成人黄色片网站| 亚洲自拍偷拍在线| 久久九九有精品国产23| 亚洲精品456在线播放狼人| 国产日韩欧美另类| 欧美成人午夜激情| 九九九热精品免费视频观看网站| 国产99久久精品一区二区 夜夜躁日日躁| 午夜精品久久久久久99热软件| 亚洲免费电影一区| 日韩av在线免费| 日韩av电影手机在线观看| 精品国偷自产在线视频99| 国产精品入口日韩视频大尺度| 97香蕉久久夜色精品国产| 日韩在线资源网| 97色伦亚洲国产| 成人有码视频在线播放| 欧美色图在线视频| 亚洲美腿欧美激情另类| 91亚洲国产成人精品性色| 欧美一级高清免费播放| 不卡伊人av在线播放| 亚洲成人激情视频| 在线视频免费一区二区| 亚洲第一区中文99精品| 欧美性生活大片免费观看网址| 久久精品91久久久久久再现| 91精品国产777在线观看| 欧美xxxx综合视频| 欧美电影免费观看高清| 国产亚洲视频中文字幕视频| 在线免费观看羞羞视频一区二区| 欧洲中文字幕国产精品| 国产精品精品国产| 97超级碰碰人国产在线观看| www.99久久热国产日韩欧美.com| 91精品国产高清久久久久久91| 91精品国产综合久久久久久蜜臀| 亚洲日韩中文字幕| 国产成人精品视| 黑人与娇小精品av专区| 91久久久精品| 在线看欧美日韩| 久久久女女女女999久久| 国产一级揄自揄精品视频| 国产97免费视| 亚洲最大中文字幕| 亚洲午夜小视频| 中文字幕av一区二区| 91中文字幕在线| 日韩成人在线视频观看| 91亚洲人电影| 亚洲护士老师的毛茸茸最新章节| 欧美日韩国产精品专区| 亚洲精品中文字| 精品亚洲一区二区三区| 欧美成人午夜激情视频| 国产精品入口尤物| 全亚洲最色的网站在线观看| 91精品国产沙发| 欧美午夜电影在线| 久久这里只有精品99| 国产精品欧美日韩一区二区| 亚洲www在线观看| 4438全国亚洲精品在线观看视频| 久久久久久久一区二区三区| 亚洲色图18p| 日韩美女在线观看一区| 国产精品欧美风情| 人人澡人人澡人人看欧美| 伊人伊人伊人久久| 亚洲欧美国产另类| 久久影院免费观看| 中文欧美在线视频| 欧美色视频日本高清在线观看| 成人黄色av网| 亚洲国产欧美在线成人app| 国内免费久久久久久久久久久| 日日狠狠久久偷偷四色综合免费| 亚洲精品www久久久久久广东| 亚洲人成在线观看网站高清| 亚洲а∨天堂久久精品喷水| 欧美小视频在线| 欧美老少做受xxxx高潮| 亚洲在线观看视频网站| 色综合久久中文字幕综合网小说| 欧美成年人视频网站| 亚洲人成网7777777国产| 91亚洲精华国产精华| 日韩精品中文字幕久久臀| 国产亚洲欧美另类中文| 精品中文字幕久久久久久| 成人黄色在线免费| 欧美日韩国产中文精品字幕自在自线| 91精品国产综合久久香蕉的用户体验| 欧美一级视频免费在线观看| 亚洲成人黄色网| 欧美中文字幕第一页| 78色国产精品| 日韩高清有码在线| 欧美裸体男粗大视频在线观看| 亚洲最新中文字幕| 日韩av在线网站| 久久人人看视频| 国产91露脸中文字幕在线| 国模精品视频一区二区| 亚洲va欧美va国产综合剧情| 日韩av影院在线观看| 成人免费福利在线| 欧美精品亚州精品| 亚洲欧洲日产国产网站| 国产va免费精品高清在线观看| 国产精品一区二区久久久| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲欧洲在线免费| 亚洲成人av片在线观看| 中文字幕国产亚洲| 91精品视频播放| 中文字幕av一区二区三区谷原希美| 91精品国产乱码久久久久久久久| 久久精品视频导航| 成人性生交xxxxx网站| 久久人91精品久久久久久不卡| 亚洲资源在线看| 欧美二区乱c黑人| 国产主播精品在线| 国产精品爽爽爽| 97成人在线视频| 亚洲图片欧洲图片av| 欧美多人爱爱视频网站| 日本19禁啪啪免费观看www| 成人欧美一区二区三区在线湿哒哒| 69**夜色精品国产69乱| 国产成人精品在线播放| 久久久久久久网站|