1
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
// % Project : GUSI - Grand Unified Socket Interface
3
// % File : GUSISpecific.nw - Thread specific variables
4
// % Author : Matthias Neeracher
7
// % $Log: GUSISpecific.h,v $
8
// % Revision 1.1 2001/03/11 22:38:39 sgehani%netscape.com
11
// % Revision 1.9 2000/10/16 04:11:21 neeri
14
// % Revision 1.8 2000/03/15 07:22:07 neeri
15
// % Enforce alignment choices
17
// % Revision 1.7 1999/08/26 05:45:10 neeri
18
// % Fixes for literate edition of source code
20
// % Revision 1.6 1999/05/30 03:09:31 neeri
21
// % Added support for MPW compilers
23
// % Revision 1.5 1999/04/29 04:58:20 neeri
24
// % Fix key destruction bug
26
// % Revision 1.4 1999/03/17 09:05:13 neeri
27
// % Added GUSITimer, expanded docs
29
// % Revision 1.3 1998/10/11 16:45:25 neeri
30
// % Ready to release 2.0a2
32
// % Revision 1.2 1998/08/01 21:32:11 neeri
33
// % About ready for 2.0a1
35
// % Revision 1.1 1998/01/25 21:02:52 neeri
36
// % Engine implemented, except for signals & scheduling
38
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40
// \chapter{Thread Specific Variables}
42
// It is often useful to have variables which maintain a different value
43
// for each process. The [[GUSISpecific]] class implements such a mechanism
44
// in a way that is easily mappable to pthreads.
48
#ifndef _GUSISpecific_
49
#define _GUSISpecific_
53
typedef struct GUSISpecific GUSISpecific;
58
#include <ConditionalMacros.h>
60
#if PRAGMA_STRUCT_ALIGN
61
#pragma options align=native
64
// \section{Definition of Thread Specific Variables}
66
// A [[GUSISpecific]] instance contains a variable ID and a per-process
69
// <Definition of class [[GUSISpecific]]>=
71
typedef void (*GUSISpecificDestructor)(void *);
75
friend class GUSISpecificTable;
77
GUSISpecific(GUSISpecificDestructor destructor = nil);
80
void Destruct(void * data);
82
GUSISpecificDestructor fDestructor;
84
static unsigned sNextID;
86
// A [[GUSIContext]] contains a [[GUSISpecificTable]] storing the values of all
87
// thread specific variables defined for this thread.
89
// <Definition of class [[GUSISpecificTable]]>=
90
class GUSISpecificTable {
91
friend class GUSISpecific;
95
void * GetSpecific(const GUSISpecific * key) const;
96
void SetSpecific(const GUSISpecific * key, void * value);
97
void DeleteSpecific(const GUSISpecific * key);
99
static void Register(GUSISpecific * key);
100
static void Destruct(GUSISpecific * key);
102
// We store a [[GUSISpecificTable]] as a contiguous range of IDs.
104
// <Privatissima of [[GUSISpecificTable]]>=
108
bool Valid(const GUSISpecific * key) const;
109
// All keys are registered in a global table.
111
// <Privatissima of [[GUSISpecificTable]]>=
112
static GUSISpecific *** sKeys;
113
static unsigned sKeyAlloc;
115
// To simplify having a particular variable assume a different instance in every
116
// thread, we define the [[GUSISpecificData]] template.
118
// <Definition of template [[GUSISpecificData]]>=
119
template <class T, GUSISpecificDestructor D>
120
class GUSISpecificData {
122
GUSISpecificData() : fKey(D) { }
123
T & operator*() { return *get(); }
124
T * operator->() { return get(); }
126
const GUSISpecific * Key() const { return &fKey; }
127
T * get(GUSISpecificTable * table);
128
T * get() { return get(GUSIContext::Current()); }
133
template <class T, GUSISpecificDestructor D>
134
T * GUSISpecificData<T,D>::get(GUSISpecificTable * table)
136
void * data = table->GetSpecific(&fKey);
139
table->SetSpecific(&fKey, data = new T);
141
return static_cast<T *>(data);
144
#if PRAGMA_STRUCT_ALIGN
145
#pragma options align=reset
148
// <Inline member functions for class [[GUSISpecific]]>=
149
inline GUSISpecific::GUSISpecific(GUSISpecificDestructor destructor)
150
: fDestructor(destructor), fID(sNextID++)
152
GUSISpecificTable::Register(this);
155
inline GUSISpecific::~GUSISpecific()
157
GUSISpecificTable::Destruct(this);
160
inline void GUSISpecific::Destruct(void * data)
165
// <Inline member functions for class [[GUSISpecificTable]]>=
166
inline bool GUSISpecificTable::Valid(const GUSISpecific * key) const
168
return key && key->fID < fAlloc;
170
// <Inline member functions for class [[GUSISpecificTable]]>=
171
inline GUSISpecificTable::GUSISpecificTable()
172
: fValues(nil), fAlloc(0)
175
// <Inline member functions for class [[GUSISpecificTable]]>=
176
inline void * GUSISpecificTable::GetSpecific(const GUSISpecific * key) const
179
return fValues[0][key->fID];
184
#endif /* GUSI_SOURCE */
186
#endif /* _GUSISpecific_ */