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