Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Object_Manager.cpp
blob5570194717501e786ff006f3c37c15ccb2e9f951
1 #include "ace/Object_Manager.h"
2 #if !defined (ACE_LACKS_ACE_TOKEN)
3 # include "ace/Token_Manager.h"
4 #endif /* ! ACE_LACKS_ACE_TOKEN */
5 #include "ace/Thread_Manager.h"
6 #if !defined (ACE_LACKS_ACE_SVCCONF)
7 # include "ace/Service_Manager.h"
8 # include "ace/Service_Config.h"
9 #endif /* ! ACE_LACKS_ACE_SVCCONF */
10 #include "ace/Signal.h"
11 #include "ace/Log_Category.h"
12 #include "ace/Malloc.h"
13 #include "ace/Sig_Adapter.h"
14 #include "ace/Framework_Component.h"
15 #include "ace/DLL_Manager.h"
16 #include "ace/Atomic_Op.h"
17 #include "ace/OS_NS_sys_time.h"
19 #if defined (ACE_HAS_TRACE)
20 #include "ace/Trace.h"
21 #endif /* ACE_HAS_TRACE */
23 #if !defined (__ACE_INLINE__)
24 # include "ace/Object_Manager.inl"
25 #endif /* __ACE_INLINE__ */
27 #include "ace/Guard_T.h"
28 #include "ace/Null_Mutex.h"
29 #include "ace/Mutex.h"
30 #include "ace/RW_Thread_Mutex.h"
31 #if defined (ACE_DISABLE_WIN32_ERROR_WINDOWS)
32 # include "ace/OS_NS_stdlib.h"
33 # include /**/ <crtdbg.h>
34 #endif // ACE_DISABLE_WIN32_ERROR_WINDOWS
36 #if ! defined (ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS)
37 # define ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS
38 #endif /* ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS */
40 #if ! defined (ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS)
41 # define ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS
42 #endif /* ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS */
44 #if ! defined (ACE_APPLICATION_PREALLOCATED_OBJECT_DELETIONS)
45 # define ACE_APPLICATION_PREALLOCATED_OBJECT_DELETIONS
46 #endif /* ACE_APPLICATION_PREALLOCATED_OBJECT_DELETIONS */
48 #if ! defined (ACE_APPLICATION_PREALLOCATED_ARRAY_DELETIONS)
49 # define ACE_APPLICATION_PREALLOCATED_ARRAY_DELETIONS
50 #endif /* ACE_APPLICATION_PREALLOCATED_ARRAY_DELETIONS */
52 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
54 // Note the following fix was derived from that proposed by Jochen Kalmbach
55 // http://blog.kalmbachnet.de/?postid=75
56 #if defined (ACE_DISABLE_WIN32_ERROR_WINDOWS)
57 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI ACEdisableSetUnhandledExceptionFilter (
58 LPTOP_LEVEL_EXCEPTION_FILTER /*lpTopLevelExceptionFilter*/)
60 return 0;
62 #endif // ACE_DISABLE_WIN32_ERROR_WINDOWS
64 // Singleton pointer.
65 ACE_Object_Manager *ACE_Object_Manager::instance_ = 0;
67 void *ACE_Object_Manager::preallocated_object[
68 ACE_Object_Manager::ACE_PREALLOCATED_OBJECTS] = { 0 };
70 void *ACE_Object_Manager::preallocated_array[
71 ACE_Object_Manager::ACE_PREALLOCATED_ARRAYS] = { 0 };
73 // Handy macros for use by ACE_Object_Manager constructor to
74 // preallocate or delete an object or array, either statically (in
75 // global data) or dynamically (on the heap).
76 #if defined (ACE_HAS_STATIC_PREALLOCATION)
77 # define ACE_PREALLOCATE_OBJECT(TYPE, ID)\
79 static ACE_Cleanup_Adapter<TYPE> obj;\
80 preallocated_object[ID] = &obj;\
82 # define ACE_PREALLOCATE_ARRAY(TYPE, ID, COUNT)\
84 static ACE_Cleanup_Adapter<TYPE> obj[COUNT];\
85 preallocated_array[ID] = &obj;\
87 #else
88 # define ACE_PREALLOCATE_OBJECT(TYPE, ID)\
90 ACE_Cleanup_Adapter<TYPE> *obj_p;\
91 ACE_NEW_RETURN (obj_p, ACE_Cleanup_Adapter<TYPE>, -1);\
92 preallocated_object[ID] = obj_p;\
94 # define ACE_PREALLOCATE_ARRAY(TYPE, ID, COUNT)\
96 ACE_Cleanup_Adapter<TYPE[COUNT]> *array_p;\
97 ACE_NEW_RETURN (array_p, ACE_Cleanup_Adapter<TYPE[COUNT]>, -1);\
98 preallocated_array[ID] = array_p;\
100 # define ACE_DELETE_PREALLOCATED_OBJECT(TYPE, ID)\
101 ACE_CLEANUP_DESTROYER_NAME (\
102 (ACE_Cleanup_Adapter<TYPE> *) preallocated_object[ID], 0);\
103 preallocated_object[ID] = 0;
104 # define ACE_DELETE_PREALLOCATED_ARRAY(TYPE, ID, COUNT)\
105 delete (ACE_Cleanup_Adapter<TYPE[COUNT]> *) preallocated_array[ID];\
106 preallocated_array[ID] = 0;
107 #endif /* ACE_HAS_STATIC_PREALLOCATION */
109 #if !defined (ACE_LACKS_ACE_SVCCONF)
112 * @class ACE_Object_Manager_Preallocations
114 * @brief Performs preallocations of certain statically allocated services
115 * needed by ACE.
117 class ACE_Object_Manager_Preallocations
119 public:
120 ACE_Object_Manager_Preallocations ();
121 ~ACE_Object_Manager_Preallocations ();
123 ACE_ALLOC_HOOK_DECLARE;
125 private:
126 ACE_Static_Svc_Descriptor ace_svc_desc_ACE_Service_Manager;
129 ACE_Object_Manager_Preallocations::ACE_Object_Manager_Preallocations ()
131 ACE_STATIC_SVC_DEFINE (ACE_Service_Manager_initializer,
132 ACE_TEXT ("ACE_Service_Manager"),
133 ACE_SVC_OBJ_T,
134 &ACE_SVC_NAME (ACE_Service_Manager),
135 ACE_Service_Type::DELETE_THIS |
136 ACE_Service_Type::DELETE_OBJ,
139 // Initialize the static service objects using the descriptors created
140 // above.
141 ace_svc_desc_ACE_Service_Manager =
142 ace_svc_desc_ACE_Service_Manager_initializer;
144 // Add to the list of static configured services.
145 ACE_Service_Config::static_svcs ()->
146 insert (&ace_svc_desc_ACE_Service_Manager);
149 ACE_Object_Manager_Preallocations::~ACE_Object_Manager_Preallocations ()
153 ACE_ALLOC_HOOK_DEFINE(ACE_Object_Manager_Preallocations)
155 #endif /* ! ACE_LACKS_ACE_SVCCONF */
158 ACE_Object_Manager::starting_up ()
160 return ACE_Object_Manager::instance_ ? instance_->starting_up_i () : 1;
164 ACE_Object_Manager::shutting_down ()
166 return ACE_Object_Manager::instance_ ? instance_->shutting_down_i () : 1;
169 #if defined (ACE_DISABLE_WIN32_ERROR_WINDOWS)
170 // Instead of popping up a window for exceptions, just print something out
171 LONG WINAPI ACE_UnhandledExceptionFilter (PEXCEPTION_POINTERS pExceptionInfo)
173 DWORD const dwExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode;
175 if (dwExceptionCode == EXCEPTION_ACCESS_VIOLATION)
176 ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("\n(%P|%t) ERROR: ACCESS VIOLATION\n")));
177 else
178 ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("\n(%P|%t) ERROR: UNHANDLED EXCEPTION\n")));
180 return EXCEPTION_EXECUTE_HANDLER;
182 #endif /* ACE_DISABLE_WIN32_ERROR_WINDOWS */
184 // Initialize an ACE_Object_Manager. There can be instances of this object
185 // other than The Instance. This can happen if a user creates one for some
186 // reason. All objects set up their per-object information and managed
187 // objects, but only The Instance sets up the static preallocated objects and
188 // the (static) ACE_Service_Config signal handler.
190 ACE_Object_Manager::init ()
192 if (starting_up_i ())
194 // First, indicate that the ACE_Object_Manager instance is being
195 // initialized.
196 object_manager_state_ = OBJ_MAN_INITIALIZING;
198 // Only The Instance sets up with ACE_OS_Object_Manager and initializes
199 // the preallocated objects.
200 if (this == instance_)
202 // Make sure that the ACE_OS_Object_Manager has been created,
203 // and register with it for chained fini ().
204 ACE_OS_Object_Manager::instance ()->next_ = this;
206 # if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
207 ACE_Atomic_Op<ACE_Thread_Mutex, long>::init_functions ();
208 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::init_functions ();
209 # endif /* ACE_HAS_BUILTIN_ATOMIC_OP */
211 # if !defined (ACE_LACKS_ACE_SVCCONF)
212 // Construct the ACE_Service_Config's signal handler.
213 ACE_NEW_RETURN (ace_service_config_sig_handler_,
214 ACE_Sig_Adapter (&ACE_Service_Config::handle_signal), -1);
215 ACE_Service_Config::signal_handler (ace_service_config_sig_handler_);
216 # endif /* ! ACE_LACKS_ACE_SVCCONF */
218 // Allocate the preallocated (hard-coded) object instances.
219 ACE_PREALLOCATE_OBJECT (ACE_SYNCH_RW_MUTEX, ACE_FILECACHE_LOCK)
220 # if defined (ACE_HAS_THREADS)
221 ACE_PREALLOCATE_OBJECT (ACE_Recursive_Thread_Mutex,
222 ACE_STATIC_OBJECT_LOCK)
223 # endif /* ACE_HAS_THREADS */
224 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
225 ACE_PREALLOCATE_OBJECT (ACE_Thread_Mutex,
226 ACE_MT_CORBA_HANDLER_LOCK)
227 ACE_PREALLOCATE_OBJECT (ACE_Thread_Mutex, ACE_DUMP_LOCK)
228 ACE_PREALLOCATE_OBJECT (ACE_Recursive_Thread_Mutex,
229 ACE_SIG_HANDLER_LOCK)
230 ACE_PREALLOCATE_OBJECT (ACE_Null_Mutex, ACE_SINGLETON_NULL_LOCK)
231 ACE_PREALLOCATE_OBJECT (ACE_Recursive_Thread_Mutex,
232 ACE_SINGLETON_RECURSIVE_THREAD_LOCK)
233 ACE_PREALLOCATE_OBJECT (ACE_Thread_Mutex, ACE_THREAD_EXIT_LOCK)
234 #if !defined (ACE_LACKS_ACE_TOKEN) && defined (ACE_HAS_TOKENS_LIBRARY)
235 ACE_PREALLOCATE_OBJECT (ACE_TOKEN_CONST::MUTEX,
236 ACE_TOKEN_MANAGER_CREATION_LOCK)
237 ACE_PREALLOCATE_OBJECT (ACE_TOKEN_CONST::MUTEX,
238 ACE_TOKEN_INVARIANTS_CREATION_LOCK)
239 #endif /* ! ACE_LACKS_ACE_TOKEN && ACE_HAS_TOKENS_LIBRARY */
240 ACE_PREALLOCATE_OBJECT (ACE_Thread_Mutex,
241 ACE_PROACTOR_EVENT_LOOP_LOCK)
242 # endif /* ACE_MT_SAFE */
245 if (this == instance_)
247 // Hooks for preallocated objects and arrays provided by application.
248 ACE_APPLICATION_PREALLOCATED_OBJECT_DEFINITIONS
249 ACE_APPLICATION_PREALLOCATED_ARRAY_DEFINITIONS
251 # if defined (ACE_HAS_TSS_EMULATION)
252 // Initialize the main thread's TS storage.
253 if (!ts_storage_initialized_)
255 ACE_TSS_Emulation::tss_open (ts_storage_);
256 ts_storage_initialized_ = true;
258 # endif /* ACE_HAS_TSS_EMULATION */
260 #if defined (ACE_DISABLE_WIN32_ERROR_WINDOWS)
261 #if defined (_DEBUG) && (defined (_MSC_VER) || defined (__INTEL_COMPILER) || defined (__MINGW32__))
262 _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
263 _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );
264 _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
265 _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
266 #endif /* _DEBUG && _MSC_VER || __INTEL_COMPILER || __MINGW32__ */
268 // The system does not display the critical-error-handler message box
269 SetErrorMode(SEM_FAILCRITICALERRORS);
271 // And this will catch all unhandled exceptions.
272 SetUnhandledExceptionFilter (&ACE_UnhandledExceptionFilter);
274 #if !defined (ACE_LACKS_SET_ABORT_BEHAVIOR)
275 // And this will stop the abort system call from being treated as a crash
276 _set_abort_behavior( 0, _CALL_REPORTFAULT);
277 #endif /* !ACE_LACKS_SET_ABORT_BEHAVIOR */
279 // Note the following fix was derived from that proposed by Jochen Kalmbach
280 // http://blog.kalmbachnet.de/?postid=75
281 // See also:
282 // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101337
284 // Starting with VC8 (VS2005), Microsoft changed the behaviour of the CRT in some
285 // security related and special situations. The are many situations in which our
286 // ACE_UnhandledExceptionFilter will never be called. This is a major change to
287 // the previous versions of the CRT and is not very well documented.
288 // The CRT simply forces the call to the default-debugger without informing the
289 // registered unhandled exception filter. Jochen's solution is to stop the CRT
290 // from calling SetUnhandledExceptionFilter() after we have done so above.
291 // NOTE this only works for intel based windows builds.
293 # if (_MSC_VER) \
294 || (__MINGW32_MAJOR_VERSION > 3) || \
295 ((__MINGW32_MAJOR_VERSION == 3) && \
296 (__MINGW32_MINOR_VERSION >= 15)) // VC++ || MingW32 >= 3.15
297 # ifdef _M_IX86
298 HMODULE hKernel32 = ACE_TEXT_LoadLibrary (ACE_TEXT ("kernel32.dll"));
299 if (hKernel32)
301 void *pOrgEntry =
302 reinterpret_cast<void*> (GetProcAddress (hKernel32, "SetUnhandledExceptionFilter"));
303 if (pOrgEntry)
305 unsigned char newJump[ 100 ];
306 DWORD dwOrgEntryAddr = reinterpret_cast<DWORD> (pOrgEntry);
307 dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far
308 void *pNewFunc = reinterpret_cast<void*> (&ACEdisableSetUnhandledExceptionFilter);
309 DWORD dwNewEntryAddr = reinterpret_cast<DWORD> (pNewFunc);
310 DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
312 newJump[ 0 ] = 0xE9; // JMP absolute
313 ACE_OS::memcpy (&newJump[ 1 ], &dwRelativeAddr, sizeof (pNewFunc));
314 SIZE_T bytesWritten;
315 WriteProcessMemory (
316 GetCurrentProcess (),
317 pOrgEntry,
318 newJump,
319 sizeof (pNewFunc) + 1,
320 &bytesWritten);
323 # endif // _M_IX86
324 # endif // (_MSC_VER)
325 #endif /* ACE_DISABLE_WIN32_ERROR_WINDOWS */
327 # if !defined (ACE_LACKS_ACE_SVCCONF)
328 ACE_NEW_RETURN (preallocations_,
329 ACE_Object_Manager_Preallocations,
330 -1);
331 # endif /* ! ACE_LACKS_ACE_SVCCONF */
333 // Open the main thread's ACE_Log_Msg.
334 if (0 == ACE_LOG_MSG)
335 return -1;
338 // Finally, indicate that the ACE_Object_Manager instance has
339 // been initialized.
340 object_manager_state_ = OBJ_MAN_INITIALIZED;
342 #if defined (ACE_HAS_TRACE)
343 // Allow tracing again (useful if user does init/fini/init)
344 ACE_Trace::start_tracing ();
345 #endif /* ACE_HAS_TRACE */
347 return 0;
348 } else {
349 // Had already initialized.
350 return 1;
354 #if defined (ACE_HAS_TSS_EMULATION)
356 ACE_Object_Manager::init_tss ()
358 return ACE_Object_Manager::instance ()->init_tss_i ();
362 ACE_Object_Manager::init_tss_i ()
364 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
365 *instance_->internal_lock_, -1));
367 if (!ts_storage_initialized_)
369 ACE_TSS_Emulation::tss_open (ts_storage_);
370 ts_storage_initialized_ = true;
373 return 0;
376 #endif
378 ACE_Object_Manager::ACE_Object_Manager ()
379 // With ACE_HAS_TSS_EMULATION, ts_storage_ is initialized by the call to
380 // ACE_OS::tss_open () in the function body.
381 : exit_info_ ()
382 #if !defined (ACE_LACKS_ACE_SVCCONF)
383 , preallocations_ (0)
384 , ace_service_config_sig_handler_ (0)
385 #endif /* ! ACE_LACKS_ACE_SVCCONF */
386 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
387 , singleton_null_lock_ (0)
388 , singleton_recursive_lock_ (0)
389 #endif /* ACE_MT_SAFE */
390 #if defined (ACE_HAS_TSS_EMULATION)
391 , ts_storage_initialized_ (false)
392 #endif
394 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
395 ACE_NEW (internal_lock_, ACE_Recursive_Thread_Mutex);
396 # endif /* ACE_MT_SAFE */
398 // If instance_ was not 0, then another ACE_Object_Manager has
399 // already been instantiated (it is likely to be one initialized by way
400 // of library/DLL loading). Let this one go through construction in
401 // case there really is a good reason for it (like, ACE is a static/archive
402 // library, and this one is the non-static instance (with
403 // ACE_HAS_NONSTATIC_OBJECT_MANAGER, or the user has a good reason for
404 // creating a separate one) but the original one will be the one retrieved
405 // from calls to ACE_Object_Manager::instance().
407 // Be sure that no further instances are created via instance ().
408 if (instance_ == 0)
409 instance_ = this;
411 init ();
414 ACE_Object_Manager::~ACE_Object_Manager ()
416 dynamically_allocated_ = false; // Don't delete this again in fini()
417 fini ();
420 ACE_ALLOC_HOOK_DEFINE(ACE_Object_Manager)
422 ACE_Object_Manager *
423 ACE_Object_Manager::instance ()
425 // This function should be called during construction of static
426 // instances, or before any other threads have been created in
427 // the process. So, it's not thread safe.
429 if (instance_ == 0)
431 ACE_Object_Manager *instance_pointer = 0;
433 ACE_NEW_RETURN (instance_pointer,
434 ACE_Object_Manager,
436 ACE_ASSERT (instance_pointer == instance_);
438 instance_pointer->dynamically_allocated_ = true;
440 return instance_pointer;
442 else
443 return instance_;
447 ACE_Object_Manager::at_exit_i (void *object,
448 ACE_CLEANUP_FUNC cleanup_hook,
449 void *param,
450 const char* name)
452 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
453 *instance_->internal_lock_, -1));
455 if (shutting_down_i ())
457 errno = EAGAIN;
458 return -1;
461 if (exit_info_.find (object))
463 // The object has already been registered.
464 errno = EEXIST;
465 return -1;
468 return exit_info_.at_exit_i (object, cleanup_hook, param, name);
472 ACE_Object_Manager::remove_at_exit_i (void *object)
474 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
475 *instance_->internal_lock_, -1));
477 if (shutting_down_i ())
479 errno = EAGAIN;
480 return -1;
483 return exit_info_.remove (object);
486 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
489 ACE_Object_Manager::get_singleton_lock (ACE_Null_Mutex *&lock)
491 if (starting_up () || shutting_down ())
493 // The preallocated lock has not been constructed yet.
494 // Therefore, the program is single-threaded at this point. Or,
495 // the ACE_Object_Manager instance has been destroyed, so the
496 // preallocated lock is not available. Allocate a lock to use,
497 // for interface compatibility, though there should be no
498 // contention on it.
499 if (ACE_Object_Manager::instance ()->singleton_null_lock_ == 0)
501 ACE_NEW_RETURN (ACE_Object_Manager::instance ()->
502 singleton_null_lock_,
503 ACE_Cleanup_Adapter<ACE_Null_Mutex>,
504 -1);
506 // Can't register with the ACE_Object_Manager here! The
507 // lock's declaration is visible to the ACE_Object_Manager
508 // destructor, so it will clean it up as a special case.
511 if (ACE_Object_Manager::instance ()->singleton_null_lock_ != 0)
512 lock = &ACE_Object_Manager::instance ()->singleton_null_lock_->
513 object ();
515 else
516 // Use the Object_Manager's preallocated lock.
517 lock = ACE_Managed_Object<ACE_Null_Mutex>::get_preallocated_object
518 (ACE_Object_Manager::ACE_SINGLETON_NULL_LOCK);
520 return 0;
524 ACE_Object_Manager::get_singleton_lock (ACE_Thread_Mutex *&lock)
526 if (lock == 0)
528 if (starting_up () || shutting_down ())
530 // The Object_Manager and its internal lock have not been
531 // constructed yet. Therefore, the program is single-
532 // threaded at this point. Or, the ACE_Object_Manager
533 // instance has been destroyed, so the internal lock is not
534 // available. Either way, we can not use double-checked
535 // locking. So, we'll leak the lock.
536 ACE_NEW_RETURN (lock,
537 ACE_Thread_Mutex,
538 -1);
540 else
542 // Allocate a new lock, but use double-checked locking to
543 // ensure that only one thread allocates it.
544 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
545 ace_mon,
546 *ACE_Object_Manager::instance ()->
547 internal_lock_,
548 -1));
550 if (lock == 0)
552 ACE_Cleanup_Adapter<ACE_Thread_Mutex> *lock_adapter = 0;
553 ACE_NEW_RETURN (lock_adapter,
554 ACE_Cleanup_Adapter<ACE_Thread_Mutex>,
555 -1);
556 lock = &lock_adapter->object ();
558 // Register the lock for destruction at program
559 // termination. This call will cause us to grab the
560 // ACE_Object_Manager::instance ()->internal_lock_
561 // again; that's why it is a recursive lock.
562 ACE_Object_Manager::at_exit (lock_adapter,
564 typeid (*lock_adapter).name ());
569 return 0;
573 ACE_Object_Manager::get_singleton_lock (ACE_Mutex *&lock)
575 if (lock == 0)
577 if (starting_up () || shutting_down ())
579 // The Object_Manager and its internal lock have not been
580 // constructed yet. Therefore, the program is single-
581 // threaded at this point. Or, the ACE_Object_Manager
582 // instance has been destroyed, so the internal lock is not
583 // available. Either way, we can not use double-checked
584 // locking. So, we'll leak the lock.
586 ACE_NEW_RETURN (lock,
587 ACE_Mutex,
588 -1);
590 else
592 // Allocate a new lock, but use double-checked locking to
593 // ensure that only one thread allocates it.
594 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
595 ace_mon,
596 *ACE_Object_Manager::instance ()->
597 internal_lock_,
598 -1));
600 if (lock == 0)
602 ACE_Cleanup_Adapter<ACE_Mutex> *lock_adapter = 0;
603 ACE_NEW_RETURN (lock_adapter,
604 ACE_Cleanup_Adapter<ACE_Mutex>,
605 -1);
606 lock = &lock_adapter->object ();
608 // Register the lock for destruction at program
609 // termination. This call will cause us to grab the
610 // ACE_Object_Manager::instance ()->internal_lock_
611 // again; that's why it is a recursive lock.
612 ACE_Object_Manager::at_exit (lock_adapter);
617 return 0;
621 ACE_Object_Manager::get_singleton_lock (ACE_Recursive_Thread_Mutex *&lock)
623 if (starting_up () || shutting_down ())
625 // The preallocated lock has not been constructed yet.
626 // Therefore, the program is single-threaded at this point. Or,
627 // the ACE_Object_Manager instance has been destroyed, so the
628 // preallocated lock is not available. Allocate a lock to use,
629 // for interface compatibility, though there should be no
630 // contention on it.
631 if (ACE_Object_Manager::instance ()->singleton_recursive_lock_ == 0)
632 ACE_NEW_RETURN (ACE_Object_Manager::instance ()->
633 singleton_recursive_lock_,
634 ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex>,
635 -1);
637 // Can't register with the ACE_Object_Manager here! The lock's
638 // declaration is visible to the ACE_Object_Manager destructor,
639 // so it will clean it up as a special case.
641 if (ACE_Object_Manager::instance ()->singleton_recursive_lock_ != 0)
642 lock = &ACE_Object_Manager::instance ()->singleton_recursive_lock_->
643 object ();
645 else
647 // Use the Object_Manager's preallocated lock.
648 lock = ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::
649 get_preallocated_object (ACE_Object_Manager::
650 ACE_SINGLETON_RECURSIVE_THREAD_LOCK);
653 return 0;
657 ACE_Object_Manager::get_singleton_lock (ACE_RW_Thread_Mutex *&lock)
659 if (lock == 0)
661 if (starting_up () || shutting_down ())
663 // The Object_Manager and its internal lock have not been
664 // constructed yet. Therefore, the program is single-
665 // threaded at this point. Or, the ACE_Object_Manager
666 // instance has been destroyed, so the internal lock is not
667 // available. Either way, we can not use double-checked
668 // locking. So, we'll leak the lock.
670 ACE_NEW_RETURN (lock,
671 ACE_RW_Thread_Mutex,
672 -1);
674 else
676 // Allocate a new lock, but use double-checked locking to
677 // ensure that only one thread allocates it.
678 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
679 ace_mon,
680 *ACE_Object_Manager::instance ()->
681 internal_lock_,
682 -1));
684 if (lock == 0)
686 ACE_Cleanup_Adapter<ACE_RW_Thread_Mutex> *lock_adapter = 0;
687 ACE_NEW_RETURN (lock_adapter,
688 ACE_Cleanup_Adapter<ACE_RW_Thread_Mutex>,
689 -1);
690 lock = &lock_adapter->object ();
693 // Register the lock for destruction at program
694 // termination. This call will cause us to grab the
695 // ACE_Object_Manager::instance ()->internal_lock_
696 // again; that's why it is a recursive lock.
697 ACE_Object_Manager::at_exit (lock_adapter);
702 return 0;
704 #endif /* ACE_MT_SAFE */
706 // Clean up an ACE_Object_Manager. There can be instances of this object
707 // other than The Instance. This can happen if (on Win32) the ACE DLL
708 // causes one to be created, or if a user creates one for some reason.
709 // Only The Instance cleans up the static preallocated objects. All objects
710 // clean up their per-object information and managed objects.
712 ACE_Object_Manager::fini ()
714 if (shutting_down_i ())
715 // Too late. Or, maybe too early. Either fini () has already
716 // been called, or init () was never called.
717 return object_manager_state_ == OBJ_MAN_SHUT_DOWN ? 1 : -1;
719 // No mutex here. Only the main thread should destroy the singleton
720 // ACE_Object_Manager instance.
722 // Indicate that this ACE_Object_Manager instance is being
723 // shut down.
724 object_manager_state_ = OBJ_MAN_SHUTTING_DOWN;
726 // Call all registered cleanup hooks, in reverse order of
727 // registration.
728 exit_info_.call_hooks ();
730 if (this == instance_)
732 #if !defined (ACE_LACKS_ACE_SVCCONF)
733 delete preallocations_;
734 preallocations_ = 0;
735 #endif /* ! ACE_LACKS_ACE_SVCCONF */
737 #if defined (ACE_HAS_TRACE)
738 ACE_Trace::stop_tracing ();
739 #endif /* ACE_HAS_TRACE */
741 #if !defined (ACE_LACKS_ACE_SVCCONF)
742 // Close and possibly delete all service instances in the Service
743 // Repository.
744 ACE_Service_Config::fini_svcs ();
746 // Unlink all services in the Service Repository and close/delete
747 // all ACE library services and singletons.
748 ACE_Service_Config::close ();
749 #endif /* ! ACE_LACKS_ACE_SVCCONF */
751 // This must come after closing ACE_Service_Config, since it will
752 // close down it's dlls--it manages ACE_DLL_Manager.
753 ACE_Framework_Repository::close_singleton ();
754 ACE_DLL_Manager::close_singleton ();
756 # if ! defined (ACE_THREAD_MANAGER_LACKS_STATICS)
757 ACE_Thread_Manager::close_singleton ();
758 # endif /* ! ACE_THREAD_MANAGER_LACKS_STATICS */
760 // Close the main thread's TSS, including its Log_Msg instance.
761 ACE_OS::cleanup_tss (1 /* main thread */);
764 // Note: Do not access Log Msg after this since it is gone
767 // Close the ACE_Allocator.
768 ACE_Allocator::close_singleton ();
770 #if ! defined (ACE_HAS_STATIC_PREALLOCATION)
771 // Hooks for deletion of preallocated objects and arrays provided by
772 // application.
773 ACE_APPLICATION_PREALLOCATED_ARRAY_DELETIONS
774 ACE_APPLICATION_PREALLOCATED_OBJECT_DELETIONS
776 // Cleanup the dynamically preallocated arrays.
777 // (none)
779 // Cleanup the dynamically preallocated objects.
780 ACE_DELETE_PREALLOCATED_OBJECT (ACE_SYNCH_RW_MUTEX, ACE_FILECACHE_LOCK)
781 #if defined (ACE_HAS_THREADS)
782 ACE_DELETE_PREALLOCATED_OBJECT (ACE_Recursive_Thread_Mutex,
783 ACE_STATIC_OBJECT_LOCK)
784 #endif /* ACE_HAS_THREADS */
785 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
786 ACE_DELETE_PREALLOCATED_OBJECT (ACE_Thread_Mutex,
787 ACE_MT_CORBA_HANDLER_LOCK)
788 ACE_DELETE_PREALLOCATED_OBJECT (ACE_Thread_Mutex, ACE_DUMP_LOCK)
789 ACE_DELETE_PREALLOCATED_OBJECT (ACE_Recursive_Thread_Mutex,
790 ACE_SIG_HANDLER_LOCK)
791 ACE_DELETE_PREALLOCATED_OBJECT (ACE_Null_Mutex,
792 ACE_SINGLETON_NULL_LOCK)
793 ACE_DELETE_PREALLOCATED_OBJECT (ACE_Recursive_Thread_Mutex,
794 ACE_SINGLETON_RECURSIVE_THREAD_LOCK)
795 ACE_DELETE_PREALLOCATED_OBJECT (ACE_Thread_Mutex, ACE_THREAD_EXIT_LOCK)
796 #if !defined (ACE_LACKS_ACE_TOKEN) && defined (ACE_HAS_TOKENS_LIBRARY)
797 ACE_DELETE_PREALLOCATED_OBJECT (ACE_TOKEN_CONST::MUTEX,
798 ACE_TOKEN_MANAGER_CREATION_LOCK)
799 ACE_DELETE_PREALLOCATED_OBJECT (ACE_TOKEN_CONST::MUTEX,
800 ACE_TOKEN_INVARIANTS_CREATION_LOCK)
801 #endif /* ! ACE_LACKS_ACE_TOKEN && ACE_HAS_TOKENS_LIBRARY */
802 ACE_DELETE_PREALLOCATED_OBJECT (ACE_Thread_Mutex,
803 ACE_PROACTOR_EVENT_LOOP_LOCK)
804 # endif /* ACE_MT_SAFE */
805 #endif /* ! ACE_HAS_STATIC_PREALLOCATION */
807 #if defined (ACE_HAS_THREADS)
808 ACE_Static_Object_Lock::cleanup_lock ();
809 #endif /* ACE_HAS_THREADS */
812 #if !defined (ACE_LACKS_ACE_SVCCONF)
813 delete ace_service_config_sig_handler_;
814 ace_service_config_sig_handler_ = 0;
815 #endif /* ! ACE_LACKS_ACE_SVCCONF */
817 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
818 delete internal_lock_;
819 internal_lock_ = 0;
821 delete singleton_null_lock_;
822 singleton_null_lock_ = 0;
824 delete singleton_recursive_lock_;
825 singleton_recursive_lock_ = 0;
826 #endif /* ACE_MT_SAFE */
828 // Indicate that this ACE_Object_Manager instance has been shut down.
829 object_manager_state_ = OBJ_MAN_SHUT_DOWN;
831 // Then, ensure that the ACE_OS_Object_Manager gets shut down.
832 if (this == instance_ && ACE_OS_Object_Manager::instance_)
833 ACE_OS_Object_Manager::instance_->fini ();
835 if (dynamically_allocated_)
837 delete this;
840 if (this == instance_)
841 instance_ = 0;
843 return 0;
847 #if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
849 * @class ACE_Object_Manager_Manager
851 * @brief Ensure that the ACE_Object_Manager gets initialized at program
852 * startup, and destroyed at program termination.
854 * Without ACE_HAS_NONSTATIC_OBJECT_MANAGER, a static instance of this
855 * class is created. Therefore, it gets created before main ()
856 * is called. And it gets destroyed after main () returns.
858 class ACE_Export ACE_Object_Manager_Manager
860 public:
861 ACE_Object_Manager_Manager ();
862 ~ACE_Object_Manager_Manager ();
864 private:
865 /// Save the main thread ID, so that destruction can be suppressed.
866 ACE_thread_t saved_main_thread_id_;
869 ACE_Object_Manager_Manager::ACE_Object_Manager_Manager ()
870 : saved_main_thread_id_ (ACE_OS::thr_self ())
872 // Ensure that the Object_Manager gets initialized before any
873 // application threads have been spawned. Because this will be called
874 // during construction of static objects, that should always be the
875 // case.
876 (void) ACE_Object_Manager::instance ();
879 ACE_Object_Manager_Manager::~ACE_Object_Manager_Manager ()
881 if (ACE_OS::thr_equal (ACE_OS::thr_self (),
882 saved_main_thread_id_))
884 delete ACE_Object_Manager::instance_;
885 ACE_Object_Manager::instance_ = 0;
887 // else if this destructor is not called by the main thread, then do
888 // not delete the ACE_Object_Manager. That causes problems, on
889 // WIN32 at least.
892 static ACE_Object_Manager_Manager ACE_Object_Manager_Manager_instance;
893 #endif /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER */
895 #if defined (ACE_HAS_THREADS)
897 // This is global so that it doesn't have to be declared in the header
898 // file. That would cause nasty circular include problems.
899 using ACE_Static_Object_Lock_Type = ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex>;
900 static ACE_Static_Object_Lock_Type *ACE_Static_Object_Lock_lock = 0;
902 // ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK isn't (currently) used by ACE.
903 // But, applications may find it useful for avoiding recursive calls
904 // if they have overridden operator new. Thanks to Jody Hagins
905 // <jody@atdesk.com> for contributing it.
907 ACE_Recursive_Thread_Mutex *
908 ACE_Static_Object_Lock::instance ()
910 if (ACE_Object_Manager::starting_up () ||
911 ACE_Object_Manager::shutting_down ())
913 // The preallocated ACE_STATIC_OBJECT_LOCK has not been
914 // constructed yet. Therefore, the program is single-threaded
915 // at this point. Or, the ACE_Object_Manager instance has been
916 // destroyed, so the preallocated lock is not available.
917 // Allocate a lock to use, for interface compatibility, though
918 // there should be no contention on it.
919 if (ACE_Static_Object_Lock_lock == 0)
921 # if defined (ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK)
922 // Allocate a buffer with malloc, and then use placement
923 // new for the object, on the malloc'd buffer.
924 void *buffer =
925 ACE_OS::malloc (sizeof (*ACE_Static_Object_Lock_lock));
926 if (buffer == 0)
928 return 0;
930 // do not use ACE_NEW macros for placement new
931 ACE_Static_Object_Lock_lock = new (buffer)
932 ACE_Static_Object_Lock_Type ();
934 # else /* ! ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK */
935 ACE_NEW_RETURN (ACE_Static_Object_Lock_lock,
936 ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex>,
938 # endif /* ! ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK */
941 // Can't register with the ACE_Object_Manager here! The lock's
942 // declaration is visible to the ACE_Object_Manager destructor,
943 // so it will clean it up as a special case.
945 return &ACE_Static_Object_Lock_lock->object ();
947 else
948 // Return the preallocated ACE_STATIC_OBJECT_LOCK.
949 return
950 ACE_Managed_Object<ACE_Recursive_Thread_Mutex>::get_preallocated_object
951 (ACE_Object_Manager::ACE_STATIC_OBJECT_LOCK);
954 void
955 ACE_Static_Object_Lock::cleanup_lock ()
957 # if defined(ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK)
958 // It was malloc'd, so we need to explicitly call the dtor
959 // and then free the memory.
960 ACE_DES_FREE (ACE_Static_Object_Lock_lock,
961 ACE_OS::free,
962 ACE_Static_Object_Lock_Type);
963 # else /* ! ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK */
964 delete ACE_Static_Object_Lock_lock;
965 # endif /* ! ACE_SHOULD_MALLOC_STATIC_OBJECT_LOCK */
966 ACE_Static_Object_Lock_lock = 0;
968 #endif /* ACE_HAS_THREADS */
970 ACE_END_VERSIONED_NAMESPACE_DECL