1/*
2 * This is the header file for the module that implements shared variables.
3 * for protected multithreaded access.
4 *
5 * Copyright (c) 2002 by Zoran Vasiljevic.
6 *
7 * See the file "license.txt" for information on usage and redistribution
8 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9 *
10 * Rcsid: @(#)$Id: threadSvCmd.h,v 1.17 2010/03/31 08:50:24 vasiljevic Exp $
11 * ---------------------------------------------------------------------------
12 */
13
14#ifndef _SV_H_
15#define _SV_H_
16
17#include <tcl.h>
18#include <ctype.h>
19#include <string.h>
20
21#include "threadSpCmd.h" /* For recursive locks */
22
23/*
24 * Uncomment following line to get command-line
25 * compatibility with AOLserver nsv_* commands
26 */
27
28/* #define NSV_COMPAT 1 */
29
30/*
31 * Uncomment following line to force command-line
32 * compatibility with older thread::sv_ commands
33 * If you leave it commented-out, the older style
34 * command is going to be included in addition to
35 * the new tsv::* style.
36 */
37
38/* #define OLD_COMPAT 1 */
39
40#ifdef NS_AOLSERVER
41# ifdef NSV_COMPAT
42#  define TSV_CMD_PREFIX "nsv_"  /* Compatiblity prefix for AOLserver */
43# else
44#  define TSV_CMD_PREFIX "sv_"   /* Regular command prefix for AOLserver */
45# endif
46#else
47# ifdef OLD_COMPAT
48#  define TSV_CMD_PREFIX "thread::sv_" /* Old command prefix for Tcl */
49# else
50#  define TSV_CMD_PREFIX "tsv::" /* Regular command prefix for Tcl */
51# endif
52#endif
53
54/*
55 * Used when creating arrays/variables
56 */
57
58#define FLAGS_CREATEARRAY  1   /* Create the array in bucket if none found */
59#define FLAGS_NOERRMSG     2   /* Do not format error message */
60#define FLAGS_CREATEVAR    4   /* Create the array variable if none found */
61
62/*
63 * Macros for handling locking and unlocking
64 */
65#define LOCK_BUCKET(a)      Sp_RecursiveMutexLock(&(a)->lock)
66#define UNLOCK_BUCKET(a)    Sp_RecursiveMutexUnlock(&(a)->lock)
67
68#define LOCK_CONTAINER(a)   Sp_RecursiveMutexLock(&(a)->bucketPtr->lock)
69#define UNLOCK_CONTAINER(a) Sp_RecursiveMutexUnlock(&(a)->bucketPtr->lock)
70
71/*
72 * This is named synetrically to LockArray as function
73 * rather than as a macro just to improve readability.
74 */
75
76#define UnlockArray(a) UNLOCK_CONTAINER(a)
77
78/*
79 * Mode for Sv_PutContainer, so it knows what
80 * happened with the embedded shared object.
81 */
82
83#define SV_UNCHANGED       0   /* Object has not been modified */
84#define SV_CHANGED         1   /* Object has been modified */
85#define SV_ERROR          -1   /* Object may be in incosistent state */
86
87/*
88 * Definitions of functions implementing simple key/value
89 * persistent storage for shared variable arrays.
90 */
91
92typedef ClientData (ps_open_proc)(const char*);
93
94typedef int (ps_get_proc)   (ClientData, const char*, char**, int*);
95typedef int (ps_put_proc)   (ClientData, const char*, char*, int);
96typedef int (ps_first_proc) (ClientData, char**, char**, int*);
97typedef int (ps_next_proc)  (ClientData, char**, char**, int*);
98typedef int (ps_delete_proc)(ClientData, const char*);
99typedef int (ps_close_proc) (ClientData);
100typedef void(ps_free_proc)  (char*);
101
102typedef char* (ps_geterr_proc)(ClientData);
103
104/*
105 * This structure maintains a bunch of pointers to functions implementing
106 * the simple persistence layer for the shared variable arrays.
107 */
108
109typedef struct PsStore {
110    char *type;                /* Type identifier of the persistent storage */
111    ClientData psHandle;       /* Handle to the opened storage */
112    ps_open_proc   *psOpen;    /* Function to open the persistent key store */
113    ps_get_proc    *psGet;     /* Function to retrieve value bound to key */
114    ps_put_proc    *psPut;     /* Function to store user key and value */
115    ps_first_proc  *psFirst;   /* Function to retrieve the first key/value */
116    ps_next_proc   *psNext;    /* Function to retrieve the next key/value */
117    ps_delete_proc *psDelete;  /* Function to delete user key and value */
118    ps_close_proc  *psClose;   /* Function to close the persistent store */
119    ps_free_proc   *psFree;    /* Fuction to free allocated memory */
120    ps_geterr_proc *psError;   /* Function to return last store error */
121    struct PsStore *nextPtr;   /* For linking into linked lists */
122} PsStore;
123
124/*
125 * The following structure defines a collection of arrays.
126 * Only the arrays within a given bucket share a lock,
127 * allowing for more concurency.
128 */
129
130typedef struct Bucket {
131    Sp_RecursiveMutex lock;    /* */
132    Tcl_ThreadId lockt;        /* Thread holding the lock */
133    Tcl_HashTable arrays;      /* Hash table of all arrays in bucket */
134    Tcl_HashTable handles;     /* Hash table of given-out handles in bucket */
135    struct Container *freeCt;  /* List of free Tcl-object containers */
136} Bucket;
137
138/*
139 * The following structure maintains the context for each variable array.
140 */
141
142typedef struct Array {
143    char *bindAddr;            /* Array is bound to this address */
144    PsStore *psPtr;            /* Persistent storage functions */
145    Bucket *bucketPtr;         /* Array bucket. */
146    Tcl_HashEntry *entryPtr;   /* Entry in bucket array table. */
147    Tcl_HashEntry *handlePtr;  /* Entry in handles table */
148    Tcl_HashTable vars;        /* Table of variables. */
149} Array;
150
151/*
152 * The object container for Tcl-objects stored within shared arrays.
153 */
154
155typedef struct Container {
156    Bucket *bucketPtr;         /* Bucket holding the array below */
157    Array *arrayPtr;           /* Array with the object container*/
158    Tcl_HashEntry *entryPtr;   /* Entry in array table. */
159    Tcl_HashEntry *handlePtr;  /* Entry in handles table */
160    Tcl_Obj *tclObj;           /* Tcl object to hold shared values */
161    int epoch;                 /* Track object changes */
162    char *chunkAddr;           /* Address of one chunk of object containers */
163    struct Container *nextPtr; /* Next object container in the free list */
164} Container;
165
166/*
167 * Structure for generating command names in Tcl
168 */
169
170typedef struct SvCmdInfo {
171    char *name;                 /* The short name of the command */
172    char *cmdName;              /* Real (rewritten) name of the command */
173    Tcl_ObjCmdProc *objProcPtr; /* The object-based command procedure */
174    Tcl_CmdDeleteProc *delProcPtr; /* Pointer to command delete function */
175    ClientData *clientData;     /* Pointer passed to above command */
176    struct SvCmdInfo *nextPtr;  /* Next in chain of registered commands */
177} SvCmdInfo;
178
179/*
180 * Structure for registering special object duplicator functions.
181 * Reason for this is that even some regular Tcl duplicators
182 * produce shallow instead of proper deep copies of the object.
183 * While this is considered to be ok in single-threaded apps,
184 * a multithreaded app could have problems when accessing objects
185 * which live in (i.e. are accessed from) different interpreters.
186 * So, for each object type which should be stored in shared object
187 * pools, we must assure that the object is copied properly.
188 */
189
190typedef struct RegType {
191    const Tcl_ObjType *typePtr;       /* Type of the registered object */
192    Tcl_DupInternalRepProc *dupIntRepProc; /* Special deep-copy duper */
193    struct RegType *nextPtr;    /* Next in chain of registered types */
194} RegType;
195
196/*
197 * Limited API functions
198 */
199
200void
201Sv_RegisterCommand(const char*,Tcl_ObjCmdProc*,Tcl_CmdDeleteProc*,ClientData);
202
203void
204Sv_RegisterObjType(const Tcl_ObjType*, Tcl_DupInternalRepProc*);
205
206void
207Sv_RegisterPsStore(PsStore*);
208
209int
210Sv_GetContainer(Tcl_Interp*,int,Tcl_Obj*const objv[],Container**,int*,int);
211
212int
213Sv_PutContainer(Tcl_Interp*, Container*, int);
214
215/*
216 * Private version of Tcl_DuplicateObj which takes care about
217 * copying objects when loaded to and retrieved from shared array.
218 */
219
220Tcl_Obj* Sv_DuplicateObj(Tcl_Obj*);
221
222#endif /* _SV_H_ */
223
224/* EOF $RCSfile: threadSvCmd.h,v $ */
225
226/* Emacs Setup Variables */
227/* Local Variables:      */
228/* mode: C               */
229/* indent-tabs-mode: nil */
230/* c-basic-offset: 4     */
231/* End:                  */
232
233