summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornw1 <nw1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-10-15 06:55:08 +0000
committernw1 <nw1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-10-15 06:55:08 +0000
commita18c53df34d56daeb3481ad6ba7ab4def21ea173 (patch)
treed379d83ef16db61a7b5346be1d4ff36f8d76e4e5
parent63cf609ad94232c516d717ba4440c205eb20f95a (diff)
downloadATCD-a18c53df34d56daeb3481ad6ba7ab4def21ea173.tar.gz
Work in progress.
-rw-r--r--ace/Containers.h240
-rw-r--r--ace/Thread_Manager.cpp12
-rw-r--r--ace/Thread_Manager.h83
-rw-r--r--ace/Thread_Manager.i88
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 *