]>
git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/globalizer.h
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 * globalizer - multiscope globalization services
25 #include <Security/threading.h>
32 // GlobalNexus is the common superclass of all globality scopes.
33 // A Nexus is an *access point* to the *single* object of a given
34 // type in the Nexus's particular scope.
38 class Error
: public std::exception
{
40 virtual ~Error() throw();
41 const char * const message
;
42 Error(const char *m
) : message(m
) { }
43 const char *what() const throw() { return message
; }
49 // A module-scope nexus is tied to the linker Nexus object itself.
50 // Its scope is all code accessing that particular Nexus object
51 // from within a process. Any number of ModuleNexus objects can
52 // exist, and each implements a different scope.
54 // IMPORTANT notes on this class can be found in globalizer.cpp.
55 // DO NOT change anything here before carefully reading them.
57 #if defined(_HAVE_ATOMIC_OPERATIONS)
59 class ModuleNexusCommon
: public GlobalNexus
{
61 AtomicWord
create(void *(*make
)());
64 // both of these will be statically initialized to zero
66 StaticAtomicCounter
<uint32
> sync
;
70 class ModuleNexus
: public ModuleNexusCommon
{
74 AtomicWord p
= pointer
; // latch pointer
75 if (!p
|| (p
& 0x1)) {
77 secdebug("nexus", "module %s 0x%x", Debug::typeName
<Type
>().c_str(), pointer
);
79 return *reinterpret_cast<Type
*>(p
);
84 if (pointer
&& !(pointer
& 0x1)) {
85 delete reinterpret_cast<Type
*>(pointer
);
91 static void *make() { return new Type
; }
95 class CleanModuleNexus
: public ModuleNexus
<Type
> {
99 secdebug("nexus", "ModuleNexus %p destroyed object 0x%x", this, pointer
);
100 delete reinterpret_cast<Type
*>(pointer
);
104 #else // !_HAVE_ATOMIC_OPERATIONS
106 template <class Type
>
107 class ModuleNexus
: public GlobalNexus
{
111 #if !defined(PTHREAD_STRICT)
112 // not strictly kosher POSIX, but pointers are usually atomic types
116 StLock
<Mutex
> _(mLock
);
117 if (mSingleton
== NULL
)
118 mSingleton
= new Type
;
122 void reset() { delete mSingleton
; mSingleton
= NULL
; }
125 Type
*mSingleton
; // pointer to singleton static initialized to NULL
126 Mutex mLock
; // construction lock
129 template <class Type
>
130 class CleanModuleNexus
: public ModuleNexus
<Type
> {
134 secdebug("nexus", "ModuleNexus %p destroyed object 0x%x", this, mSingleton
);
139 #endif // _HAVE_ATOMIC_OPERATIONS
143 // A thread-scope nexus is tied to a particular native thread AND
144 // a particular nexus object. Its scope is all code in any one thread
145 // that access that particular Nexus object. Any number of Nexus objects
146 // can exist, and each implements a different scope for each thread.
147 // NOTE: ThreadNexus is dynamically constructed. If you want static,
148 // zero-initialization ThreadNexi, put them inside a ModuleNexus.
150 #if _USE_THREADS == _USE_PTHREADS
152 template <class Type
>
153 class ThreadNexus
: public GlobalNexus
{
155 ThreadNexus() : mSlot(true) { }
158 // no thread contention here!
166 PerThreadPointer
<Type
> mSlot
;
169 #endif //_USE_PTHREADS
173 // A ProcessNexus is global within a single process, regardless of
174 // load module boundaries. You can have any number of ProcessNexus
175 // scopes, each identified by a C string (compared by value, not pointer).
177 class ProcessNexusBase
: public GlobalNexus
{
179 ProcessNexusBase(const char *identifier
);
188 template <class Type
>
189 class ProcessNexus
: public ProcessNexusBase
{
191 ProcessNexus(const char *identifier
) : ProcessNexusBase(identifier
) { }
192 Type
&operator () ();
198 template <class Type
>
199 Type
&ProcessNexus
<Type
>::operator () ()
201 #if !defined(PTHREAD_STRICT)
202 // not strictly kosher POSIX, but pointers are usually atomic types
204 return *reinterpret_cast<Type
*>(mStore
->mObject
);
206 StLock
<Mutex
> _(mStore
->mLock
);
207 if (mStore
->mObject
== NULL
)
208 mStore
->mObject
= new Type
;
209 return *reinterpret_cast<Type
*>(mStore
->mObject
);
213 } // end namespace Security
215 #endif //_H_GLOBALIZER