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