File: threadSvCmd.h

package info (click to toggle)
tclthread3 3.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,752 kB
  • sloc: ansic: 8,259; tcl: 1,711; sh: 436; makefile: 38
file content (226 lines) | stat: -rw-r--r-- 7,733 bytes parent folder | download | duplicates (2)
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:                  */