]> git.saurik.com Git - apple/security.git/blame - cdsa/cdsa_utilities/globalizer.h
Security-54.1.9.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / globalizer.h
CommitLineData
bac41a7b
A
1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19/*
20 * globalizer - multiscope globalization services
21 */
22#ifndef _H_GLOBALIZER
23#define _H_GLOBALIZER
24
25#include <Security/threading.h>
26#include <memory>
27
29654253 28namespace Security {
bac41a7b 29
bac41a7b
A
30
31//
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.
35//
36class GlobalNexus {
37public:
29654253 38 class Error : public std::exception {
bac41a7b 39 public:
29654253 40 virtual ~Error() throw();
bac41a7b
A
41 const char * const message;
42 Error(const char *m) : message(m) { }
29654253 43 const char *what() const throw() { return message; }
bac41a7b
A
44 };
45};
46
47
48//
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.
53//
54// IMPORTANT notes on this class can be found in globalizer.cpp.
55// DO NOT change anything here before carefully reading them.
56//
57#if defined(_HAVE_ATOMIC_OPERATIONS)
58
59class ModuleNexusCommon : public GlobalNexus {
60protected:
61 AtomicWord create(void *(*make)());
62
63protected:
64 // both of these will be statically initialized to zero
65 AtomicWord pointer;
66 StaticAtomicCounter<uint32> sync;
67};
68
69template <class Type>
70class ModuleNexus : public ModuleNexusCommon {
71public:
72 Type &operator () ()
73 {
74 AtomicWord p = pointer; // latch pointer
75 return *reinterpret_cast<Type *>((p && !(p & 0x1)) ? p : create(make));
76 }
77
78 void reset()
79 {
80 if (pointer && !(pointer & 0x1)) {
81 delete reinterpret_cast<Type *>(pointer);
82 pointer = 0;
83 }
84 }
85
86private:
87 static void *make() { return new Type; }
88};
89
29654253
A
90template <class Type>
91class CleanModuleNexus : public ModuleNexus<Type> {
92public:
93 ~CleanModuleNexus()
94 {
95 debug("nexus", "ModuleNexus %p destroyed object 0x%x", this, pointer);
96 delete reinterpret_cast<Type *>(pointer);
97 }
98};
99
bac41a7b
A
100#else // !_HAVE_ATOMIC_OPERATIONS
101
102template <class Type>
103class ModuleNexus : public GlobalNexus {
104public:
105 Type &operator () ()
106 {
107#if !defined(PTHREAD_STRICT)
108 // not strictly kosher POSIX, but pointers are usually atomic types
109 if (mSingleton)
110 return *mSingleton;
111#endif
112 StLock<Mutex> _(mLock);
113 if (mSingleton == NULL)
114 mSingleton = new Type;
115 return *mSingleton;
116 }
117
118 void reset() { delete mSingleton; mSingleton = NULL; }
119
29654253 120protected:
bac41a7b
A
121 Type *mSingleton; // pointer to singleton static initialized to NULL
122 Mutex mLock; // construction lock
123};
124
bac41a7b
A
125template <class Type>
126class CleanModuleNexus : public ModuleNexus<Type> {
127public:
128 ~CleanModuleNexus()
129 {
29654253
A
130 debug("nexus", "ModuleNexus %p destroyed object 0x%x", this, mSingleton);
131 delete mSingleton;
bac41a7b
A
132 }
133};
134
29654253
A
135#endif // _HAVE_ATOMIC_OPERATIONS
136
bac41a7b
A
137
138//
139// A thread-scope nexus is tied to a particular native thread AND
140// a particular nexus object. Its scope is all code in any one thread
141// that access that particular Nexus object. Any number of Nexus objects
142// can exist, and each implements a different scope for each thread.
143// NOTE: ThreadNexus is dynamically constructed. If you want static,
144// zero-initialization ThreadNexi, put them inside a ModuleNexus.
145//
146#if _USE_THREADS == _USE_PTHREADS
147
148template <class Type>
149class ThreadNexus : public GlobalNexus {
150public:
151 ThreadNexus() : mSlot(true) { }
152 Type &operator () ()
153 {
154 // no thread contention here!
155 if (Type *p = mSlot)
156 return *p;
157 mSlot = new Type;
158 return *mSlot;
159 }
160
161private:
162 PerThreadPointer<Type> mSlot;
163};
164
165#endif //_USE_PTHREADS
166
167
168//
169// A ProcessNexus is global within a single process, regardless of
170// load module boundaries. You can have any number of ProcessNexus
171// scopes, each identified by a C string (compared by value, not pointer).
172//
173class ProcessNexusBase : public GlobalNexus {
174protected:
175 ProcessNexusBase(const char *identifier);
176
177 struct Store {
178 void *mObject;
179 Mutex mLock;
180 };
181 Store *mStore;
182};
183
184template <class Type>
185class ProcessNexus : public ProcessNexusBase {
186public:
187 ProcessNexus(const char *identifier) : ProcessNexusBase(identifier) { }
188 Type &operator () ();
189
190private:
191 Type *mObject;
192};
193
194template <class Type>
195Type &ProcessNexus<Type>::operator () ()
196{
197#if !defined(PTHREAD_STRICT)
198 // not strictly kosher POSIX, but pointers are usually atomic types
199 if (mStore->mObject)
200 return *reinterpret_cast<Type *>(mStore->mObject);
201#endif
202 StLock<Mutex> _(mStore->mLock);
203 if (mStore->mObject == NULL)
204 mStore->mObject = new Type;
205 return *reinterpret_cast<Type *>(mStore->mObject);
206};
207
208
209} // end namespace Security
210
211#endif //_H_GLOBALIZER