diff options
author | nw1 <nw1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1997-10-15 06:55:08 +0000 |
---|---|---|
committer | nw1 <nw1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1997-10-15 06:55:08 +0000 |
commit | a18c53df34d56daeb3481ad6ba7ab4def21ea173 (patch) | |
tree | d379d83ef16db61a7b5346be1d4ff36f8d76e4e5 | |
parent | 63cf609ad94232c516d717ba4440c205eb20f95a (diff) | |
download | ATCD-a18c53df34d56daeb3481ad6ba7ab4def21ea173.tar.gz |
Work in progress.
-rw-r--r-- | ace/Containers.h | 240 | ||||
-rw-r--r-- | ace/Thread_Manager.cpp | 12 | ||||
-rw-r--r-- | ace/Thread_Manager.h | 83 | ||||
-rw-r--r-- | ace/Thread_Manager.i | 88 |
4 files changed, 421 insertions, 2 deletions
diff --git a/ace/Containers.h b/ace/Containers.h index 9e08f3bb411..efb8c832afa 100644 --- a/ace/Containers.h +++ b/ace/Containers.h @@ -173,7 +173,7 @@ template <class T> class ACE_Unbounded_Stack_Iterator; template<class T> class ACE_Node // = TITLE - // Implementation element in a Queue + // Implementation element in a Queue. { friend class ACE_Unbounded_Queue<T>; friend class ACE_Unbounded_Queue_Iterator<T>; @@ -197,6 +197,64 @@ private: // Current value of the item in this node. }; +#if defined (NANBOR_EXP_CODES) +class ACE_DNode_Base + // = TITLE + // Implement the minimum stuff a node in a double + // linked list should have. + // + // = DESCRIPTION + // Basic functionalities an element in double linked + // lists. +{ + public: + ACE_DNode_Base (void); + // Default do nothing ctor. + + ACE_DNode_Base (ACE_DNode_Base *n, ACE_DNode_Base *p); + // Build and set ctor. + + void next (ACE_DNode_Base *n) = 0; + // Set <next_> ptr. + + ACE_DNode_Base *next (void) = 0; + // Get <next_> ptr. + + void prev (ACE_DNode_Base *p) = 0; + // Set <prev_> ptr. + + ACE_DNode_Base *prev (void) = 0; + // Get <prev_> ptr. + + protected: + ACE_DNode_Base *prev_; + // Pointer to previous element in the list. + + ACE_DNode_Base *next_; + // Pointer to next element in the list. +}; +#endif /* NANBOR_EXP_CODES */ + +#if defined (NANBOR_DISABLED_EXP_CODES) +template <class T> +class ACE_DNode : public ACE_Node<T> +// = TITLE +// Implementation element in a Double Linked List. +{ + friend class ACE_Double_Linked_List<T>; + friend class ACE_Double_Linked_List_Iterator<T>; +protected: + ACE_DNode (const T &i, ACE_DNode<T> *n, ACE_DNode<T> *p); + ACE_DNode (ACE_DNode<T> *n = 0, ACE_DNode<T> *p = 0); + ACE_DNode (const ACE_DNode<T> &i); + + ~ACE_DNode (void); + + ACE_DNode<T> *prev_; + // Pointer to prev element in the list of <ACE_DNode>s. +}; +#endif /* NANBOR_DISABLED_EXP_CODES */ + template <class T> class ACE_Unbounded_Stack // = TITLE @@ -450,6 +508,186 @@ protected: }; template <class T> +class ACE_Unbounded_Stack_Iterator + // = TITLE + // Implement an iterator over an unbounded Stack. +{ +public: + // = Initialization method. + ACE_Unbounded_Stack_Iterator (ACE_Unbounded_Stack<T> &); + + // = Iteration methods. + + int next (T *&next_item); + // Pass back the <next_item> that hasn't been seen in the Stack. + // Returns 0 when all items have been seen, else 1. + + int advance (void); + // Move forward by one element in the Stack. Returns 0 when all the + // items in the Stack have been seen, else 1. + + int done (void) const; + // Returns 1 when all items have been seen, else 0. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_Node<T> *current_; + // Pointer to the current node in the iteration. + + ACE_Unbounded_Stack<T> &stack_; + // Pointer to the Stack we're iterating over. +}; + +#if defined (NANBOR_DISABLED_EXP_CODES) +template <class T> +class ACE_Double_Linked_List; + +template <class T> +class ACE_Double_Linked_List_Iterator + // = TITLE + // Implement an iterator over a double-linked list. +{ +public: + // = Initialization method. + ACE_Double_Linked_List (ACE_Double_Linked_List<T> &); + + // = Iteration methods. + + int next (T *&next_item); + // Pass back the <next_item> that hasn't been seen in the queue. + // Returns 0 when all items have been seen, else 1. + + int advance (void); + // Move forward by one element in the set. Returns 0 when all the + // items in the queue have been seen, else 1. + + int done (void) const; + // Returns 1 when all items have been seen, else 0. + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +private: + ACE_DNode<T> *current_; + // Pointer to the current node in the iteration. + + ACE_Double_Linked_List<T> &list_; + // Pointer to the queue we're iterating over. +}; + +template <class T> +class ACE_Double_Linked_List + // = TITLE + // A double linked list implementation. + // + // = DESCRIPTION + // This implementation of an unbounded double linked list uses a circular + // linked list with a dummy node. It is pretty much like the ACE_Unbounded_Queue + // except that it allows removing of a specific element from a specific location. +{ + friend class ACE_Double_Linked_List_Iterator<T>; +public: + // = Initialization and termination methods. + ACE_Double_Linked_List (ACE_Allocator *alloc = 0); + // construction. Use user specified allocation strategy + // if specified. + + ACE_Double_Linked_List (const ACE_Double_Linked_list<T> &); + // Copy constructor. + + void operator= (const ACE_Double_linked_List<T> &); + // Assignment operator. + + ~ACE_Double_Linked_List (void); + // construction. + + // = Check boundary conditions. + + int is_empty (void) const; + // Returns 1 if the container is empty, otherwise returns 0. + + int is_full (void) const; + // Returns 1 if the container is full, otherwise returns 0. + + // = Classic queue operations. + + int enqueue_tail (const T &new_item); + // Adds <new_item> to the tail of the queue. Returns 0 on success, + // -1 on failure. + + int enqueue_head (const T &new_item); + // Adds <new_item> to the head of the queue. Returns 0 on success, + // -1 on failure. + + int dequeue_head (T &item); + // Removes and returns the first <item> on the queue. Returns 0 on + // success, -1 if the queue was empty. + + // = Additional utility methods. + + void reset (void); + // Reset the <ACE_Unbounded_Queue> to be empty. + + int get (T *&item, size_t index = 0) const; + // Get the <index>th element in the set. Returns -1 if the element + // isn't in the range <0..size() - 1>, else 0. + + int set (const T &item, size_t index); + // Set the <index>th element in the set. Will pad out the set with + // empty nodes if <index> is beyond the range <0..size() - 1>. + // Returns -1 on failure, 0 if <index> isn't initially in range, and + // 0 otherwise. + + size_t size (void) const; + // The number of items in the queue. + + void dump (void) const; + // Dump the state of an object. + + ACE_DNode<T> *find (const T &item); + // Locate the DNode address that contains the item. Return + // an address if succeed, 0 otherwise. + + int remove (const T &item); + // This function will iterate thru the double linked list and + // remove it from the list. return 0 if succeed, -1 otherwise. + + int remove (ACE_DNode<T> *n); + // Use DNode address directly. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + void add_node (ACE_DNode<T> *new_node, ACE_DNode<T> *target, int after = 1); + // Add an node before/after a current list element. + + void delete_nodes (void); + // Delete all the nodes in the queue. + + void copy_nodes (const ACE_Unbounded_Queue<T> &); + // Copy nodes into this queue. + + ACE_DNode<T> *head_; + // Pointer to the dummy node in the circular linked Queue. + + size_t cur_size_; + // Current size of the queue. + + ACE_Allocator *allocator_; + // Allocation Strategy of the queue. +}; +#endif /* NANBOR_DISABLED_EXP_CODES */ + +template <class T> class ACE_Unbounded_Set_Iterator // = TITLE // Implement an iterator over an unbounded set. diff --git a/ace/Thread_Manager.cpp b/ace/Thread_Manager.cpp index d68ef9874d4..ef2bf49db13 100644 --- a/ace/Thread_Manager.cpp +++ b/ace/Thread_Manager.cpp @@ -108,6 +108,12 @@ int ACE_Thread_Manager::hthread_descriptor (ACE_hthread_t thr_handle, ACE_Thread_Descriptor &descriptor) { + // @@ This will probably not work right on Win32 for app. programmers since + // the Thread_Manager now returns a "duplicated handle" and it's not + // the one stored in the thread descriptor table. Therefore, be sure to + // use the thread handle inside thread manager, not the one returned by + // thread manager. + ACE_TRACE ("ACE_Thread_Manager::hthread_descriptor"); ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); @@ -121,6 +127,8 @@ ACE_Thread_Manager::hthread_descriptor (ACE_hthread_t thr_handle, int ACE_Thread_Manager::thr_self (ACE_hthread_t &self) { + // @@ We can get this information from TSS directly after my change. + ACE_TRACE ("ACE_Thread_Manager::thr_self"); ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); @@ -145,6 +153,8 @@ ACE_Thread_Manager::thr_self (ACE_hthread_t &self) int ACE_Thread_Manager::resize (size_t size) { + // @@ We probably won't need this anymore after changing to use TSS. + ACE_TRACE ("ACE_Thread_Manager::resize"); ACE_Thread_Descriptor *temp; @@ -501,6 +511,8 @@ ACE_Thread_Manager::spawn_i (ACE_THR_FUNC func, { #if defined (ACE_HAS_WTHREADS) // Have to duplicate handle if client asks for it. + // @@ How are thread handles implemented on AIX? Do they + // also need to be duplicated? if (t_handle != 0) (void) ::DuplicateHandle (::GetCurrentProcess (), thr_handle, diff --git a/ace/Thread_Manager.h b/ace/Thread_Manager.h index 7b7248611a4..cb319570c77 100644 --- a/ace/Thread_Manager.h +++ b/ace/Thread_Manager.h @@ -96,6 +96,85 @@ private: // Pointer to an <ACE_Task_Base> or NULL if there's no <ACE_Task_Base>; }; +////////////////////////////////////////////////// + +// @@ Thread handle comparison, how? When we duplicate a handle, (on +// Win32) the returning handle won't have the same value as the +// original handle. Therefore, I don't see a way to distinguish +// whether two handles point to the same theread or not. +// Motto: Always use thread ids to manipulate Thread_Manager. (???) + +#if defined (NANBOR_EXP_CODES) +CLASS ACE_Export ACE_Thread_Descriptor_Adapter + // = TITLE + // Wrap ACE_Thread_Descriptor for putting it into a container. + // + // = DESCRIPTION + // This class contains a pointer to a ACE_Thread_Descriptor. + // It then gets put into a container. This is to avoid extra + // data copying and also expose ACE_Thread_Descriptor's methods + // to the external world. + // + // *I assume no two threads will have the same thread id.* +{ +public: + ACE_Thread_Descriptor_Adapter (); + // Default constructor. Used by container classes. + + ACE_Thread_Descriptor_Adapter (ACE_Thread_Descriptor *thr_desc); + // Construct a adapter containing <thr_desc>. User should call this method. + + ACE_Thread_Descriptor_Adapter (const ACE_Thread_Descriptor_Adapter &td); + // Copy constructor. Required by container classes. + + ACE_Thread_Descriptor_Adatper& operator= (const ACE_Thread_Descriptor_Adapter &td); + // Assignment operation. Required by container classes. + + int operator== (const ACE_Thread_Descriptor_Adapter &td) const; + // Comparison operator. Required by container classes. + + // = Accessing the underlying methods of ACE_Thread_Descriptor. + + ACE_thread_t self (void); + // Unique thread id. + + void self (ACE_hthread_t &); + // Unique handle to thread (used by Win32 and AIX). + + int grp_id (void); + // Group ID. + + ACE_Thread_State state (void); + // Current state of the thread. + + ACE_Task_Base *task (void); + // Return the pointer to an <ACE_Task_Base> or NULL if there's no + // <ACE_Task_Base> associated with this thread.; + + void dump (void) const; + // Dump the state of an object. + + int at_exit (void *object, + ACE_CLEANUP_FUNC cleanup_hook, + void *param); + // 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. Returns 0 on success, non-zero on + // failure: -1 if virtual memory is exhausted or 1 if the object (or + // arrayt) had already been registered. + + ACE_Thread_Descriptor *get_thread_descriptor (void); + +private: + ACE_Thread_Descriptor *thr_desc_; + // Underlying thread descriptor location. +}; +#endif /* NANBOR_EXP_CODES */ + // Forward declaration. class ACE_Thread_Control; @@ -215,7 +294,9 @@ public: // Passes out 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., Win32) we can't get this - // handle via direct method calls. + // 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. ACE_thread_t thr_self (void); // Return the unique ID of the thread. This is not strictly diff --git a/ace/Thread_Manager.i b/ace/Thread_Manager.i index 3344c108e73..8391b50b4cf 100644 --- a/ace/Thread_Manager.i +++ b/ace/Thread_Manager.i @@ -44,6 +44,94 @@ ACE_Thread_Descriptor::state (void) return thr_state_; } +////////////////////////////////////////////////// +#if defined (NANBOR_EXP_CODES) +ACE_INLINE +ACE_Thread_Descriptor_Adapter::ACE_Thread_Descriptor_Adapter (void) + : thr_desc_ (0) +{ +} + +ACE_INLINE +ACE_Thread_Descriptor_Adapter::ACE_Thread_Descriptor_Adapter + (ACE_Thread_Descriptor *thr_desc) + : thr_desc_ (thr_desc) +{ +} + +ACE_INLINE +ACE_Thread_Descriptor_Adapter::ACE_Thread_Descriptor_Adapter + (const ACE_Thread_Descriptor_Adapter &td) + : thr_desc_ (td.thr_desc_) +{ +} + +ACE_INLINE ACE_Thread_Descriptor_Adatper& +ACE_Thread_Descriptor_Adapter::operator= (const ACE_Thread_Descriptor_Adapter &td) +{ + this->thr_desc_ = td.thr_desc_; +} + +ACE_INLINE int +ACE_Thread_Descriptor_Adapter::operator== (const ACE_Thread_Descriptor_Adapter &td) const +{ + return (this->self () == td.self ()); +} + +// = Accessing the underlying methods of ACE_Thread_Descriptor. + +ACE_INLINE ACE_thread_t +ACE_Thread_Descriptor_Adapter::self (void) +{ + return this->thr_desc_->self (); +} + +ACE_INLINE void +ACE_Thread_Descriptor_Adapter::self (ACE_hthread_t &handle) +{ + this->thr_desc_->self (handle); +} + +ACE_INLINE int +ACE_Thread_Descriptor_Adapter::grp_id (void) +{ + return this->thr_desc_->grp_id (); +} + +ACE_INLINE ACE_Thread_State +ACE_Thread_Descriptor_Adapter::state (void) +{ + return this->thr_desc_->state (); +} + +ACE_INLINE ACE_Task_Base * +ACE_Thread_Descriptor_Adapter::task (void) +{ + return this->thr_desc_->task (); +} + +ACE_INLINE void +ACE_Thread_Descriptor_Adapter::dump (void) const +{ + this->thr_desc_->dump (); +} + +ACE_INLINE int +ACE_Thread_Descriptor_Adapter::at_exit (void *object, + ACE_CLEANUP_FUNC cleanup_hook, + void *param) +{ + return this->thr_desc_->at_exit (object, cleanup_hook, param); +} + +ACE_INLINE ACE_Thread_Descriptor * +ACE_Thread_Descriptor_Adapter::get_thread_descriptor (void) +{ + return this->thr_desc_; +} +#endif /* NANBOR_EXP_CODES */ +////////////////////////////////////////////////// + // Set the exit status. ACE_INLINE void * |