diff options
author | schmidt <douglascraigschmidt@users.noreply.github.com> | 1996-12-22 22:06:04 +0000 |
---|---|---|
committer | schmidt <douglascraigschmidt@users.noreply.github.com> | 1996-12-22 22:06:04 +0000 |
commit | aa56341042bf18dfb4754e0910113e8e059acc82 (patch) | |
tree | 147fc294556751cc24df552768b29a173a22c924 /ace | |
parent | f13a60d21d6b6971654b1b2737dd09fafdbef944 (diff) | |
download | ATCD-aa56341042bf18dfb4754e0910113e8e059acc82.tar.gz |
foo
Diffstat (limited to 'ace')
37 files changed, 792 insertions, 347 deletions
diff --git a/ace/Acceptor.cpp b/ace/Acceptor.cpp index d770af37146..79ad80fd9ae 100644 --- a/ace/Acceptor.cpp +++ b/ace/Acceptor.cpp @@ -170,6 +170,14 @@ ACE_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDLE, this->reactor_->remove_handler (handle, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL); + + // Shut down the listen socket to recycle the handles. + if (this->peer_acceptor_.close () == -1) + ACE_ERROR ((LM_ERROR, "close\n")); + + // Set the Reactor to 0 so that we don't try to close down + // again. + this->reactor (0); } return 0; } @@ -484,7 +492,7 @@ ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDL { ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close"); // Guard against multiple closes. - if (this->creation_strategy_ != 0) + if (this->reactor () != 0) { ACE_HANDLE handle = this->get_handle (); @@ -513,6 +521,10 @@ ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>::handle_close (ACE_HANDL this->reactor ()->remove_handler (handle, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL); + + // Set the Reactor to 0 so that we don't try to close down + // again. + this->reactor (0); } return 0; } diff --git a/ace/Local_Name_Space_T.cpp b/ace/Local_Name_Space_T.cpp index 0f6c66f651b..821ee3797d6 100644 --- a/ace/Local_Name_Space_T.cpp +++ b/ace/Local_Name_Space_T.cpp @@ -211,7 +211,7 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::unbind_i (const ACE_WString &name) { ACE_TRACE ("ACE_Local_Name_Space::unbind"); - ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); ACE_NS_String ns_name (name); ACE_NS_Internal ns_internal; if (this->name_space_map_->unbind (ns_name, ns_internal, this->allocator_) != 0) @@ -233,7 +233,7 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::bind (const ACE_WString &name, const char *type) { ACE_TRACE ("ACE_Local_Name_Space::bind"); - ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); return this->shared_bind (name, value, type, 0); } @@ -244,7 +244,7 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::rebind (const ACE_WString &name, const char *type) { ACE_TRACE ("ACE_Local_Name_Space::rebind"); - ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_WRITE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); return this->shared_bind (name, value, type, 1); } @@ -273,7 +273,7 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::resolve_i (const ACE_WString &name, char *&type) { ACE_TRACE ("ACE_Local_Name_Space::resolve"); - ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); ACE_NS_String ns_name (name); ACE_NS_Internal ns_internal; @@ -337,8 +337,9 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::~ACE_Local_Name_Space (void) { ACE_TRACE ("ACE_Local_Name_Space::~ACE_Local_Name_Space"); - // Remove the map + // Remove the map. delete this->allocator_; + delete this->lock_; } template <ACE_MEM_POOL_1, class LOCK> int @@ -378,15 +379,29 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::create_manager_i (void) ACE_OS::strcat (this->context_file_, ACE_DIRECTORY_SEPARATOR_STR); ACE_OS::strcat (this->context_file_, this->name_options_->database ()); - // ACE_DEBUG ((LM_DEBUG, "contextfile is %s\n", this->context_file_)); - ACE_MEM_POOL_OPTIONS options (this->name_options_->base_address ()); + TCHAR lock_name_for_local_name_space [MAXNAMELEN]; + TCHAR lock_name_for_backing_store [MAXNAMELEN]; + LPCTSTR prefix = ACE::basename (this->context_file_, + ACE_DIRECTORY_SEPARATOR_CHAR); + + ACE_OS::strcpy (lock_name_for_local_name_space , prefix); + ACE_OS::strcat (lock_name_for_local_name_space, "_name_space"); + + ACE_OS::strcpy (lock_name_for_backing_store, prefix); + ACE_OS::strcat (lock_name_for_backing_store, "_backing_store"); + // Create the allocator with the appropriate options. - ACE_NEW_RETURN (this->allocator_, ALLOCATOR (this->context_file_, 0, &options), -1); + ACE_NEW_RETURN (this->allocator_, + ALLOCATOR (this->context_file_, + lock_name_for_backing_store, + &options), -1); if (ACE_LOG_MSG->op_status ()) ACE_ERROR_RETURN ((LM_ERROR, "Allocator::Allocator\n"), -1); + + ACE_NEW_RETURN (this->lock_, LOCK (lock_name_for_local_name_space), -1); // Now check if the backing store has been created successfully if (ACE_OS::access (this->context_file_, F_OK) != 0) @@ -404,31 +419,33 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::create_manager_i (void) } // This is the hard part since we have to avoid potential race - // conditions... + // conditions... We will use the double check here else { - size_t map_size = sizeof *this->name_space_map_; - ns_map = this->allocator_->malloc (map_size); - - // Initialize the map into its memory location (e.g., shared memory). - ACE_NEW_RETURN (this->name_space_map_, - (ns_map) ACE_Name_Space_Map <ALLOCATOR> (this->allocator_), - -1); + ACE_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); - // Don't allow duplicates (atomically return existing int_id, if - // there is one). - if (this->allocator_->trybind (ACE_NAME_SERVER_MAP, ns_map) == 1) + // This is the easy case since if we find the Name Server Map + // Manager we know it's already initialized. + if (this->allocator_->find (ACE_NAME_SERVER_MAP, ns_map) == 0) { - // We're not the first one in, so free up the map and assign - // the map to the pointer that was allocated by the caller - // that was the first time in! - this->name_space_map_->close (this->allocator_); - - // Note that we can't free <map> since that was overwritten - // in the call to bind()! - this->allocator_->free ((void *) this->name_space_map_); this->name_space_map_ = (ACE_Name_Space_Map <ALLOCATOR> *) ns_map; + ACE_DEBUG ((LM_DEBUG, "name_space_map_ = %d, ns_map = %d\n", + this->name_space_map_, ns_map)); + } + else + { + size_t map_size = sizeof *this->name_space_map_; + ns_map = this->allocator_->malloc (map_size); + + // Initialize the map into its memory location (e.g., shared memory). + ACE_NEW_RETURN (this->name_space_map_, + (ns_map) ACE_Name_Space_Map <ALLOCATOR> (this->allocator_), + -1); + + if (this->allocator_->bind (ACE_NAME_SERVER_MAP, ns_map) == -1) + ACE_ERROR_RETURN ((LM_ERROR, "create_manager\n"), -1); } + ACE_DEBUG ((LM_DEBUG, "name_space_map_ = %d, ns_map = %d\n", this->name_space_map_, ns_map)); } @@ -436,12 +453,13 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::create_manager_i (void) return 0; } + template <ACE_MEM_POOL_1, class LOCK> int ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::list_names (ACE_PWSTRING_SET &set, const ACE_WString &pattern) { ACE_TRACE ("ACE_Local_Name_Space::list_names"); - ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); MAP_ITERATOR map_iterator (*this->name_space_map_); MAP_ENTRY *map_entry; @@ -474,7 +492,7 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::list_values (ACE_PWSTRING_SET &set, const ACE_WString &pattern) { ACE_TRACE ("ACE_Local_Name_Space::list_values"); - ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); MAP_ITERATOR map_iterator (*this->name_space_map_); MAP_ENTRY *map_entry; @@ -507,7 +525,7 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::list_types (ACE_PWSTRING_SET &set, const ACE_WString &pattern) { ACE_TRACE ("ACE_Local_Name_Space::list_types"); - ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); MAP_ITERATOR map_iterator (*this->name_space_map_); MAP_ENTRY *map_entry; @@ -569,7 +587,7 @@ ACE_Local_Name_Space <ACE_MEM_POOL_2, LOCK>::list_name_entries (ACE_BINDING_SET const ACE_WString &pattern) { ACE_TRACE ("ACE_Local_Name_Space::list_name_entries"); - ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); MAP_ITERATOR map_iterator (*this->name_space_map_); MAP_ENTRY *map_entry; @@ -597,7 +615,7 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::list_value_entries (ACE_BINDING_SET const ACE_WString &pattern) { ACE_TRACE ("ACE_Local_Name_Space::list_value_entries"); - ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); MAP_ITERATOR map_iterator (*this->name_space_map_); MAP_ENTRY *map_entry; @@ -624,7 +642,7 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::list_type_entries (ACE_BINDING_SET & const ACE_WString &pattern) { ACE_TRACE ("ACE_Local_Name_Space::list_type_entries"); - ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, this->lock_, -1); + ACE_READ_GUARD_RETURN (ACE_RW_Process_Mutex, ace_mon, *this->lock_, -1); MAP_ITERATOR map_iterator (*this->name_space_map_); MAP_ENTRY *map_entry; @@ -703,6 +721,3 @@ ACE_Local_Name_Space<ACE_MEM_POOL_2, LOCK>::dump (void) const } #endif /* ACE_LOCAL_NAME_SPACE_T_C */ - - - diff --git a/ace/Local_Name_Space_T.h b/ace/Local_Name_Space_T.h index 6745738e044..616019884a9 100644 --- a/ace/Local_Name_Space_T.h +++ b/ace/Local_Name_Space_T.h @@ -212,7 +212,7 @@ private: TCHAR context_file_[MAXNAMELEN]; // Name of the file used as the backing store. - LOCK lock_; + LOCK *lock_; // Synchronization variable. }; diff --git a/ace/Malloc_T.cpp b/ace/Malloc_T.cpp index 3685c4a42ac..4a45dbcb3cb 100644 --- a/ace/Malloc_T.cpp +++ b/ace/Malloc_T.cpp @@ -164,7 +164,8 @@ ACE_Malloc<ACE_MEM_POOL_2, LOCK>::ACE_Malloc (LPCTSTR pool_name, LPCTSTR lock_name, const ACE_MEM_POOL_OPTIONS *options) : memory_pool_ (pool_name, options), - lock_ (lock_name) + lock_ (lock_name != 0 ? lock_name : ACE::basename (pool_name, + ACE_DIRECTORY_SEPARATOR_CHAR)) { ACE_TRACE ("ACE_Malloc<ACE_MEM_POOL_2, LOCK>::ACE_Malloc"); this->open (); diff --git a/ace/Naming_Context.cpp b/ace/Naming_Context.cpp index 90048ca5353..12779536a7d 100644 --- a/ace/Naming_Context.cpp +++ b/ace/Naming_Context.cpp @@ -347,7 +347,7 @@ ACE_Name_Options::ACE_Name_Options (void) nameserver_host_ (ACE_OS::strdup (ACE_DEFAULT_SERVER_HOST)), namespace_dir_ (ACE_OS::strdup (ACE_DEFAULT_NAMESPACE_DIR)), process_name_ (0), - database_ (0), + database_ (ACE_OS::strdup (ACE_DEFAULT_LOCALNAME)), base_address_ (ACE_DEFAULT_BASE_ADDR) { ACE_TRACE ("ACE_Name_Options::ACE_Name_Options"); diff --git a/ace/OS.cpp b/ace/OS.cpp index f52c5639c40..2a8b83b75cd 100644 --- a/ace/OS.cpp +++ b/ace/OS.cpp @@ -696,6 +696,7 @@ ACE_OS::thr_create (ACE_THR_FUNC func, size = PTHREAD_STACK_MIN; #endif /* PTHREAD_STACK_MIN */ +#if !defined (ACE_LACKS_THREAD_STACK_SIZE) // JCEJ 12/17/96 if (::pthread_attr_setstacksize (&attr, size) != 0) { #if defined (ACE_HAS_SETKIND_NP) @@ -706,6 +707,7 @@ ACE_OS::thr_create (ACE_THR_FUNC func, return -1; } } +#endif /* !ACE_LACKS_THREAD_STACK_SIZE */ #if !defined (ACE_LACKS_THREAD_STACK_ADDR) if (stack != 0) @@ -919,17 +921,17 @@ ACE_OS::thr_create (ACE_THR_FUNC func, if (ACE_BIT_ENABLED (flags, THR_USE_AFX)) { CWinThread *cwin_thread = - ::AfxBeginThread (ACE_THR_C_FUNC (&ace_thread_adapter)), + ::AfxBeginThread ((AFX_THREADPROC) &ace_thread_adapter), thread_args, priority, 0, flags | THR_SUSPENDED); // Have to duplicate the handle because // CWinThread::~CWinThread() closes the original handle. - *thr_handle = ::DuplicateHandle (::GetCurrentProcess (), - cwin_thread->m_hThread, - ::GetCurrentProcess (), - thr_handle, - 0, - TRUE, - DUPLICATE_SAME_ACCESS); + (void) ::DuplicateHandle (::GetCurrentProcess (), + cwin_thread->m_hThread, + ::GetCurrentProcess (), + thr_handle, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); *thr_id = cwin_thread->m_nThreadID; @@ -1115,7 +1117,11 @@ ACE_OS::thr_keyfree (ACE_thread_key_t key) int ACE_OS::thr_keycreate (ACE_thread_key_t *key, +#if defined (ACE_HAS_THR_C_DEST) + ACE_THR_C_DEST dest, +#else ACE_THR_DEST dest, +#endif /* ACE_HAS_THR_C_DEST */ void *inst) { // ACE_TRACE ("ACE_OS::thr_keycreate"); @@ -1392,62 +1398,59 @@ int sys_nerr = ERRMAX + 1; #include /**/ <usrLib.h> /* for ::sp() */ -// This global function can be used from the VxWorks shell to -// pass arguments to a C main () function. -// usage: -> spa main, "arg1", "arg2" -// All arguments must be quoted, even numbers. +// This global function can be used from the VxWorks shell to pass +// arguments to a C main () function. usage: -> spa main, "arg1", +// "arg2" All arguments must be quoted, even numbers. int spa (FUNCPTR entry, ...) { - static const unsigned int MAX_ARGS = 10; - static char *argv[MAX_ARGS]; - va_list pvar; - int argc; - - // Hardcode a program name because the real one isn't available - // through the VxWorks shell. - argv[0] = "spa ():t"; - - // Peel off arguments to spa () and put into argv. va_arg () - // isn't necessarily supposed to return 0 when done, though - // since the VxWorks shell uses a fixed number (10) of arguments, - // it might 0 the unused ones. - // This function could be used to increase that limit, but then - // it couldn't depend on the trailing 0. So, the number of arguments - // would have to be passed. - va_start (pvar, entry); - for (argc = 1; argc <= MAX_ARGS; ++argc) - { - argv[argc] = va_arg (pvar, char *); - if (argv[argc] == 0) - break; - } + static const unsigned int MAX_ARGS = 10; + static char *argv[MAX_ARGS]; + va_list pvar; + int argc; + + // Hardcode a program name because the real one isn't available + // through the VxWorks shell. + argv[0] = "spa ():t"; + + // Peel off arguments to spa () and put into argv. va_arg () isn't + // necessarily supposed to return 0 when done, though since the + // VxWorks shell uses a fixed number (10) of arguments, it might 0 + // the unused ones. This function could be used to increase that + // limit, but then it couldn't depend on the trailing 0. So, the + // number of arguments would have to be passed. + va_start (pvar, entry); + + for (argc = 1; argc <= MAX_ARGS; ++argc) + { + argv[argc] = va_arg (pvar, char *); - if (argc > MAX_ARGS && argv[argc-1] != 0) - { - // try to read another arg, and warn user if the limit was exceeded - if (va_arg (pvar, char *) != 0) - fprintf (stderr, "spa(): number of arguments limited to %d\n", - MAX_ARGS); - } - else - { - // fill unused argv slots with 0 to get rid of leftovers - // from previous invocations - for ( int i = argc; i <= MAX_ARGS; ++i) - { - argv[i] = 0; - } - } + if (argv[argc] == 0) + break; + } + + if (argc > MAX_ARGS && argv[argc-1] != 0) + { + // try to read another arg, and warn user if the limit was exceeded + if (va_arg (pvar, char *) != 0) + fprintf (stderr, "spa(): number of arguments limited to %d\n", + MAX_ARGS); + } + else + { + // fill unused argv slots with 0 to get rid of leftovers + // from previous invocations + for (int i = argc; i <= MAX_ARGS; ++i) + argv[i] = 0; + } - int ret = ::sp (entry, argc, (int) argv, 0, 0, 0, 0, 0, 0, 0); - va_end (pvar); + int ret = ::sp (entry, argc, (int) argv, 0, 0, 0, 0, 0, 0, 0); + va_end (pvar); - // ::sp () returns the taskID on success: return 0 instead - // if successful - return ret > 0 ? 0 : ret; + // ::sp () returns the taskID on success: return 0 instead if + // successful + return ret > 0 ? 0 : ret; } - #endif /* VXWORKS */ #if !defined (ACE_HAS_SIGINFO_T) @@ -644,7 +644,6 @@ typedef pthread_mutex_t ACE_thread_mutex_t; #define THR_SCOPE_PROCESS 0x00200000 #define THR_INHERIT_SCHED 0x00400000 #define THR_EXPLICIT_SCHED 0x00800000 -#define THR_USE_AFX 0x01000000 #if !defined (ACE_HAS_STHREADS) #if !defined (ACE_HAS_POSIX_SEM) @@ -663,28 +662,6 @@ struct ACE_sema_t }; #endif /* !ACE_HAS_POSIX_SEM */ -// This is used to implement readers/writer locks for POSIX pthreads. -struct ACE_rwlock_t -{ - ACE_mutex_t lock_; - // Serialize access to internal state. - - ACE_cond_t waiting_readers_; - // Reader threads waiting to acquire the lock. - - int num_waiting_readers_; - // Number of waiting readers. - - ACE_cond_t waiting_writers_; - // Writer threads waiting to acquire the lock. - - int num_waiting_writers_; - // Number of waiting writers. - - int ref_count_; - // Value is -1 if writer has the lock, else this keeps track of the - // number of readers holding the lock. -}; #else // If we are on Solaris we can just reuse the existing implementations // of these synchronization types. @@ -751,59 +728,6 @@ typedef char * ACE_thread_t; typedef int ACE_hthread_t; typedef int ACE_thread_key_t; -struct ACE_cond_t - // = TITLE - // This structure is used to implement condition variables on VxWorks - // - // = DESCRIPTION - // At the current time, this stuff only works for threads - // within the same process, which there's only one of on VxWorks. -{ - long waiters_; - // Number of waiting threads. - - ACE_thread_mutex_t waiters_lock_; - // Serialize access to the waiters count. - - ACE_sema_t sema_; - // Queue up threads waiting for the condition to become signaled. - - ACE_event_t waiters_done_; - // An auto reset event used by the broadcast/signal thread to wait - // for the waiting thread(s) to wake up and get a chance at the - // semaphore. - - size_t was_broadcast_; - // Keeps track of whether we were broadcasting or just signaling. -}; - -struct ACE_rwlock_t - // = TITLE - // This is used to implement readers/writer locks on VxWorks - // - // = DESCRIPTION - // At the current time, this stuff only works for threads - // within the same process, which there's only one of on VxWorks. -{ - ACE_mutex_t lock_; - // Serialize access to internal state. - - ACE_cond_t waiting_readers_; - // Reader threads waiting to acquire the lock. - - int num_waiting_readers_; - // Number of waiting readers. - - ACE_cond_t waiting_writers_; - // Writer threads waiting to acquire the lock. - - int num_waiting_writers_; - // Number of waiting writers. - - int ref_count_; - // Value is -1 if writer has the lock, else this keeps track of the - // number of readers holding the lock. -}; #elif defined (ACE_HAS_WTHREADS) typedef CRITICAL_SECTION ACE_thread_mutex_t; typedef struct @@ -817,28 +741,59 @@ typedef struct } ACE_mutex_t; typedef HANDLE ACE_sema_t; +// These need to be different values, neither of which can be 0... +#define USYNC_THREAD 1 +#define USYNC_PROCESS 2 + +#define THR_CANCEL_DISABLE 0 +#define THR_CANCEL_ENABLE 0 +#define THR_CANCEL_DEFERRED 0 +#define THR_CANCEL_ASYNCHRONOUS 0 +#define THR_DETACHED 0 /* ?? ignore in most places */ +#define THR_BOUND 0 /* ?? ignore in most places */ +#define THR_NEW_LWP 0 /* ?? ignore in most places */ +#define THR_SUSPENDED CREATE_SUSPENDED +#define THR_USE_AFX 0x01000000 +#endif /* ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ + +#if defined (ACE_LACKS_COND_T) struct ACE_cond_t // = TITLE - // This structure is used to implement condition variables on NT. + // This structure is used to implement condition variables on + // VxWorks and Win32. // // = DESCRIPTION - // At the current time, this stuff only works for threads - // within the same process. + // At the current time, this stuff only works for threads + // within the same process. { - DWORD waiters_; + long waiters_; // Number of waiting threads. + ACE_thread_mutex_t waiters_lock_; + // Serialize access to the waiters count. + ACE_sema_t sema_; // Queue up threads waiting for the condition to become signaled. + + ACE_event_t waiters_done_; + // An auto reset event used by the broadcast/signal thread to wait + // for the waiting thread(s) to wake up and get a chance at the + // semaphore. + + size_t was_broadcast_; + // Keeps track of whether we were broadcasting or just signaling. }; +#endif /* ACE_LACKS_COND_T */ +#if defined (ACE_LACKS_RWLOCK_T) struct ACE_rwlock_t // = TITLE - // This is used to implement readers/writer locks on NT. + // This is used to implement readers/writer locks on NT, + // VxWorks, and POSIX pthreads. // // = DESCRIPTION - // At the current time, this stuff only works for threads - // within the same process. + // At the current time, this stuff only works for threads + // within the same process. { ACE_mutex_t lock_; // Serialize access to internal state. @@ -859,20 +814,8 @@ struct ACE_rwlock_t // Value is -1 if writer has the lock, else this keeps track of the // number of readers holding the lock. }; +#endif /* ACE_LACKS_RWLOCK_T */ -// These need to be different values, neither of which can be 0... -#define USYNC_THREAD 1 -#define USYNC_PROCESS 2 - -#define THR_CANCEL_DISABLE 0 -#define THR_CANCEL_ENABLE 0 -#define THR_CANCEL_DEFERRED 0 -#define THR_CANCEL_ASYNCHRONOUS 0 -#define THR_DETACHED 0 /* ?? ignore in most places */ -#define THR_BOUND 0 /* ?? ignore in most places */ -#define THR_NEW_LWP 0 /* ?? ignore in most places */ -#define THR_SUSPENDED CREATE_SUSPENDED -#endif /* ACE_HAS_DCETHREADS || ACE_HAS_PTHREADS */ #else /* !ACE_HAS_THREADS, i.e., the OS/platform doesn't support threading. */ // Give these things some reasonable value... #define THR_CANCEL_DISABLE 0 @@ -1806,14 +1749,10 @@ typedef FUNCPTR ACE_THR_FUNC; // where typedef int (*FUNCPTR) (...) typedef void *(*ACE_THR_FUNC)(void *); #endif /* VXWORKS */ -#if defined (ACE_HAS_THR_C_DEST) -// Needed for frigging MVS C++... extern "C" { -typedef void (*ACE_THR_DEST)(void *); +typedef void (*ACE_THR_C_DEST)(void *); } -#else typedef void (*ACE_THR_DEST)(void *); -#endif /* ACE_HAS_THR_C_DEST */ extern "C" { @@ -2422,7 +2361,11 @@ public: static int thr_getspecific (ACE_thread_key_t key, void **data); static int thr_keyfree (ACE_thread_key_t key); static int thr_key_detach (void *inst); +#if defined (ACE_HAS_THR_C_DEST) + static int thr_keycreate (ACE_thread_key_t *key, ACE_THR_C_DEST, void *inst = 0); +#else static int thr_keycreate (ACE_thread_key_t *key, ACE_THR_DEST, void *inst = 0); +#endif /* ACE_HAS_THR_C_DEST */ static int thr_key_used (ACE_thread_key_t key); static size_t thr_min_stack (void); static int thr_setconcurrency (int hint); @@ -743,9 +743,15 @@ ACE_OS::mutex_init (ACE_mutex_t *m, int result = -1; #if defined (ACE_HAS_SETKIND_NP) +#if defined (ACE_HAS_DCETHREADS) + if (::pthread_mutexattr_create (&attributes) == 0 + && ::pthread_mutexattr_setkind_np (&attributes, type) == 0 + && ::pthread_mutex_init (m, attributes) == 0) +#else if (::pthread_mutexattr_init (&attributes) == 0 && ::pthread_mutexattr_setkind_np (&attributes, type) == 0 && ::pthread_mutex_init (m, &attributes) == 0) +#endif /* ACE_HAS_DCETHREADS */ #else if (::pthread_mutexattr_init (&attributes) == 0 #if defined (ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP) @@ -1074,8 +1080,13 @@ ACE_OS::cond_init (ACE_cond_t *cv, int type, LPCTSTR name, void *arg) int result = -1; #if defined (ACE_HAS_SETKIND_NP) +#if defined (ACE_HAS_DCETHREADS) + if (::pthread_condattr_create (&attributes) == 0 + && ::pthread_cond_init (cv, attributes) == 0 +#else if (::pthread_condattr_init (&attributes) == 0 && ::pthread_cond_init (cv, &attributes) == 0 +#endif /* ACE_HAS_DCETHREADS */ #if defined (ACE_HAS_PTHREAD_CONDATTR_SETKIND_NP) && ::pthread_condattr_setkind_np (&attributes, type) == 0 #endif /* ACE_HAS_PTHREAD_CONDATTR_SETKIND_NP */ @@ -1275,7 +1286,6 @@ ACE_OS::cond_timedwait (ACE_cond_t *cv, // ACE_TRACE ("ACE_OS::cond_timedwait"); #if defined (ACE_HAS_THREADS) #if defined (ACE_HAS_WTHREADS) - // Handle the easy case first. if (timeout == 0) return ACE_OS::cond_wait (cv, external_mutex); @@ -1391,41 +1401,71 @@ ACE_OS::cond_timedwait (ACE_cond_t *cv, // ACE_TRACE ("ACE_OS::cond_timedwait"); #if defined (ACE_HAS_THREADS) #if defined (ACE_HAS_WTHREADS) - cv->waiters_++; - - if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) - return -1; - - DWORD result; - + // Handle the easy case first. if (timeout == 0) - // Wait forever. - result = ::WaitForSingleObject (cv->sema_, INFINITE); - else if (timeout->sec () == 0 && timeout->usec () == 0) - // Do a "poll". - result = ::WaitForSingleObject (cv->sema_, 0); + return ACE_OS::cond_wait (cv, external_mutex); + + // It's ok to increment this because the <external_mutex> must be + // locked by the caller. + cv->waiters_++; + + int result = 0; + int error = 0; + int msec_timeout; + + if (timeout->sec () == 0 && timeout->usec () == 0) + msec_timeout = 0; // Do a "poll." else { - // Wait for upto <relative_time> number of milliseconds. Note - // that we must convert between absolute time (which is passed - // as a parameter) and relative time (which is what + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what // WaitForSingleObjects() expects). ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); - result = ::WaitForSingleObject (cv->sema_, relative_time.msec ()); + msec_timeout = relative_time.msec (); } - ACE_OS::thread_mutex_lock (external_mutex); - - cv->waiters_--; + // We keep the lock held just long enough to increment the count of + // waiters by one. Note that we can't keep it held across the call + // to WaitForSingleObject since that will deadlock other calls to + // ACE_OS::cond_signal(). + if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) + return -1; - if (result == WAIT_OBJECT_0) - return 0; - else + // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast(). + result = ::WaitForSingleObject (cv->sema_, msec_timeout); + + if (result != WAIT_OBJECT_0) + // This is a hack, we need to find an appropriate mapping... + error = result == WAIT_TIMEOUT ? ETIME : ::GetLastError (); + else { - errno = result == WAIT_TIMEOUT ? ETIME : ::GetLastError (); - // This is a hack, we need to find an appropriate mapping... - return -1; + // If we are broadcasting, then we need to be smarter about + // locking since there can now be multiple threadsd in the + // crtical section. If we are signaling, however, we don't have + // to worry since there will just be 1 thread here. + if (cv->was_broadcast_) + { + if (ACE_OS::thread_mutex_lock (cv->waiters_lock_) != -1) + { + // By making the waiter responsible for decrementing its count we + // don't have to worry about having an internal mutex. Thanks to + // Karlheinz for recognizing this optimization. + cv->waiters_--; + // Release the signaler/broadcaster if we're the last waiter. + if (cv->waiters_ == 0) + ::SetEvent (cv->waiters_done_); + ACE_OS::thread_mutex_unlock (cv->internal_mutex_); + } + } + else + cv->waiters_--; } + // We must always regain the external mutex, even when errors + // occur because that's the guarantee that we give to our + // callers. + ACE_OS::thread_mutex_lock (external_mutex); + errno = error; + return result; #endif /* ACE_HAS_WTHREADS */ #else ACE_NOTSUP_RETURN (-1); @@ -1439,29 +1479,58 @@ ACE_OS::cond_wait (ACE_cond_t *cv, // ACE_TRACE ("ACE_OS::cond_wait"); #if defined (ACE_HAS_THREADS) #if defined (ACE_HAS_WTHREADS) + // It's ok to increment this because the <external_mutex> must be + // locked by the caller. cv->waiters_++; + int result = 0; + int error = 0; + + // We keep the lock held just long enough to increment the count of + // waiters by one. Note that we can't keep it held across the call + // to ACE_OS::sema_wait() since that will deadlock other calls to + // ACE_OS::cond_signal(). if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) return -1; - int result = 0; - int error = 0; + // Wait to be awakened by a ACE_OS::cond_signal() or + // ACE_OS::cond_broadcast(). + result = ::WaitForSingleObject (cv->sema_, INFINITE); - if (ACE_OS::sema_wait (&cv->sema_) != 0) + if (result != WAIT_OBJECT_0) + // This is a hack, we need to find an appropriate mapping... + error = result == WAIT_TIMEOUT ? ETIME : ::GetLastError (); + else { - result = -1; - error = errno; + // If we are broadcasting, then we need to be smarter about + // locking since there can now be multiple threadsd in the + // crtical section. If we are signaling, however, we don't have + // to worry since there will just be 1 thread here. + if (cv->was_broadcast_) + { + if (ACE_OS::thread_mutex_lock (cv->waiters_lock_) != -1) + { + // By making the waiter responsible for decrementing its count we + // don't have to worry about having an internal mutex. Thanks to + // Karlheinz for recognizing this optimization. + cv->waiters_--; + // Release the signaler/broadcaster if we're the last waiter. + if (cv->waiters_ == 0) + ::SetEvent (cv->waiters_done_); + ACE_OS::thread_mutex_unlock (cv->internal_mutex_); + } + } + else + cv->waiters_--; } - - // We must always regain the mutex, even when errors occur. + // We must always regain the external mutex, even when errors + // occur because that's the guarantee that we give to our + // callers. ACE_OS::thread_mutex_lock (external_mutex); - cv->waiters_--; - // Reset errno in case mutex_lock() also fails... errno = error; return result; - #endif /* ACE_HAS_STHREADS */ #else ACE_NOTSUP_RETURN (-1); @@ -3467,7 +3536,7 @@ ACE_OS::thr_sigsetmask (int how, ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsm, osm), ace_result_), int, -1); #elif defined (ACE_HAS_PTHREADS) && !defined (ACE_HAS_FSU_PTHREADS) -#if defined (ACE_HAS_IRIX62_THREADS) +#if defined (ACE_HAS_IRIX62_THREADS) || defined (ACE_HAS_PTHREADS_XAVIER) ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsm, osm), ace_result_),int, -1); #else @@ -3592,7 +3661,9 @@ ACE_OS::thr_self (ACE_hthread_t &self) { // ACE_TRACE ("ACE_OS::thr_self"); #if defined (ACE_HAS_THREADS) -#if defined (ACE_HAS_THREAD_SELF) +#if defined (ACE_HAS_DCETHREADS) + self = ::pthread_self (); +#elif defined (ACE_HAS_THREAD_SELF) self = ::thread_self (); #elif defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_SETKIND_NP) self = ::pthread_self (); @@ -3662,8 +3733,9 @@ ACE_OS::thr_setprio (ACE_hthread_t thr_id, int prio) #elif (defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS)) && !defined (ACE_LACKS_SETSCHED) struct sched_param param; int result; + int policy = 0; - ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id, policy, ¶m), result), int, -1, result); + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id, &policy, ¶m), result), int, -1, result); prio = param.sched_priority; return result; ACE_NOTSUP_RETURN (-1); diff --git a/ace/Proactor.cpp b/ace/Proactor.cpp index 0484a7e31b7..7229d2ac8c4 100644 --- a/ace/Proactor.cpp +++ b/ace/Proactor.cpp @@ -245,14 +245,14 @@ ACE_Proactor::schedule_timer (ACE_Event_Handler *handler, #define ACE_TIMEOUT_OCCURRED 258 int -ACE_Proactor::handle_events (ACE_Time_Value *how_long) +ACE_Proactor::handle_events (ACE_Time_Value *max_wait_time) { // Stash the current time -- the destructor of this object will // automatically compute how much time elapsed since this method was // called. - ACE_Countdown_Time countdown (how_long); + ACE_Countdown_Time countdown (max_wait_time); - how_long = timer_queue_->calculate_timeout (how_long); + max_wait_time = timer_queue_->calculate_timeout (max_wait_time); ACE_Overlapped_IO *overlapped = 0; u_long bytes_transferred = 0; @@ -260,7 +260,7 @@ ACE_Proactor::handle_events (ACE_Time_Value *how_long) int error = 0; #if defined (ACE_WIN32) ACE_HANDLE io_handle = ACE_INVALID_HANDLE; - int timeout = how_long == 0 ? INFINITE : how_long->msec (); + int timeout = max_wait_time == 0 ? INFINITE : max_wait_time->msec (); BOOL result = 0; diff --git a/ace/Proactor.h b/ace/Proactor.h index 7d85e12fd03..af2431cc1eb 100644 --- a/ace/Proactor.h +++ b/ace/Proactor.h @@ -64,7 +64,7 @@ public: // = Initialization and termination methods. ACE_Proactor (size_t number_of_threads = 0, ACE_Timer_Queue *tq = 0); - // Initialize a proactor. -number_of_threads- is passed to + // Initialize a proactor. <number_of_threads> is passed to // CreateIoCompletionPort. ~ACE_Proactor (void); @@ -83,15 +83,15 @@ public: // integrate I/O completion ports with the ReactorEx. // = Event loop methods. - virtual int handle_events (ACE_Time_Value *how_long = 0); - virtual int handle_events (ACE_Time_Value &how_long); - // Main event loop driver that blocks for -how_long- before + virtual int handle_events (ACE_Time_Value *max_wait_time = 0); + virtual int handle_events (ACE_Time_Value &max_wait_time); + // Main event loop driver that blocks for <max_wait_time> before // returning (will return earlier if I/O or signal events occur). - // Note that -how_long- can be 0, in which case this method blocks + // Note that <max_wait_time> can be 0, in which case this method blocks // until I/O events or signals occur. handle_events just blocks // on GetQueuedCompletionStatus at completion_port_. When I/O // completions arrive, it calls back the Event_Handler associated - // with completed I/O operation. Returns 0 if -how_long- elapses + // with completed I/O operation. Returns 0 if <max_wait_time> elapses // before an event occurs, 1 when if an event occured, and -1 on // failure. diff --git a/ace/README b/ace/README index 01b65c546cb..a5be0ad87dc 100644 --- a/ace/README +++ b/ace/README @@ -132,6 +132,7 @@ ACE_HAS_XLI Platform has the XLI version of TLI ACE_HAS_XT Platform has Xt and Motif ACE_HAS_YIELD_VOID_PTR Platform requires pthread_yield() to take a NULL. ACE_LACKS_CONST_TIMESPEC_PTR Platform forgot const in cond_timewait (e.g., HP/UX). +ACE_LACKS_COND_T Platform lacks condition variables (e.g., Win32 and VxWorks) ACE_LACKS_CONDATTR_PSHARED Platform has no implementation of pthread_condattr_setpshared(), even though it supports pthreads! ACE_LACKS_MADVISE Platform lacks madvise() (e.g., Linux) ACE_LACKS_MALLOC_H Platform lacks malloc.h @@ -146,6 +147,7 @@ ACE_LACKS_POSIX_PROTO Platform lacks POSIX prototypes for certain System V fun ACE_LACKS_PTHREAD_THR_SIGSETMASK Platform lacks pthread_thr_sigsetmask (e.g., MVS, HP/UX, and OSF/1 3.2) ACE_LACKS_RECVMSG Platform lacks recvmsg() (e.g., Linux) ACE_LACKS_RPC_H Platform lacks the ONC RPC header files. +ACE_LACKS_RWLOCK_T Platform lacks readers/writer locks. ACE_LACKS_SBRK Platform lacks a working sbrk() (e.g., Win32 and VxWorks) ACE_LACKS_SEMBUF_T Platform lacks struct sembuf (e.g., Win32 and VxWorks) ACE_LACKS_SETDETACH Platform lacks pthread_attr_setdetachstate() (e.g., HP/UX 10.x) @@ -161,6 +163,7 @@ ACE_LACKS_STRRECVFD Platform doesn't define struct strrecvfd. ACE_LACKS_SYSCALL Platform doesn't have syscall() prototype ACE_LACKS_SYSV_MSQ_PROTOS Platform doesn't have prototypes for Sys V msg()* queues. ACE_LACKS_T_ERRNO Header files lack t_errno for TLI +ACE_LACKS_THREAD_STACK_SIZE Platform lacks pthread_attr_setstacksize() (e.g., Linux pthreads) ACE_LACKS_UCONTEXT_H Platform lacks the ucontext.h file ACE_LACKS_UNIX_DOMAIN_SOCKETS ACE platform has no UNIX domain sockets ACE_LACKS_UTSNAME_T Platform lacks struct utsname (e.g., Win32 and VxWorks) diff --git a/ace/ReactorEx.cpp b/ace/ReactorEx.cpp index 21bcc46f161..9215d3d815e 100644 --- a/ace/ReactorEx.cpp +++ b/ace/ReactorEx.cpp @@ -120,18 +120,19 @@ ACE_ReactorEx::schedule_timer (ACE_Event_Handler *handler, } // Waits for and dispatches all events. Returns -1 on error, 0 if -// how_long expired, and 1 if events were dispatched. +// max_wait_time expired, and 1 if events were dispatched. int -ACE_ReactorEx::handle_events (ACE_Time_Value *how_long, +ACE_ReactorEx::handle_events (ACE_Time_Value *max_wait_time, int wait_all, - ACE_Event_Handler *wait_all_callback) + ACE_Event_Handler *wait_all_callback, + int alertable) { ACE_TRACE ("ACE_ReactorEx::handle_events"); // Stash the current time -- the destructor of this object will // automatically compute how much time elapsed since this method was // called. - ACE_Countdown_Time countdown (how_long); + ACE_Countdown_Time countdown (max_wait_time); #if defined (ACE_MT_SAFE) ACE_GUARD_RETURN (ACE_ReactorEx_Token, ace_mon, this->token_, -1); @@ -148,16 +149,26 @@ ACE_ReactorEx::handle_events (ACE_Time_Value *how_long, } // Check for pending timeout events. - ACE_Time_Value *wait_time = timer_queue_->calculate_timeout (how_long); + ACE_Time_Value *wait_time = timer_queue_->calculate_timeout (max_wait_time); // Translate into Win32 time value. int timeout = wait_time == 0 ? INFINITE : wait_time->msec (); + DWORD wait_status; // Wait for any of handles_ to be active, or until timeout expires. // If wait_all is true, then wait for all handles_ to be active. - DWORD wait_status = ::WaitForMultipleObjects (active_handles_, - handles_, - wait_all, - timeout); + + if (alertable) + // Allow asynchronous completion of ReadFileEx and WriteFileEx + // operations. + wait_status= ::WaitForMultipleObjectsEx (active_handles_, + handles_, + wait_all, + timeout); + else + wait_status= ::WaitForMultipleObjects (active_handles_, + handles_, + wait_all, + timeout); // Expire all pending timers. this->timer_queue_->expire (); diff --git a/ace/ReactorEx.h b/ace/ReactorEx.h index 6c4ec881b8a..ef72259970f 100644 --- a/ace/ReactorEx.h +++ b/ace/ReactorEx.h @@ -61,11 +61,10 @@ private: class ACE_Export ACE_ReactorEx_Notify : public ACE_Event_Handler // = TITLE - // Unblock the <ACE_ReactorEx> from its event loop, passing it an - // optional <ACE_Event_Handler> to dispatch. + // Unblock the <ACE_ReactorEx> from its event loop, passing it an + // optional <ACE_Event_Handler> to dispatch. // // = DESCRIPTION - // // This implementation is necessary for cases where the // <ACE_ReactorEx> is run in a multi-threaded program. In this // case, we need to be able to unblock WaitForMultipleObjects() @@ -130,61 +129,73 @@ public: virtual ~ACE_ReactorEx (void); // Close down the ReactorEx and release all of its resources. - // = Event loop drivers. Main event loop driver that blocks for - // -how_long- before returning (will return earlier if I/O or signal - // events occur). Note that -how_long- can be 0, in which case this - // method blocks until I/O events or signals occur. Returns 0 if - // timed out, 1 if an event occurred, and -1 if an error occured. - // -how_long- is decremented to reflect how much time the call to - // handle_events took. For instance, if a time value of 3 seconds - // is passed to handle_events and an event occurs after 2 seconds, - // -how_long- will equal 1 second. This can be used if an - // application wishes to handle events for some fixed amount of - // time. If wait_all is TRUE, then handle_events will only dispatch - // the handlers if *all* handles become active. If a timeout - // occurs, then no handlers will be dispatched. If - // <wait_all_callback> is NULL then we dispatch the <handle_signal> - // method on each and every HANDLE in the dispatch array. - // Otherwise, we just call back the <handle_signal> method of the - // <wait_all_callback> object, after first assigning the siginfo_t - // <si_handles_> argument to point to the array of signaled handles. - virtual int handle_events (ACE_Time_Value *how_long = 0, + // = Event loop drivers. + + virtual int handle_events (ACE_Time_Value *max_wait_time = 0, int wait_all = 0, - ACE_Event_Handler *wait_all_callback = 0); - virtual int handle_events (ACE_Time_Value &how_long, + ACE_Event_Handler *wait_all_callback = 0, + int alertable = 0); + // This event loop driver blocks for up to <max_wait_time> for I/O + // or signaled events occur. Note that <max_wait_time> can be 0, in + // which case this method blocks until I/O events or signaled events + // occur. Returns 0 if timed out, 1 if an event occurred, and -1 if + // an error occured. <max_wait_time> is decremented to reflect how + // much time this call took. For instance, if a time value of 3 + // seconds is passed to handle_events and an event occurs after 2 + // seconds, <max_wait_time> will equal 1 second. This can be used + // if an application wishes to handle events for some fixed amount + // of time. + // + // If <wait_all> is TRUE, then handle_events will only dispatch the + // handlers if *all* handles become active. If a timeout occurs, + // then no handlers will be dispatched. If <wait_all_callback> is 0 + // then we dispatch the <handle_signal> method on each and every + // registered HANDLE. Otherwise, we just call back the + // <handle_signal> method of the <wait_all_callback> object, after + // first assigning the siginfo_t <si_handles_> argument to point to + // the array of signaled handles. + // + // If <alertable> is true, then <WaitForMultipleObjectsEx> is used + // as the demultiplexing call, otherwise <WaitForMultipleObjects> is + // used. + + virtual int handle_events (ACE_Time_Value &max_wait_time, int wait_all = 0, - ACE_Event_Handler *wait_all_callback = 0); + ACE_Event_Handler *wait_all_callback = 0, + int alertable = 0); + // This method is just like the one above, except the <max_wait_time> + // value is a reference and must therefore never be NULL. // = Register and remove Handlers. virtual int register_handler (ACE_Event_Handler *eh, ACE_HANDLE handle = ACE_INVALID_HANDLE); - // Register an Event_Handler -eh-. If handle == ACE_INVALID_HANDLE - // the ReactorEx will call eh->get_handle() to extract the - // underlying I/O handle). + // Register an Event_Handler <eh>. If handle == ACE_INVALID_HANDLE + // the <ReactorEx> will call the <get_handle> method of <eh> to + // extract the underlying I/O handle. virtual int remove_handler (ACE_Event_Handler *eh, ACE_Reactor_Mask mask = 0); - // Removes -eh- from the ReactorEx. Note that the ReactorEx will - // call eh->get_handle() to extract the underlying I/O handle. If - // -mask- == ACE_Event_Handler::DONT_CALL then the -handle_close- - // method of the -eh- is not invoked. + // Removes <eh> from the ReactorEx. Note that the ReactorEx will + // call the <get_handle> method of <eh> to extract the underlying + // I/O handle. If <mask> == ACE_Event_Handler::DONT_CALL then the + // <handle_close> method of the <eh> is not invoked. int notify (ACE_Event_Handler * = 0, ACE_Reactor_Mask = ACE_Event_Handler::EXCEPT_MASK); // Wakeup <ACE_ReactorEx> if currently blocked in - // WaitForMultipleObjects(). + // <WaitForMultipleObjects>. // = Timer management. virtual int schedule_timer (ACE_Event_Handler *eh, const void *arg, const ACE_Time_Value &delta, const ACE_Time_Value &interval = ACE_Time_Value::zero); - // Schedule an Event Handler -eh- that will expire after -delta- - // amount of time. If it expires then -arg- is passed in as the - // value to eh->handle_timeout. If -interval- is != to - // ACE_Time_Value::zero then it is used to reschedule -eh- + // Schedule an Event Handler <eh> that will expire after <delta> + // amount of time. If it expires then <arg> is passed in as the + // value to <handle_timeout> method call on <eh>. If <interval> is + // != to ACE_Time_Value::zero then it is used to reschedule <eh> // automatically. This method returns a timer handle that uniquely - // identifies the -eh- in an internal list. This timer handle can + // identifies the <eh> in an internal list. This timer handle can // be used to cancel an Event_Handler before it expires. The // cancellation ensures that timer_ids are unique up to values of // greater than 2 billion timers. As long as timers don't stay @@ -193,10 +204,10 @@ public: virtual int cancel_timer (ACE_Event_Handler *event_handler); // Cancel all Event_Handlers that match the address of - // -event_handler-. + // <event_handler>. virtual int cancel_timer (int timer_id, const void **arg = 0); - // Cancel the single Event_Handler that matches the -timer_id- value + // Cancel the single Event_Handler that matches the <timer_id> value // (which was returned from the schedule method). If arg is // non-NULL then it will be set to point to the ``magic cookie'' // argument passed in when the Event_Handler was registered. This @@ -210,7 +221,7 @@ public: protected: int dispatch (size_t index); - // Dispatches any active handles from handles_[-index-] to + // Dispatches any active handles from handles_[<index>] to // handles_[active_handles_] using <WaitForMultipleObjects> to poll // through our handle set looking for active handles. diff --git a/ace/ReactorEx.i b/ace/ReactorEx.i index fda66981674..a5cd53034a2 100644 --- a/ace/ReactorEx.i +++ b/ace/ReactorEx.i @@ -20,9 +20,12 @@ ACE_ReactorEx::cancel_timer (int timer_id, ACE_INLINE int ACE_ReactorEx::handle_events (ACE_Time_Value &how_long, - int wait_all) + int wait_all, + ACE_Event_Handler *wait_all_callback, + int alertable) { - return this->handle_events (&how_long, wait_all); + return this->handle_events (&how_long, wait_all, + wait_all_callback, alertable); } #endif /* ACE_WIN32 */ diff --git a/ace/SV_Semaphore_Complex.cpp b/ace/SV_Semaphore_Complex.cpp index 09aac60b0bf..1bcd3d64cec 100644 --- a/ace/SV_Semaphore_Complex.cpp +++ b/ace/SV_Semaphore_Complex.cpp @@ -103,12 +103,11 @@ ACE_SV_Semaphore_Complex::open (key_t k, // Get the value of the process counter. If it equals 0, then no // one has initialized the ACE_SV_Semaphore yet. - int semval; + int semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1); - if ((semval = ACE_SV_Semaphore_Simple::control (GETVAL, 0, 1)) < 0) + if (semval == -1) return this->init (); - - if (semval == 0) + else if (semval == 0) { // We should initialize by doing a SETALL, but that would // clear the adjust value that we set when we locked the diff --git a/ace/SV_Semaphore_Simple.cpp b/ace/SV_Semaphore_Simple.cpp index 29d97dfa8a3..f7a6809dbb2 100644 --- a/ace/SV_Semaphore_Simple.cpp +++ b/ace/SV_Semaphore_Simple.cpp @@ -121,26 +121,26 @@ ACE_SV_Semaphore_Simple::name_2_key (const char *name) { ACE_TRACE ("ACE_SV_Semaphore_Simple::name_2_key"); - if (name == 0 || !isalpha (*name)) + if (name == 0) { errno = EINVAL; return ACE_INVALID_SEM_KEY; } - - // The key is the character value of the first LUSED chars from name - // placed in proto. + else + { + // Basically "hash" the values in the <name>. This won't + // necessarily guarantee uniqueness of all keys. - u_long proto = 0; + u_long proto = 0; - for (int i = 0; i < LUSED; ++i) - { - if (*name == '\0') - break; - proto <<= 8; - proto |= *name++ & 0xff; - } + for (int i = 0; name[i] != '\0'; ++i) + { + proto <<= 8; + proto |= *name++ & 0xff; + } - return (key_t) proto; + return (key_t) proto; + } } // Open or create a ACE_SV_Semaphore. We return 1 if all is OK, else diff --git a/ace/SV_Semaphore_Simple.i b/ace/SV_Semaphore_Simple.i index 1e159f36604..a66806507f2 100644 --- a/ace/SV_Semaphore_Simple.i +++ b/ace/SV_Semaphore_Simple.i @@ -6,9 +6,6 @@ #include "ace/SV_Semaphore_Simple.h" #include "ace/Trace.h" -#undef LUSED -#define LUSED 4 /* # of chars used from name */ - inline int ACE_SV_Semaphore_Simple::control (int cmd, semun arg, diff --git a/ace/Signal.cpp b/ace/Signal.cpp index 50071e83619..bceff59af42 100644 --- a/ace/Signal.cpp +++ b/ace/Signal.cpp @@ -29,7 +29,10 @@ static ACE_SignalHandler ace_signal_handler_dispatcher = ACE_SignalHandler (ace_ static ACE_SignalHandler ace_signal_handlers_dispatcher = ACE_SignalHandler (ace_sig_handlers_dispatch); #else static ACE_SignalHandler ace_signal_handler_dispatcher = ACE_SignalHandler (ACE_Sig_Handler::dispatch); + +#if !defined (HPUX) static ACE_SignalHandler ace_signal_handlers_dispatcher = ACE_SignalHandler (ACE_Sig_Handlers::dispatch); +#endif /* HPUX */ #endif /* ACE_HAS_SIG_C_FUNC */ #if defined (ACE_MT_SAFE) @@ -331,9 +334,9 @@ ACE_Sig_Adapter::handle_signal (int signum, // ---------------------------------------- // The following classes are local to this file. -// HPUX sucks big time! +// There are bugs with HP/UX's C++ compiler that prevents this stuff +// from compiling... #if !defined (HPUX) -// This needs to be fixed... #define ACE_MAX_SIGNAL_HANDLERS size_t (20) // Keeps track of the id that uniquely identifies each registered diff --git a/ace/Signal.h b/ace/Signal.h index f627bd73222..f95703de081 100644 --- a/ace/Signal.h +++ b/ace/Signal.h @@ -271,7 +271,6 @@ private: // This is a normal C function. }; -// HPUX sucks big time! #if !defined (HPUX) class ACE_Export ACE_Sig_Handlers : public ACE_Sig_Handler // = TITLE diff --git a/ace/Synch.cpp b/ace/Synch.cpp index c8fb75545ab..b163eecc7a6 100644 --- a/ace/Synch.cpp +++ b/ace/Synch.cpp @@ -16,9 +16,36 @@ ACE_ALLOC_HOOK_DEFINE(ACE_Null_Mutex) ACE_ALLOC_HOOK_DEFINE(ACE_File_Lock) ACE_ALLOC_HOOK_DEFINE(ACE_RW_Process_Mutex) - ACE_ALLOC_HOOK_DEFINE(ACE_Process_Mutex) +ACE_TSS_Adapter::ACE_TSS_Adapter (void *object, ACE_THR_DEST f) + : ts_obj_ (object), + func_ (f) +{ + // ACE_TRACE ("ACE_TSS_Adapter::ACE_TSS_Adapter"); +} + +void +ACE_TSS_Adapter::cleanup (void) +{ + // ACE_TRACE ("ACE_TSS_Adapter::~ACE_TSS_Adapter"); + (*this->func_)(this->ts_obj_); // call cleanup routine for ts_obj_ +} + +extern "C" void +ACE_TSS_C_cleanup (void *object) +{ + // ACE_TRACE ("ACE_TSS_C_cleanup"); + if (object != 0) + { + ACE_TSS_Adapter *tss_adapter = (ACE_TSS_Adapter *) object; + // Perform cleanup on the real TS object. + tss_adapter->cleanup (); + // Delete the adapter object. + delete tss_adapter; + } +} + void ACE_Process_Mutex::dump (void) const { @@ -297,8 +324,6 @@ ACE_Mutex::~ACE_Mutex (void) ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Mutex::~ACE_Mutex")); } -#if defined (ACE_HAS_THREADS) - ACE_Event::ACE_Event (int manual_reset, int initial_state, int type, @@ -406,6 +431,8 @@ ACE_Auto_Event::dump (void) const ACE_Event::dump (); } +#if defined (ACE_HAS_THREADS) + ACE_ALLOC_HOOK_DEFINE(ACE_Recursive_Thread_Mutex) ACE_ALLOC_HOOK_DEFINE(ACE_Thread_Mutex_Guard) diff --git a/ace/Synch.h b/ace/Synch.h index 0e2aba63078..1c0c5335b87 100644 --- a/ace/Synch.h +++ b/ace/Synch.h @@ -490,7 +490,35 @@ protected: ACE_Null_Mutex_Guard (const ACE_Null_Mutex_Guard &) {} }; -#if defined (ACE_HAS_THREADS) /* ACE platform supports some form of threading. */ +class ACE_TSS_Adapter + // = TITLE + // This class encapsulates a TSS object and its associated + // C++ destructor function. It is used by the ACE_TSS... + // methods (in Synch_T.cpp) in order to allow an extern + // "C" cleanup routine to be used. Needed by the "frigging" + // MVS C++ compiler. + // + // = DESCRIPTION + // Objects of this class are stored in thread specific + // storage. ts_obj_ points to the "real" object and + // func_ is a pointer to the C++ cleanup function for ts_obj_. + // +{ +public: + ACE_TSS_Adapter (void *object, ACE_THR_DEST f); + // Initialize the adapter. + + void cleanup (void); + // Perform the cleanup operation. + +//private: + + void *ts_obj_; + // The real TS object. + + ACE_THR_DEST func_; + // The real cleanup routine for ts_obj; +}; class ACE_Export ACE_Event // = TITLE @@ -610,6 +638,8 @@ public: // Declare the dynamic allocation hooks }; +#if defined (ACE_HAS_THREADS) /* ACE platform supports some form of threading. */ + class ACE_Export ACE_Thread_Mutex // = TITLE // ACE_Thread_Mutex wrapper (only valid for threads in the same diff --git a/ace/Synch_T.cpp b/ace/Synch_T.cpp index 4357c9702a3..60e0b02908f 100644 --- a/ace/Synch_T.cpp +++ b/ace/Synch_T.cpp @@ -246,6 +246,13 @@ ACE_TSS<TYPE>::dump (void) const } #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) +template <class TYPE> void +ACE_TSS<TYPE>::cleanup (void *ptr) +{ + // Cast this to the concrete TYPE * so the destructor gets called. + delete (TYPE *) ptr; +} + template <class TYPE> ACE_TSS<TYPE>::ACE_TSS (TYPE *ts_obj) : once_ (0), @@ -262,7 +269,11 @@ ACE_TSS<TYPE>::ACE_TSS (TYPE *ts_obj) ACE_ASSERT (this->once_ == 0); if (ACE_Thread::keycreate (&this->key_, - &ACE_TSS<TYPE>::cleanup, +#if defined (ACE_HAS_THR_C_DEST) + &ACE_TSS_C_cleanup, +#else + &ACE_TSS<TYPE>::cleanup, +#endif /* ACE_HAS_THR_C_DEST */ (void *) this) != 0) { int errnum = errno; @@ -274,8 +285,22 @@ ACE_TSS<TYPE>::ACE_TSS (TYPE *ts_obj) this->once_ = 1; +#if defined (ACE_HAS_THR_C_DEST) + // Encapsulate a ts_obj and it's destructor in an ACE_TSS_Adapter + ACE_TSS_Adapter *tss_adapter; + ACE_NEW (tss_adapter, + ACE_TSS_Adapter ((void *)ts_obj, ACE_TSS<TYPE>::cleanup)); + + // Put the adapter in thread specific storage + if (ACE_Thread::setspecific (this->key_, (void *) tss_adapter) != 0) + { + delete tss_adapter; + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Thread::setspecific() failed!")); + } +#else if (ACE_Thread::setspecific (this->key_, (void *) ts_obj) != 0) - ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Thread::setspecific() failed!")); + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Thread::setspecific() failed!")); +#endif /* ACE_HAS_THR_C_DEST */ } } @@ -293,8 +318,12 @@ ACE_TSS<TYPE>::ts_get (void) const if (this->once_ == 0) { if (ACE_Thread::keycreate ((ACE_thread_key_t *) &this->key_, - &ACE_TSS<TYPE>::cleanup, - (void *) this) != 0) +#if defined (ACE_HAS_THR_C_DEST) + &ACE_TSS_C_cleanup, +#else + &ACE_TSS<TYPE>::cleanup, +#endif /* ACE_HAS_THR_C_DEST */ + (void *) this) != 0) return 0; // Major problems, this should *never* happen! else // This *must* come last to avoid race conditions! Note @@ -305,6 +334,16 @@ ACE_TSS<TYPE>::ts_get (void) const TYPE *ts_obj = 0; +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + + // Get the adapter from thread-specific storage + if (ACE_Thread::getspecific (this->key_, (void **) &tss_adapter) == -1) + return 0; // This should not happen! + + // Check to see if this is the first time in for this thread. + if (tss_adapter == 0) +#else // Get the ts_obj from thread-specific storage. Note that no locks // are required here... if (ACE_Thread::getspecific (this->key_, (void **) &ts_obj) == -1) @@ -312,6 +351,7 @@ ACE_TSS<TYPE>::ts_get (void) const // Check to see if this is the first time in for this thread. if (ts_obj == 0) +#endif /* ACE_HAS_THR_C_DEST */ { // Allocate memory off the heap and store it in a pointer in // thread-specific storage (on the stack...). @@ -321,6 +361,19 @@ ACE_TSS<TYPE>::ts_get (void) const if (ts_obj == 0) return 0; +#if defined (ACE_HAS_THR_C_DEST) + // Encapsulate a ts_obj and it's destructor in an ACE_TSS_Adapter + ACE_NEW_RETURN (tss_adapter, + ACE_TSS_Adapter (ts_obj, ACE_TSS<TYPE>::cleanup), 0); + + // Put the adapter in thread specific storage + if (ACE_Thread::setspecific (this->key_, (void *) tss_adapter) != 0) + { + delete tss_adapter; + delete ts_obj; + return 0; // Major problems, this should *never* happen! + } +#else // Store the dynamically allocated pointer in thread-specific // storage. if (ACE_Thread::setspecific (this->key_, (void *) ts_obj) != 0) @@ -328,9 +381,14 @@ ACE_TSS<TYPE>::ts_get (void) const delete ts_obj; return 0; // Major problems, this should *never* happen! } +#endif /* ACE_HAS_THR_C_DEST */ } +#if defined (ACE_HAS_THR_C_DEST) + return (TYPE *) tss_adapter->ts_obj_; // return the underlying ts object +#else return ts_obj; +#endif /* ACE_HAS_THR_C_DEST */ } // Get the thread-specific object for the key associated with this @@ -348,11 +406,20 @@ ACE_TSS<TYPE>::ts_object (void) const else { TYPE *ts_obj = 0; +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + // Get the tss adapter from thread-specific storage + if (ACE_Thread::getspecific (this->key_, (void **) &tss_adapter) == -1) + return 0; // This should not happen! + else if (tss_adapter != 0) + // Extract the real TS object. + ts_obj = (TYPE *) tss_adapter->ts_obj_; +#else if (ACE_Thread::getspecific (this->key_, (void **) &ts_obj) == -1) return 0; // This should not happen! - else - return ts_obj; +#endif /* ACE_HAS_THR_C_DEST */ + return ts_obj; } } @@ -368,23 +435,38 @@ ACE_TSS<TYPE>::ts_object (TYPE *new_ts_obj) { TYPE *ts_obj = 0; +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + + if (ACE_Thread::getspecific (this->key_, (void **) &tss_adapter) == -1) + return 0; // This should not happen! + + if (tss_adapter != 0) + { + ts_obj = (TYPE *) tss_adapter->ts_obj_; + delete tss_adapter; // don't need this anymore + } + + ACE_NEW_RETURN (tss_adapter, + ACE_TSS_Adapter ((void *)new_ts_obj, ACE_TSS<TYPE>::cleanup), + 0); + + if (ACE_Thread::setspecific (this->key_, (void *) tss_adapter) == -1) + { + delete tss_adapter; + return ts_obj; // This should not happen! + } +#else if (ACE_Thread::getspecific (this->key_, (void **) &ts_obj) == -1) - return 0; // This should not happen! + return 0; // This should not happen! if (ACE_Thread::setspecific (this->key_, (void *) new_ts_obj) == -1) - return ts_obj; // This should not happen! + return ts_obj; // This should not happen! +#endif /* ACE_HAS_THR_C_DEST */ else return ts_obj; } } -/* static */ -template <class TYPE> void -ACE_TSS<TYPE>::cleanup (void *ptr) -{ - // This cast is necessary to invoke the destructor (if necessary). - delete (TYPE *) ptr; -} - ACE_ALLOC_HOOK_DEFINE(ACE_TSS_Guard) template <class LOCK> void @@ -405,7 +487,11 @@ ACE_TSS_Guard<LOCK>::init_key (void) this->key_ = ACE_OS::NULL_key; ACE_Thread::keycreate (&this->key_, +#if defined (ACE_HAS_THR_C_DEST) + &ACE_TSS_C_cleanup, +#else &ACE_TSS_Guard<LOCK>::cleanup, +#endif /* ACE_HAS_THR_C_DEST */ (void *) this); } @@ -422,7 +508,15 @@ ACE_TSS_Guard<LOCK>::release (void) // ACE_TRACE ("ACE_TSS_Guard<LOCK>::release"); ACE_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *)tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + return guard->release (); } @@ -432,7 +526,15 @@ ACE_TSS_Guard<LOCK>::remove (void) // ACE_TRACE ("ACE_TSS_Guard<LOCK>::remove"); ACE_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *)tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + return guard->remove (); } @@ -442,7 +544,15 @@ ACE_TSS_Guard<LOCK>::~ACE_TSS_Guard (void) // ACE_TRACE ("ACE_TSS_Guard<LOCK>::~ACE_TSS_Guard"); ACE_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *)tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + // Make sure that this pointer is NULL when we shut down... ACE_Thread::setspecific (this->key_, 0); ACE_Thread::keyfree (this->key_); @@ -467,7 +577,16 @@ ACE_TSS_Guard<LOCK>::ACE_TSS_Guard (LOCK &lock, int block) this->init_key (); ACE_Guard<LOCK> *guard; ACE_NEW (guard, ACE_Guard<LOCK> (lock, block)); + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter; + ACE_NEW (tss_adapter, + ACE_TSS_Adapter ((void *) guard, + ACE_TSS_Guard<LOCK>::cleanup)); + ACE_Thread::setspecific (this->key_, (void *) tss_adapter); +#else ACE_Thread::setspecific (this->key_, (void *) guard); +#endif /* ACE_HAS_THR_C_DEST */ } template <class LOCK> int @@ -476,7 +595,15 @@ ACE_TSS_Guard<LOCK>::acquire (void) // ACE_TRACE ("ACE_TSS_Guard<LOCK>::acquire"); ACE_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *) tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + return guard->acquire (); } @@ -486,7 +613,15 @@ ACE_TSS_Guard<LOCK>::tryacquire (void) // ACE_TRACE ("ACE_TSS_Guard<LOCK>::tryacquire"); ACE_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *) tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + return guard->tryacquire (); } @@ -498,7 +633,16 @@ ACE_TSS_Write_Guard<LOCK>::ACE_TSS_Write_Guard (LOCK &lock, int block) this->init_key (); ACE_Guard<LOCK> *guard; ACE_NEW (guard, ACE_Write_Guard<LOCK> (lock, block)); + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter; + ACE_NEW (tss_adapter, + ACE_TSS_Adapter ((void *) guard, + ACE_TSS_Guard<LOCK>::cleanup)); + ACE_Thread::setspecific (this->key_, (void *) tss_adapter); +#else ACE_Thread::setspecific (this->key_, (void *) guard); +#endif /* ACE_HAS_THR_C_DEST */ } template <class LOCK> int @@ -507,7 +651,15 @@ ACE_TSS_Write_Guard<LOCK>::acquire (void) // ACE_TRACE ("ACE_TSS_Write_Guard<LOCK>::acquire"); ACE_Write_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *) tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + return guard->acquire_write (); } @@ -517,7 +669,15 @@ ACE_TSS_Write_Guard<LOCK>::tryacquire (void) // ACE_TRACE ("ACE_TSS_Write_Guard<LOCK>::tryacquire"); ACE_Write_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *) tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + return guard->tryacquire_write (); } @@ -552,7 +712,16 @@ ACE_TSS_Read_Guard<LOCK>::ACE_TSS_Read_Guard (LOCK &lock, int block) this->init_key (); ACE_Guard<LOCK> *guard; ACE_NEW (guard, ACE_Read_Guard<LOCK> (lock, block)); + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter; + ACE_NEW (tss_adapter, + ACE_TSS_Adapter ((void *)guard, + ACE_TSS_Guard<LOCK>::cleanup)); + ACE_Thread::setspecific (this->key_, (void *) tss_adapter); +#else ACE_Thread::setspecific (this->key_, (void *) guard); +#endif /* ACE_HAS_THR_C_DEST */ } template <class LOCK> int @@ -561,7 +730,15 @@ ACE_TSS_Read_Guard<LOCK>::acquire (void) // ACE_TRACE ("ACE_TSS_Read_Guard<LOCK>::acquire"); ACE_Read_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *)tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + return guard->acquire_read (); } @@ -571,7 +748,15 @@ ACE_TSS_Read_Guard<LOCK>::tryacquire (void) // ACE_TRACE ("ACE_TSS_Read_Guard<LOCK>::tryacquire"); ACE_Read_Guard<LOCK> *guard = 0; + +#if defined (ACE_HAS_THR_C_DEST) + ACE_TSS_Adapter *tss_adapter = 0; + ACE_Thread::getspecific (this->key_, (void **) &tss_adapter); + guard = (ACE_Guard<LOCK> *) tss_adapter->ts_obj_; +#else ACE_Thread::getspecific (this->key_, (void **) &guard); +#endif /* ACE_HAS_THR_C_DEST */ + return guard->tryacquire_read (); } diff --git a/ace/Thread.h b/ace/Thread.h index 8d71fb8a29d..bb5411e8b95 100644 --- a/ace/Thread.h +++ b/ace/Thread.h @@ -132,7 +132,11 @@ public: // Change and/or examine calling thread's signal mask. static int keycreate (ACE_thread_key_t *keyp, +#if defined (ACE_HAS_THR_C_DEST) + ACE_THR_C_DEST destructor, +#else ACE_THR_DEST destructor, +#endif /* ACE_HAS_THR_C_DEST */ void * = 0); // Allocates a <keyp> that is used to identify data that is specific // to each thread in the process. The key is global to all threads diff --git a/ace/Thread.i b/ace/Thread.i index 1a5e2746f65..1684c0c7f14 100644 --- a/ace/Thread.i +++ b/ace/Thread.i @@ -9,7 +9,11 @@ ACE_INLINE int ACE_Thread::keycreate (ACE_thread_key_t *keyp, +#if defined (ACE_HAS_THR_C_DEST) + ACE_THR_C_DEST destructor, +#else ACE_THR_DEST destructor, +#endif /* ACE_HAS_THR_C_DEST */ void *inst) { ACE_TRACE ("ACE_Thread::keycreate"); diff --git a/ace/config-aix-4.1.x.h b/ace/config-aix-4.1.x.h index 6ee505fc0bf..04b6529e0f7 100644 --- a/ace/config-aix-4.1.x.h +++ b/ace/config-aix-4.1.x.h @@ -95,6 +95,7 @@ // EYE assume it does for now. #define ACE_LACKS_PTHREAD_THR_SIGSETMASK #define ACE_HAS_PTHREADS +#define ACE_LACKS_RWLOCK_T #define ACE_PTHREADS_MAP // include there diff --git a/ace/config-hpux-10.x.h b/ace/config-hpux-10.x.h index 83ff5c4eafb..b40b27c39ea 100644 --- a/ace/config-hpux-10.x.h +++ b/ace/config-hpux-10.x.h @@ -58,6 +58,7 @@ #define ACE_HAS_THREADS #define ACE_HAS_PTHREADS +#define ACE_LACKS_RWLOCK_T #define ACE_MT_SAFE #define ACE_HAS_SIGINFO_T #define ACE_LACKS_PTHREAD_THR_SIGSETMASK diff --git a/ace/config-irix6.2-sgic++.h b/ace/config-irix6.2-sgic++.h index c35f452cb17..47076738861 100644 --- a/ace/config-irix6.2-sgic++.h +++ b/ace/config-irix6.2-sgic++.h @@ -42,6 +42,7 @@ // IRIX 6.2 supports some variant of POSIX Pthreads, is it stock DCE? #define ACE_HAS_PTHREADS +#define ACE_LACKS_RWLOCK_T // Platform/compiler has the sigwait(2) prototype #define ACE_HAS_SIGWAIT diff --git a/ace/config-linux-lxpthreads.h b/ace/config-linux-lxpthreads.h new file mode 100644 index 00000000000..66dab145a99 --- /dev/null +++ b/ace/config-linux-lxpthreads.h @@ -0,0 +1,104 @@ +/* -*- C++ -*- */ +// $Id$ + +// The following configuration file is designed to work for Linux +// platforms using GNU C++ and L. Xavier's pthreads package. + +#if !defined (ACE_CONFIG_H) +#define ACE_CONFIG_H + +// Fixes a problem with new versions of Linux... +#ifndef msg_accrights +#undef msg_control +#define msg_accrights msg_control +#endif + +#ifndef msg_accrightslen +#undef msg_controllen +#define msg_accrightslen msg_controllen +#endif + +#define ACE_HAS_POSIX_TIME +#define ACE_LACKS_STRRECVFD + +// Platform supports System V IPC (most versions of UNIX, but not Win32) +#define ACE_HAS_SYSV_IPC + +// Compiler/platform contains the <sys/syscall.h> file. +#define ACE_HAS_SYSCALL_H + +#define ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES + +// Platforms lacks UNIX domain sockets. +//#define ACE_LACKS_UNIX_DOMAIN_SOCKETS + +// Compiler/platform supports alloca(). +#define ACE_HAS_ALLOCA + +//#define ACE_LACKS_SENDMSG +//#define ACE_LACKS_RECVMSG +#define ACE_LACKS_MSYNC +#define ACE_LACKS_MADVISE + +// Compiler/platform has <alloca.h> +#define ACE_HAS_ALLOCA_H + +// Compiler/platform has the getrusage() system call. +#define ACE_HAS_GETRUSAGE + +// Compiler/platform defines the sig_atomic_t typedef. +#define ACE_HAS_SIG_ATOMIC_T + +// Compiler/platform supports sys_siglist array. +#define ACE_HAS_SYS_SIGLIST + +// Compiler/platform defines a union semun for SysV shared memory. +#define ACE_HAS_SEMUN + +// Compiler supports the ssize_t typedef. +#define ACE_HAS_SSIZE_T + +// Compiler/platform supports strerror (). +#define ACE_HAS_STRERROR + +// Defines the page size of the system. +#define ACE_PAGE_SIZE 4096 + +#define ACE_HAS_SUNOS4_GETTIMEOFDAY +#define LINUX 1.2.10 + +// Turns off the tracing feature. +#if !defined (ACE_NTRACE) +#define ACE_NTRACE 1 +#endif /* ACE_NTRACE */ + +// Linux defines struct msghdr in /usr/include/socket.h +#define ACE_HAS_MSG + +// TDN - adapted from file for SunOS4 platforms using the GNU g++ compiler +// Compiler's template mechanism must see source code (i.e., .C files). +#define ACE_TEMPLATES_REQUIRE_SOURCE + +#define ACE_TEMPLATES_REQUIRE_SPECIALIZATION + +// Compiler doesn't support static data member templates. +#define ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES + +// Yes, we do have threads. +#define ACE_HAS_THREADS +// And they're even POSIX pthreads (MIT implementation) +#define ACE_HAS_PTHREADS +#define ACE_MT_SAFE +#define ACE_HAS_THREAD_SPECIFIC_STORAGE +#define ACE_HAS_PTHREADS_XAVIER // JCEJ 12/19/96 +#define ACE_HAS_SIGWAIT +#define ACE_LACKS_CONDATTR_PSHARED +#define ACE_LACKS_THREAD_STACK_ADDR // JCEJ 12/17/96 +#define ACE_LACKS_THREAD_STACK_SIZE // JCEJ 12/17/96 + +// To use pthreads on Linux you'll need to use the MIT version, for +// now... +#define _MIT_POSIX_THREADS 1 +#include /**/ <pthread.h> + +#endif /* ACE_CONFIG_H */ diff --git a/ace/config-linux-pthread.h b/ace/config-linux-pthread.h index 1b43cbbe68f..0cb01d1fbf0 100644 --- a/ace/config-linux-pthread.h +++ b/ace/config-linux-pthread.h @@ -86,8 +86,12 @@ // Yes, we do have threads. #define ACE_HAS_THREADS + +#define ACE_HAS_THREAD_SPECIFIC_STORAGE +#define ACE_MT_SAFE // And they're even POSIX pthreads (MIT implementation) #define ACE_HAS_PTHREADS +#define ACE_LACKS_RWLOCK_T #define ACE_HAS_SIGWAIT #define ACE_LACKS_CONDATTR_PSHARED diff --git a/ace/config-m88k.h b/ace/config-m88k.h index 212a0869c53..d5b2ac928dc 100644 --- a/ace/config-m88k.h +++ b/ace/config-m88k.h @@ -177,12 +177,8 @@ struct ip_mreq // Compile using multi-thread libraries. #define ACE_MT_SAFE -#if !defined (m88k) -// Platform supports Solaris threads. -#define ACE_HAS_STHREADS -#else #define ACE_HAS_PTHREADS -#endif /* m88k */ +#define ACE_LACKS_RWLOCK_T // Platform supports threads. #define ACE_HAS_THREADS diff --git a/ace/config-mvs.h b/ace/config-mvs.h index 7ead2fc5488..c6f13364a32 100644 --- a/ace/config-mvs.h +++ b/ace/config-mvs.h @@ -61,6 +61,8 @@ // Platform supports POSIX threads #define ACE_HAS_PTHREADS +#define ACE_LACKS_RWLOCK_T + // Platform has pthread_condattr_setkind_np() #define ACE_HAS_PTHREAD_CONDATTR_SETKIND_NP diff --git a/ace/config-osf1-4.0-g++.h b/ace/config-osf1-4.0-g++.h index f60a6e2577b..4564aa8234b 100644 --- a/ace/config-osf1-4.0-g++.h +++ b/ace/config-osf1-4.0-g++.h @@ -109,7 +109,11 @@ // DJT modified 6/5/96 // ACE supports POSIX Pthreads. //#define ACE_HAS_DCETHREADS + #define ACE_HAS_PTHREADS + +#define ACE_LACKS_RWLOCK_T + // DJT 6/6/96 added // IEEE Std 1003.1c-1995, POSIX System Application Program Interface #define ACE_HAS_PTHREADS_1003_DOT_1C diff --git a/ace/config-osf1-4.0.h b/ace/config-osf1-4.0.h index 5a8f4a565a0..711e3f5c547 100644 --- a/ace/config-osf1-4.0.h +++ b/ace/config-osf1-4.0.h @@ -88,6 +88,8 @@ // ACE supports POSIX Pthreads. //#define ACE_HAS_DCETHREADS #define ACE_HAS_PTHREADS + +#define ACE_LACKS_RWLOCK_T // DJT 6/6/96 added // IEEE Std 1003.1c-1995, POSIX System Application Program Interface #define ACE_HAS_PTHREADS_1003_DOT_1C diff --git a/ace/config-vxworks-ghs-1.8.h b/ace/config-vxworks-ghs-1.8.h index 02b3c8f0b72..bc20ffd918f 100644 --- a/ace/config-vxworks-ghs-1.8.h +++ b/ace/config-vxworks-ghs-1.8.h @@ -7,6 +7,8 @@ #if !defined (ACE_CONFIG_H) #define ACE_CONFIG_H +#define ACE_LACKS_COND_T +#define ACE_LACKS_RWLOCK_T #define ACE_HAS_BROKEN_SENDMSG #define ACE_HAS_BROKEN_WRITEV #define ACE_HAS_CHARPTR_SOCKOPT diff --git a/ace/config-vxworks5.2-g++.h b/ace/config-vxworks5.2-g++.h index 842c11d723d..82a6efd8440 100644 --- a/ace/config-vxworks5.2-g++.h +++ b/ace/config-vxworks5.2-g++.h @@ -7,6 +7,8 @@ #if !defined (ACE_CONFIG_H) #define ACE_CONFIG_H +#define ACE_LACKS_COND_T +#define ACE_LACKS_RWLOCK_T #define ACE_HAS_BROKEN_SENDMSG #define ACE_HAS_BROKEN_WRITEV #define ACE_HAS_CHARPTR_SOCKOPT diff --git a/ace/config-win32-msvc2.0.h b/ace/config-win32-msvc2.0.h index 357201c7caa..e68ead2d81f 100644 --- a/ace/config-win32-msvc2.0.h +++ b/ace/config-win32-msvc2.0.h @@ -220,4 +220,6 @@ inline void *operator new (unsigned int, void *p) { return p; } // Compiler/Platform supports the "using" keyword. // #define ACE_HAS_USING_KEYWORD +#define ACE_LACKS_COND_T +#define ACE_LACKS_RWLOCK_T #endif /* ACE_CONFIG_H */ diff --git a/ace/config-win32-msvc4.0.h b/ace/config-win32-msvc4.0.h index 62d41a93a30..97856aeacc3 100644 --- a/ace/config-win32-msvc4.0.h +++ b/ace/config-win32-msvc4.0.h @@ -226,4 +226,6 @@ // Compiler/Platform supports the "using" keyword. #define ACE_HAS_USING_KEYWORD +#define ACE_LACKS_COND_T +#define ACE_LACKS_RWLOCK_T #endif /* ACE_CONFIG_H */ |