ACE_Thread_Manager-------ACE线程管理

本文详细介绍了ACE线程管理器的使用方法及内部实现原理,包括如何启动、等待线程,以及线程管理器提供的各种高级功能如取消、挂起和恢复线程等。
部署运行你感兴趣的模型镜像

在一个ACE项目中使用线程是再常见不过了。然而ACE线程做到了很好的管理。使用了ACE_Thread_Manager封装了很多东西。

该类是将启动的线程放到了一个双向链表里进行管理的。

当我们想启动一个线程的时候,我们就可以这样的使用

启动线程:

void* func(void*);

ACE_Thread_Manager::instance()->spawn(ACE_THR_FUNC(func), 0, THR_NEW_LWP); 

线程阻塞,等待子线程退出:

ACE_Thread_Manager::instance()->wait();

ACE_Thread_Manager使用了单例模式。

ACE_Thread_Manager代码展示

带参构造函数

ACE_Thread_Manager::ACE_Thread_Manager (size_t prealloc,
                                        size_t lwm,
                                        size_t inc,
                                        size_t hwm)
  : grp_id_ (1),
    automatic_wait_ (1)
#if defined (ACE_HAS_THREADS)
    , zero_cond_ (lock_)
#endif /* ACE_HAS_THREADS */
    , thread_desc_freelist_ (ACE_FREE_LIST_WITH_POOL,
                             prealloc, lwm, hwm, inc)
{
  ACE_TRACE ("ACE_Thread_Manager::ACE_Thread_Manager");
}


单例模式函数:

其中他ACE_Thread_Manager::delete_thr_mgr_ 布尔变量,当实例化的时候,设置true。

#if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
ACE_Thread_Manager *
ACE_Thread_Manager::instance (void)
{
  ACE_TRACE ("ACE_Thread_Manager::instance");

  if (ACE_Thread_Manager::thr_mgr_ == 0)
    {
      // Perform Double-Checked Locking Optimization.
      ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
                                *ACE_Static_Object_Lock::instance (), 0));

      if (ACE_Thread_Manager::thr_mgr_ == 0)
        {
          ACE_NEW_RETURN (ACE_Thread_Manager::thr_mgr_,
                          ACE_Thread_Manager,
                          0);
          ACE_Thread_Manager::delete_thr_mgr_ = true;
        }
    }

  return ACE_Thread_Manager::thr_mgr_;
}

ACE_Thread_Manager *
ACE_Thread_Manager::instance (ACE_Thread_Manager *tm)
{
  ACE_TRACE ("ACE_Thread_Manager::instance");
  ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
                            *ACE_Static_Object_Lock::instance (), 0));

  ACE_Thread_Manager *t = ACE_Thread_Manager::thr_mgr_;
  // We can't safely delete it since we don't know who created it!
  ACE_Thread_Manager::delete_thr_mgr_ = false;

  ACE_Thread_Manager::thr_mgr_ = tm;
  return t;
}

清除实例对象:

void
ACE_Thread_Manager::close_singleton (void)
{
  ACE_TRACE ("ACE_Thread_Manager::close_singleton");

  ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
                     *ACE_Static_Object_Lock::instance ()));

  if (ACE_Thread_Manager::delete_thr_mgr_)
    {
      // First, we clean up the thread descriptor list.
      ACE_Thread_Manager::thr_mgr_->close ();
      delete ACE_Thread_Manager::thr_mgr_;
      ACE_Thread_Manager::thr_mgr_ = 0;
      ACE_Thread_Manager::delete_thr_mgr_ = false;
    }

  ACE_Thread_Exit::cleanup (ACE_Thread_Manager::thr_exit_);
}


析构函数,清除对象:

int
ACE_Thread_Manager::close ()
{
  ACE_TRACE ("ACE_Thread_Manager::close");

  // Clean up the thread descriptor list.
  if (this->automatic_wait_)
    this->wait (0, 1);
  else
    {
      ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));

      this->remove_thr_all ();
    }

  return 0;
}

ACE_Thread_Manager::~ACE_Thread_Manager (void)
{
  ACE_TRACE ("ACE_Thread_Manager::~ACE_Thread_Manager");
  this->close ();
}
void
ACE_Thread_Manager::remove_thr_all (void)
{
  ACE_Thread_Descriptor *td = 0;

  while ((td = this->thr_list_.delete_head ()) != 0)
    {
      this->remove_thr (td, 1);
    }
}


线程启动函数:

简单介绍一下参数:
func:线程函数,不用多数
args:线程函数参数,
flags:线程的属性控制Flags to control attributes of the spawned threads.
   *                    @sa ACE_OS::thr_create() for descriptions of the
   *                    possible flags values and their interactions.
t_id:线程id
t_handle: Pointer to a location to receive the spawned thread's
   *                    thread handle. If 0, the handle is not returned.
priority:线程的优先级
grp_id:组id
stack:线程栈 stack_size:栈大小
 
size_t n:启动几次线程
int
ACE_Thread_Manager::spawn (ACE_THR_FUNC func,
                           void *args,
                           long flags,
                           ACE_thread_t *t_id,
                           ACE_hthread_t *t_handle,
                           long priority,
                           int grp_id,
                           void *stack,
                           size_t stack_size,
                           const char** thr_name)
{
  ACE_TRACE ("ACE_Thread_Manager::spawn");

  ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));

  if (grp_id == -1)
    grp_id = this->grp_id_++; // Increment the group id.

  if (priority != ACE_DEFAULT_THREAD_PRIORITY)
    ACE_CLR_BITS (flags, THR_INHERIT_SCHED);

  if (this->spawn_i (func,
                     args,
                     flags,
                     t_id,
                     t_handle,
                     priority,
                     grp_id,
                     stack,
                     stack_size,
                     0,
                     thr_name) == -1)
    return -1;

  return grp_id;
}

// Create N new threads running FUNC.

int
ACE_Thread_Manager::spawn_n (size_t n,
                             ACE_THR_FUNC func,
                             void *args,
                             long flags,
                             long priority,
                             int grp_id,
                             ACE_Task_Base *task,
                             ACE_hthread_t thread_handles[],
                             void *stack[],
                             size_t stack_size[],
                             const char* thr_name[])
{
  ACE_TRACE ("ACE_Thread_Manager::spawn_n");
  ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));

  if (grp_id == -1)
    grp_id = this->grp_id_++; // Increment the group id.

  for (size_t i = 0; i < n; i++)
    {
      // @@ What should happen if this fails?! e.g., should we try to
      // cancel the other threads that we've already spawned or what?
      if (this->spawn_i (func,
                         args,
                         flags,
                         0,
                         thread_handles == 0 ? 0 : &thread_handles[i],
                         priority,
                         grp_id,
                         stack == 0 ? 0 : stack[i],
                         stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
                         task,
                         thr_name == 0 ? 0 : &thr_name [i]) == -1)
        return -1;
    }

  return grp_id;
}

// Create N new threads running FUNC.

int
ACE_Thread_Manager::spawn_n (ACE_thread_t thread_ids[],
                             size_t n,
                             ACE_THR_FUNC func,
                             void *args,
                             long flags,
                             long priority,
                             int grp_id,
                             void *stack[],
                             size_t stack_size[],
                             ACE_hthread_t thread_handles[],
                             ACE_Task_Base *task,
                             const char* thr_name[])
{
  ACE_TRACE ("ACE_Thread_Manager::spawn_n");
  ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));

  if (grp_id == -1)
    grp_id = this->grp_id_++; // Increment the group id.

  for (size_t i = 0; i < n; i++)
    {
      // @@ What should happen if this fails?! e.g., should we try to
      // cancel the other threads that we've already spawned or what?
      if (this->spawn_i (func,
                         args,
                         flags,
                         thread_ids == 0 ? 0 : &thread_ids[i],
                         thread_handles == 0 ? 0 : &thread_handles[i],
                         priority,
                         grp_id,
                         stack == 0 ? 0 : stack[i],
                         stack_size == 0 ? ACE_DEFAULT_THREAD_STACKSIZE : stack_size[i],
                         task,
                         thr_name == 0 ? 0 : &thr_name [i]) == -1)
        return -1;
    }

  return grp_id;
}

下面是函数,更具其名字应该能知道线程管理的意义了:

 ACE_THR_FUNC_RETURN exit (ACE_THR_FUNC_RETURN status = 0,
                            bool do_thread_exit = true);

  /**
   * Block until there are no more threads running in this thread
   * manager or @c timeout expires.
   *
   * @param timeout is treated as "absolute" time by default, but this
   *                can be changed to "relative" time by setting the @c
   *                use_absolute_time to false.
   * @param abandon_detached_threads If true, @c wait() will first
   *                                 check thru its thread list for
   *                                 threads with THR_DETACHED or
   *                                 THR_DAEMON flags set and remove
   *                                 these threads.  Notice that
   *                                 unlike other @c wait_*() methods,
   *                                 by default, @c wait() does wait on
   *                                 all thread spawned by this
   *                                 thread manager no matter the detached
   *                                 flags are set or not unless it is
   *                                 called with @c
   *                                 abandon_detached_threads flag set.
   * @param use_absolute_time If true then treat @c timeout as
   *                          absolute time, else relative time.
   * @return 0 on success * and -1 on failure.
   *
   * @note If this function is called while the @c
   * ACE_Object_Manager is shutting down (as a result of program
   * rundown via @c ACE::fini()), it will not wait for any threads to
   * complete. If you must wait for threads spawned by this thread
   * manager to complete and you are in a ACE rundown situation (such
   * as your object is being destroyed by the @c ACE_Object_Manager)
   * you can use @c wait_grp() instead.
   */
  int wait (const ACE_Time_Value *timeout = 0,
            bool abandon_detached_threads = false,
            bool use_absolute_time = true);

  /// Join a thread specified by @a tid.  Do not wait on a detached thread.
  int join (ACE_thread_t tid, ACE_THR_FUNC_RETURN *status = 0);

  /**
   * Block until there are no more threads running in a group.
   * Returns 0 on success and -1 on failure.  Notice that wait_grp
   * will not wait on detached threads.
   */
  int wait_grp (int grp_id);

  /**
   * Return the "real" handle to the calling thread, caching it if
   * necessary in TSS to speed up subsequent lookups. This is
   * necessary since on some platforms (e.g., Windows) we can't get this
   * handle via direct method calls.  Notice that you should *not*
   * close the handle passed back from this method.  It is used
   * internally by Thread Manager.  On the other hand, you *have to*
   * use this internal thread handle when working on Thread_Manager.
   * Return -1 if fail.
   */
  int thr_self (ACE_hthread_t &);

  /**
   * Return the unique ID of the calling thread.
   * Same as calling ACE_Thread::self().
   */
  ACE_thread_t thr_self (void);

  /**
   * Returns a pointer to the current ACE_Task_Base we're executing
   * in if this thread is indeed running in an ACE_Task_Base, else
   * return 0.
   */
  ACE_Task_Base *task (void);

  /**
   * @name Suspend and resume methods
   *
   * Suspend/resume is not supported on all platforms. For example, Pthreads
   * does not support these functions.
   */
  //@{

  /// Suspend all threads
  int suspend_all (void);

  /// Suspend a single thread.
  int suspend (ACE_thread_t);

  /// Suspend a group of threads.
  int suspend_grp (int grp_id);

  /**
   * True if @a t_id is inactive (i.e., suspended), else false.  Always
   * return false if @a t_id is not managed by the Thread_Manager.
   */
  int testsuspend (ACE_thread_t t_id);

  /// Resume all stopped threads
  int resume_all (void);

  /// Resume a single thread.
  int resume (ACE_thread_t);

  /// Resume a group of threads.
  int resume_grp (int grp_id);

  /**
   * True if @a t_id is active (i.e., resumed), else false.  Always
   * return false if @a t_id is not managed by the Thread_Manager.
   */
  int testresume (ACE_thread_t t_id);

  //@}

  // = Send signals to one or more threads without blocking.
  /**
   * Send @a signum to all stopped threads.  Not supported on platforms
   * that do not have advanced signal support, such as Win32.
   */
  int kill_all (int signum);
  /**
   * Send the @a signum to a single thread.  Not supported on platforms
   * that do not have advanced signal support, such as Win32.
   */
  int kill (ACE_thread_t, int signum);
  /**
   * Send @a signum to a group of threads, not supported on platforms
   * that do not have advanced signal support, such as Win32.
   */
  int kill_grp (int grp_id, int signum);

  // = Cancel methods, which provides a cooperative thread-termination mechanism (will not block).
  /**
   * Cancel's all the threads.
   */
  int cancel_all (int async_cancel = 0);

  /**
   * Cancel a single thread.
   */
  int cancel (ACE_thread_t, int async_cancel = 0);

  /**
   * Cancel a group of threads.
   */
  int cancel_grp (int grp_id, int async_cancel = 0);

  /**
   * True if @a t_id is cancelled, else false.  Always return false if
   * @a t_id is not managed by the Thread_Manager.
   */
  int testcancel (ACE_thread_t t_id);

  /**
   * True if @a t_id has terminated (i.e., is no longer running),
   * but the slot in the thread manager hasn't been reclaimed yet,
   * else false.  Always return false if @a t_id is not managed by the
   * Thread_Manager.
   */
  int testterminate (ACE_thread_t t_id);

  /// Set group ids for a particular thread id.
  int set_grp (ACE_thread_t,
               int grp_id);

  /// Get group ids for a particular thread id.
  int get_grp (ACE_thread_t,
               int &grp_id);

  /**
   * @name Task-related operations
   */
  //@{
  /**
   * Block until there are no more threads running in a specified task.
   * This method will not wait for either detached or daemon threads;
   * the threads must have been spawned with the @c THR_JOINABLE flag.
   * Upon successful completion, the threads have been joined, so further
   * attempts to join with any of the waited-for threads will fail.
   *
   * @param task  The ACE_Task_Base object whose threads are to waited for.
   *
   * @retval 0  Success.
   * @retval -1 Failure (consult errno for further information).
   */
  int wait_task (ACE_Task_Base *task);

  /**
   * Suspend all threads in an ACE_Task.
   */
  int suspend_task (ACE_Task_Base *task);

  /**
   * Resume all threads in an ACE_Task.
   */
  int resume_task (ACE_Task_Base *task);

  /**
   * Send a signal @a signum to all threads in an ACE_Task.
   */
  int kill_task (ACE_Task_Base *task, int signum);

  /**
   * Cancel all threads in an ACE_Task.  If <async_cancel> is non-0,
   * then asynchronously cancel these threads if the OS platform
   * supports cancellation.  Otherwise, perform a "cooperative"
   * cancellation.
   */
  int cancel_task (ACE_Task_Base *task, int async_cancel = 0);

  //@}

  // = Collect thread handles in the thread manager.  Notice that
  //   the collected information is just a snapshot.
  /// Check if the thread is managed by the thread manager.  Return true if
  /// the thread is found, false otherwise.
  int hthread_within (ACE_hthread_t handle);
  int thread_within (ACE_thread_t tid);

  /// Returns the number of ACE_Task_Base in a group.
  int num_tasks_in_group (int grp_id);

  /// Returns the number of threads in an ACE_Task_Base.
  int num_threads_in_task (ACE_Task_Base *task);

  /**
   * Returns a list of ACE_Task_Base pointers corresponding to the tasks
   * that have active threads in a specified thread group.
   *
   * @param grp_id    The thread group ID to obtain task pointers for.
   *
   * @param task_list is a pointer to an array to receive the list of pointers.
   *                  The caller is responsible for supplying an array with at
   *                  least @arg n entries.
   *
   * @param n         The maximum number of ACE_Task_Base pointers to write
   *                  in @arg task_list.
   *
   * @retval  If successful, the number of pointers returned, which will be
   *          no greater than @arg n. Returns -1 on error.
   *
   * @note    This method has no way to indicate if there are more than
   *          @arg n ACE_Task_Base pointers available. Therefore, it may be
   *          wise to guess a larger value of @arg n than one thinks in cases
   *          where the exact number of tasks is not known.
   *
   * @sa      num_tasks_in_group(), task_all_list()
   */
  ssize_t task_list (int grp_id,
                     ACE_Task_Base *task_list[],
                     size_t n);

  /**
   * Returns in @a thread_list a list of up to @a n thread ids in an
   * ACE_Task_Base.  The caller must allocate the memory for
   * @a thread_list.  In case of an error, -1 is returned. If no
   * requested values are found, 0 is returned, otherwise correct
   * number of retrieved values are returned.
   */
  ssize_t thread_list (ACE_Task_Base *task,
                       ACE_thread_t thread_list[],
                       size_t n);

  /**
   * Returns in @a hthread_list a list of up to @a n thread handles in
   * an ACE_Task_Base.  The caller must allocate memory for
   * @a hthread_list.  In case of an error, -1 is returned. If no
   * requested values are found, 0 is returned, otherwise correct
   * number of retrieved values are returned.
   */
  ssize_t hthread_list (ACE_Task_Base *task,
                        ACE_hthread_t hthread_list[],
                        size_t n);

  /**
   * Returns in @a thread_list a list of up to @a n thread ids in a
   * group @a grp_id.  The caller must allocate the memory for
   * @a thread_list.  In case of an error, -1 is returned. If no
   * requested values are found, 0 is returned, otherwise correct
   * number of retrieved values are returned.
   */
  ssize_t thread_grp_list (int grp_id,
                           ACE_thread_t thread_list[],
                           size_t n);

  /**
   * Returns in @a hthread_list a list of up to @a n thread handles in
   * a group @a grp_id.  The caller must allocate memory for
   * @a hthread_list.
   */
  ssize_t hthread_grp_list (int grp_id,
                            ACE_hthread_t hthread_list[],
                            size_t n);

  /**
   * Returns a list of ACE_Task_Base pointers corresponding to the tasks
   * that have active threads managed by this instance.
   *
   * @param task_list is a pointer to an array to receive the list of pointers.
   *                  The caller is responsible for supplying an array with at
   *                  least @arg n entries.
   *
   * @param n         The maximum number of ACE_Task_Base pointers to write
   *                  in @arg task_list.
   *
   * @retval  If successful, the number of pointers returned, which will be
   *          no greater than @arg n. Returns -1 on error.
   *
   * @note    This method has no way to indicate if there are more than
   *          @arg n ACE_Task_Base pointers available. Therefore, it may be
   *          wise to guess a larger value of @arg n than one thinks in cases
   *          where the exact number of tasks is not known.
   *
   * @sa      count_threads()
   */
  ssize_t task_all_list (ACE_Task_Base *task_list[],
                         size_t n);

  /**
   * Returns in @a thread_list a list of up to @a n thread ids.  The
   * caller must allocate the memory for @a thread_list.  In case of an
   * error, -1 is returned. If no requested values are found, 0 is
   * returned, otherwise correct number of retrieved values are
   * returned.
   */
  ssize_t thread_all_list (ACE_thread_t thread_list[],
                           size_t n);

  /// Set group ids for a particular task.
  int set_grp (ACE_Task_Base *task, int grp_id);

  /// Get group ids for a particular task.
  int get_grp (ACE_Task_Base *task, int &grp_id);

  /// Return a count of the current number of threads active in the
  /// <Thread_Manager>.
  size_t count_threads (void) const;

  /// Get the state of the thread. Returns false if the thread is not
  /// managed by this thread manager.
  int thr_state (ACE_thread_t id, ACE_UINT32& state);

  /**
   * Register an At_Thread_Exit hook and the ownership is acquire by
   * Thread_Descriptor, this is the usual case when the AT is dynamically
   * allocated.
   */
  int at_exit (ACE_At_Thread_Exit* cleanup);

  /// Register an At_Thread_Exit hook and the ownership is retained for the
  /// caller. Normally used when the at_exit hook is created in stack.
  int at_exit (ACE_At_Thread_Exit& cleanup);

  /**
   *
   *****
   * @deprecated This function is deprecated.  Please use the previous two
   *    at_exit method.  Notice that you should avoid mixing this method
   *    with the previous two at_exit methods.
   *****
   *
   * Register an object (or array) for cleanup at
   * thread termination.  "cleanup_hook" points to a (global, or
   * static member) function that is called for the object or array
   * when it to be destroyed.  It may perform any necessary cleanup
   * specific for that object or its class.  "param" is passed as the
   * second parameter to the "cleanup_hook" function; the first
   * parameter is the object (or array) to be destroyed.
   * "cleanup_hook", for example, may delete the object (or array).
   * If <cleanup_hook> == 0, the <object> will _NOT_ get cleanup at
   * thread exit.  You can use this to cancel the previously added
   * at_exit.
   */
  int at_exit (void *object,
               ACE_CLEANUP_FUNC cleanup_hook,
               void *param);

  /// Access function to determine whether the Thread_Manager will
  /// wait for its thread to exit or not when being closing down.
  void wait_on_exit (int dowait);
  int wait_on_exit (void);

  /// Dump the state of an object.
  void dump (void);

  /// Declare the dynamic allocation hooks.
  ACE_ALLOC_HOOK_DECLARE;

protected:
  // = Accessors for ACE_Thread_Descriptors.
  /**
   * Get a pointer to the calling thread's own thread_descriptor.
   * This must be called from a spawn thread.  This function will
   * fetch the info from TSS.
   */
  ACE_Thread_Descriptor *thread_desc_self (void);

  /// Return a pointer to the thread's Thread_Descriptor,
  /// 0 if fail.
  ACE_Thread_Descriptor *thread_descriptor (ACE_thread_t);

  /// Return a pointer to the thread's Thread_Descriptor,
  /// 0 if fail.
  ACE_Thread_Descriptor *hthread_descriptor (ACE_hthread_t);

  /// Create a new thread (must be called with locks held).
  int spawn_i (ACE_THR_FUNC func,
               void *arg,
               long flags,
               ACE_thread_t * = 0,
               ACE_hthread_t *t_handle = 0,
               long priority = ACE_DEFAULT_THREAD_PRIORITY,
               int grp_id = -1,
               void *stack = 0,
               size_t stack_size = 0,
               ACE_Task_Base *task = 0,
               const char** thr_name = 0);

  /// Run the registered hooks when the thread exits.
  void run_thread_exit_hooks (int i);

  /// Locate the index of the table slot occupied by <t_id>.  Returns
  /// -1 if <t_id> is not in the table doesn't contain <t_id>.
  ACE_Thread_Descriptor *find_thread (ACE_thread_t t_id);

  /// Locate the index of the table slot occupied by <h_id>.  Returns
  /// -1 if <h_id> is not in the table doesn't contain <h_id>.
  ACE_Thread_Descriptor *find_hthread (ACE_hthread_t h_id);

  /**
   * Locate the thread descriptor address of the list occupied by
   * @a task.  Returns 0 if @a task is not in the table doesn't contain
   * @a task.
   */
  ACE_Thread_Descriptor *find_task (ACE_Task_Base *task,
                                    size_t slot = 0);

  /// Insert a thread in the table (checks for duplicates).
  int insert_thr (ACE_thread_t t_id,
                  ACE_hthread_t,
                  int grp_id = -1,
                  long flags = 0);

  /// Append a thread in the table (adds at the end, growing the table
  /// if necessary).
  int append_thr (ACE_thread_t t_id, ACE_hthread_t,
                  ACE_UINT32,
                  int grp_id,
                  ACE_Task_Base *task = 0,
                  long flags = 0,
                  ACE_Thread_Descriptor *td = 0);

  /// Remove thread from the table.
  void remove_thr (ACE_Thread_Descriptor *td,
                   int close_handler);

  /// Remove all threads from the table.
  void remove_thr_all (void);

  // = The following four methods implement a simple scheme for
  // operating on a collection of threads atomically.

  /**
   * Efficiently check whether @a thread is in a particular @a state.
   * This call updates the TSS cache if possible to speed up
   * subsequent searches.
   */
  int check_state (ACE_UINT32 state,
                   ACE_thread_t thread,
                   int enable = 1);

  /// Apply @a func to all members of the table that match the @a task
  int apply_task (ACE_Task_Base *task,
                  ACE_THR_MEMBER_FUNC func,
                  int = 0);

  /// Apply @a func to all members of the table that match the @a grp_id.
  int apply_grp (int grp_id,
                 ACE_THR_MEMBER_FUNC func,
                 int arg = 0);

  /// Apply @a func to all members of the table.
  int apply_all (ACE_THR_MEMBER_FUNC,
                 int  = 0);

  /// Join the thread described in @a td.
  int join_thr (ACE_Thread_Descriptor *td,
                int = 0);

  /// Resume the thread described in @a td.
  int resume_thr (ACE_Thread_Descriptor *td,
                  int = 0);

  /// Suspend the thread described in @a td.
  int suspend_thr (ACE_Thread_Descriptor *td,
                   int = 0);

  /// Send signal @a signum to the thread described in @a td.
  int kill_thr (ACE_Thread_Descriptor *td,
                int signum);

  /// Set the cancellation flag for the thread described in @a td.
  int cancel_thr (ACE_Thread_Descriptor *td,
                  int async_cancel = 0);

  /// Register a thread as terminated and put it into the <terminated_thr_list_>.
  int register_as_terminated (ACE_Thread_Descriptor *td);

  /// Setting the static ACE_TSS_TYPE (ACE_Thread_Exit) *thr_exit_ pointer.
  static int set_thr_exit (ACE_TSS_TYPE (ACE_Thread_Exit) *ptr);

  /**
   * Keeping a list of thread descriptors within the thread manager.
   * Double-linked list enables us to cache the entries in TSS
   * and adding/removing thread descriptor entries without
   * affecting other thread's descriptor entries.
   */
  ACE_Double_Linked_List<ACE_Thread_Descriptor> thr_list_;

#if !defined (ACE_HAS_VXTHREADS)
  /// Collect terminated but not yet joined thread entries.
  ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> terminated_thr_list_;
#endif /* !ACE_HAS_VXTHREADS */

  /// Collect pointers to thread descriptors of threads to be removed later.
  ACE_Unbounded_Queue<ACE_Thread_Descriptor*> thr_to_be_removed_;

  /// Keeps track of the next group id to assign.
  int grp_id_;

  /// Set if we want the Thread_Manager to wait on all threads before
  /// being closed, reset otherwise.
  int automatic_wait_;

  // = ACE_Thread_Mutex and condition variable for synchronizing termination.
#if defined (ACE_HAS_THREADS)
  /// Serialize access to the <zero_cond_>.
  ACE_Thread_Mutex lock_;

  /// Keep track of when there are no more threads.
  ACE_Condition_Thread_Mutex zero_cond_;
#endif /* ACE_HAS_THREADS */

  ACE_Locked_Free_List<ACE_Thread_Descriptor, ACE_SYNCH_MUTEX> thread_desc_freelist_;

private:
#if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
  /// Pointer to a process-wide ACE_Thread_Manager.
  static ACE_Thread_Manager *thr_mgr_;

  /// Must delete the thr_mgr_ if true.
  static bool delete_thr_mgr_;

  /// Global ACE_TSS (ACE_Thread_Exit) object ptr.
  static ACE_TSS_TYPE (ACE_Thread_Exit) *thr_exit_;
#endif /* ! defined (ACE_THREAD_MANAGER_LACKS_STATICS) */
};

#if defined (ACE_THREAD_MANAGER_LACKS_STATICS)
#define ACE_THREAD_MANAGER_SINGLETON_DEFINE \
        ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX>;
typedef ACE_Singleton<ACE_Thread_Manager, ACE_SYNCH_MUTEX> ACE_THREAD_MANAGER_SINGLETON;
#endif /* defined (ACE_THREAD_MANAGER_LACKS_STATICS) */

ACE_END_VERSIONED_NAMESPACE_DECL

#if defined (__ACE_INLINE__)
#include "ace/Thread_Manager.inl"
#endif /* __ACE_INLINE__ */

#include /**/ "ace/post.h"
#endif /* ACE_THREAD_MANAGER_H */



注意:必须在退出functor所属的线程的上下文中,向线程管理器登记这个退出functor.使用ACE_Thread_Manager::at_exit()方法登记退出functor;
    ACE_Thread_Manager::wait()会等待所有的子线程退出,而不管与那些线程相关联的是哪个任务,当你有不止一个任务正在执行的时候,使用这个特性将会很方便;
    注意:我们要把ACE_Thread_Manager类的实例当作一个单体对象使用;其原因是:在默认情况下,ACE会通过这个单体对象来管理所有的线程;尽管在大多数情况下,你会发现默认行为已经足够,你可以创建并使用多个线程管理器对象;

线程的取消:
    取消是一种你可以用以消灭(zap)正在运行线程的途径.任何线程退出处理器都不会被调用,线程专有存储空间也不会被释放.你的线程将消失.在某些情况下,取消也是一种"必要的邪恶":为了退出一个长时间运行的、只进行计算的线程,或是终止一个阻塞在阻塞式调用上的线程.在大多数情况下,应用终止时取消线程是有意义的;
    取消有以下几种模式:
    A、延迟取消:
       这种模式下,所有的取消操作都会被延迟到该线程的下一个取消点.取消点是代码中明确定义的点,在这个点上,线程或是已经阻塞,或是用ACE_Thread_Manager::testcancal()方法编写了显式的取消点.这种模式是用ACE构建的应用的默认模式;
    B、协作式取消:
       这种模式下,线程并没有被真正的取消,而是会在派生它们的ACE_Thread_Manager实例中被标记已取消.你可以调用ACE_Thread_Manager::testcalcel()方法来确定线程是否处在已取消状态.如果这样,你可以选择退出线程.这种模式避免了常规取消所带来的大多数讨厌的副作用.如果你想构建可移植的应用,就最好坚持使用这种取消模式;   
    C、异步取消:
       这种模式下,取消操作可以在任意时刻被处理;运行在这种模式下的线程可能会难以管理.你可以把任何线程的取消状态从启用改为禁用,以确保线程不会在执行关键代码时被取消.你还可以使用线程清理处理器,它们将在线程取消时被调用,以确保线程的各不变项在取消过程中得以维持.
    D、禁用取消:
       调用ACE_Thread::disablecancel(),可以完全禁止取消某个线程;   
    ACE_Thread_Manager::cancel_task()方法可以用来取消一个线程;
    下面的方法可以把线程的取消模式设置为异步取消模式:
    cancel_state new_state;
    new_state.cancelstate = PTHREAD_CANCEL_ENABLE;
    new_state.canceltype  = PTHREAD_CANCEL_ASYNCHRONOUS;
    ACE_Thread::setcancelstate(new_state, 0);

更多文章,欢迎访问:http://blog.youkuaiyun.com/wallwind

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<think> 首先,用户的问题是:“我想查找ACE-BASE线程占用CPU过高的解决方案 请问ACE-BASE线程占用CPU过高的解决办法”。用户提到了“ACE-BASE”,但从引用内容看,似乎是ACE框架中的线程管理问题。引用中提到ACE_Task_Base类用于线程管理,以及ACE Proactor框架等。 用户提供的引用: - 引用[1] 讨论了ACE管理线程,包括ACE_Task_Base类和svc()方法。 - 引用[2] 讨论了ACE Proactor框架的监控工具。 - 引用[3] 讨论了ACE中的主动对象模式,基于ACE_Task。 用户上一次的问题是查找ACE-BASE线程占用CPU过高的解决方案。我需要基于这些引用和系统指令来回答。 系统指令要求: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如[^1]。 从引用看,没有直接提到“ACE-BASE”,但用户可能指的是ACE框架中基于ACE_Task的线程管理。在引用[1]中,提到了ACE_Task_Base用于创建线程线程在svc()方法中启动和终止。 用户的问题是关于线程占用CPU过高,所以我需要提供解决方案来诊断和解决这个问题。 可能的解决方案: 1. **诊断问题**:使用监控工具来识别哪个线程或任务导致高CPU。 - 引用[2]中提到ACE Proactor框架有性能监控工具,可以监控响应时间、吞吐量、CPU使用情况等。这可以用于诊断。 2. **优化线程代码**: - 在svc()方法中避免无限循环或高CPU消耗的逻辑。 - 确保线程在完成任务后及时终止。 - 使用同步机制如锁或信号量来避免忙等待。 3. **调整线程优先级或调度**:在ACE框架中,可能可以设置线程优先级。 4. **资源管理**:监控CPU和内存使用,确保系统资源充足。 5. **使用ACE提供的工具**:如引用[2]中的性能监控和资源监控。 由于引用[1]提到线程在svc()方法返回时终止,如果svc()方法中有无限循环或阻塞不当,可能会导致高CPU。 结构化回答: - 回答要清晰、逐步解决问题。 - 使用中文。 - 在引用的段落末尾添加引用标识。 - 最后生成相关问题。 回答结构: 1. 介绍问题:解释ACE框架线程管理。 2. 诊断步骤:如何使用ACE工具监控CPU使用。 3. 解决方案:针对高CPU问题的具体办法。 4. 生成相关问题。 添加引用标识: - 当提到引用内容时,在相关句子末尾添加[^1], [^2], [^3]。 例如: - 在讨论线程管理时,引用引用[1]。 - 在讨论监控工具时,引用引用[2]。 - 在讨论主动对象时,引用引用[3]。 确保回答真实可靠:基于提供的引用,不要添加外部知识。 最终回答应包括: - 解释ACE线程管理机制。 - 步骤来诊断和解决CPU过高问题。 - 相关问题。 </think> ### ACE-BASE线程占用CPU过高的解决方案 在ACE框架中,线程管理通常通过`ACE_Task_Base`类实现,线程在`svc()`方法中启动和终止,如果`svc()`方法中存在无限循环、阻塞不当或资源竞争,可能导致线程占用CPU过高[^1]。ACE Proactor框架提供了性能监控工具,可帮助实时监控CPU使用情况[^2]。以下我将基于ACE框架的特性,逐步指导您诊断和解决此问题。解决方案包括诊断、优化和监控三个步骤,确保回答清晰可靠。 #### 步骤1:诊断线程CPU占用问题 诊断是解决问题的第一步,目的是识别哪个线程或任务导致高CPU负载。您可以利用ACE提供的工具和方法: - **使用性能监控工具**:ACE Proactor框架内置性能监控功能,可实时跟踪异步I/O操作的响应时间、吞吐量和CPU使用率。通过配置监控器,定位高CPU占用的线程[^2]。例如: - 在代码中添加监控钩子,记录每个线程的CPU时间。 - 分析日志,找出长时间运行的`svc()`方法。 - **检查线程生命周期**:确保线程在`svc()`方法完成后及时终止。如果`svc()`方法包含无限循环或未处理中断,线程将持续占用CPU。引用[1]中提到,线程在`svc()`返回时终止,因此需验证方法逻辑是否包含退出条件[^1]。 - **资源监控**:结合ACE的资源监控功能,观察CPU和内存使用峰值,排查资源泄露或不当调度[^2]。建议使用系统工具(如top或perf)配合ACE日志,进行交叉验证。 诊断示例:假设发现一个基于`ACE_Task`的主动对象线程占用高CPU,可在`svc()`中添加调试输出: ```cpp int MyTask::svc() { while (active()) { // 检查退出条件 // 业务逻辑 if (should_exit) break; // 确保有退出机制 } return 0; } ``` 如果监控显示CPU过高,可能是`active()`条件未满足或循环耗时过长[^1][^3]。 #### 步骤2:优化线程以减少CPU占用 针对诊断结果,实施优化措施: - **优化`svc()`方法**:避免CPU密集型操作在循环中运行。例如: - 引入睡眠或等待机制(如`ACE_OS::sleep()`),减少忙等待。 - 使用事件驱动模式,将高负载逻辑分解为异步任务,通过ACE Proactor处理I/O操作,降低线程活性[^2]。 - **调整线程调度**:在ACE中,设置线程优先级或使用线程管理。例如: - 通过`ACE_Task::activate()`设置线程优先级,避免低优先级线程占用过多CPU[^1]。 - 采用ACE Thread Manager实现线程复用,减少新线程创建开销。 - **修复资源竞争**:高CPU常由锁竞争引起。使用ACE同步机制(如`ACE_Mutex`或`ACE_Condition`)确保临界区高效: ```cpp ACE_Mutex mutex; void critical_section() { ACE_GUARD(ACE_Mutex, guard, mutex); // 自动加锁解锁 // 安全访问共享资源 } ``` 这减少了自旋锁导致的CPU浪费[^1][^3]。 - **确保线程及时销毁**:主动对象(基于`ACE_Task`)在`svc()`返回后应调用`close()`释放资源[^3]。定期检查线程状态,避免僵尸线程。 #### 步骤3:监控和预防 预防高CPU问题需结合ACE工具和最佳实践: - **启用持续监控**:部署ACE Proactor的性能和资源监控,设置阈值告警(如CPU >80%时触发日志)[^2]。 - **代码审查**:重点审查`svc()`方法中的循环逻辑和退出条件,确保符合ACE线程管理规范[^1]。 - **性能测试**:使用ACE测试框架模拟高负载场景,验证优化效果。例如,通过吞吐量公式评估CPU效率:$$ \text{吞吐量} = \frac{\text{完成任务数}}{\text{时间}} $$,目标是将CPU利用率控制在安全范围(如<70%)。 如果上述步骤无效,可能涉及系统级问题(如硬件不足),建议结合操作系统工具深入分析。 ### 相关问题 1. 如何在ACE框架中配置线程优先级以优化CPU使用? 2. ACE Proactor框架的性能监控工具具体如何使用? 3. ACE的主动对象模式在哪些场景下容易导致线程泄露? 4. 异步I/O与多线程结合时如何避免CPU竞争? [^1]: ACE管理线程机制基于ACE_Task_Base类,覆盖svc()方法创建线程,并在方法返回时终止。 [^2]: ACE Proactor框架提供性能监控和资源监控工具,实时跟踪CPU使用。 [^3]: ACE_Task类实现主动对象模式,是所有主动对象的基类。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值