Using thread local variables instead of the global ones (MS-RFC-15)

Stephen Woodbridge woodbri at SWOODBRIDGE.COM
Mon May 1 21:06:33 EDT 2006


Tamás,

An excellent, well written and clear RFC. I think you have done a great 
job breaking this large effort into well defined and prioritized 
tactics. Thank you for tackling this important issue for mapserver.

-Steve W.

Szekeres Tamás wrote:
> Developers,
> 
> I was thinking a lot how to move forward with this issue. Since we are
> tending to do something i have added a new RFC
> 
> http://mapserver.gis.umn.edu/development/rfc/ms-rfc-15/
> 
> also added a bug to collect the developer and user comments and update the
> RFC accordingly.
> 
> Feel free to send your comments, modification suggestions, be a co-author
> etc. This RFC is a bit special since wide audience and contribution is
> needed from the maintainers of the different portions of the code.
> 
> Thanks,
> 
> Tamas Szekeres
> 
> 
> -----Original Message-----
> From: UMN MapServer Developers List [mailto:MAPSERVER-DEV at LISTS.UMN.EDU] On
> Behalf Of Frank Warmerdam
> Sent: Friday, April 28, 2006 4:25 PM
> To: MAPSERVER-DEV at LISTS.UMN.EDU
> Subject: Re: [UMN_MAPSERVER-DEV] Using thread local variables instead of the
> global ones
> 
> Szekeres Tamás wrote:
> 
>>At a first sight i have found *only* the following problems
>>in the core mapserver code. Some of the variables contain
>>invariant data and therefore not to be guarded.
> 
> 
> Tamas,
> 
> I'll try and comment on a few of these.
> 
> 
>>\mapserver\epplib.c(47):static int REVERSE; /* set to 1 on
>>bigendian machines */
> 
> 
> EPP support is very narrowly used, and I don't think we need worry
> about it.
> 
> 
>>\mapserver\mapcpl.c(57):static char    
>>szStaticResult[MS_PATH_BUF_SIZE];
> 
> 
> In fact this code carried over from GDAL was later remodelled in
> GDAL.  It looks like msGetBasename() is only used in a few places
> and we could remodel those to avoid using a static buffer.
> 
> 
>>\mapserver\maperror.c(110):static char
>>*ms_errorCodes[MS_NUMERRORCODES] = {"",
> 
> 
> There is no problem with the error codes being static as far as
> I know.  I think perhaps they should be declared static const char
> to indicate they are unchanging.
> 
> 
>>\mapserver\maperror.c(154):    static errorObj ms_error =
>>{MS_NOERR, "", "", NULL};
> 
>  > \mapserver\maperror.c(169):static te_info_t *error_list = NULL;
> 
> In fact, when USE_THREAD is enabled, the static errorObj isn't
> used.  Instead a per-thread error object is maintained and
> selection is managed based on the threadid.  This was a crude
> implementation of thread local data I did when first adding
> multi-thread support.  I believe this area is safe though it could
> stand some remodelling if we had a better approach to thread local
> data.
> 
> 
>>\mapserver\maperror.c(552):  static char version[1024];
> 
> 
> More static stuff.
> 
> 
>>\mapserver\maperror.c(651):    static char nonblocking_set = 0;
> 
> 
> Harmless I believe.
> 
> 
>>\mapserver\mapfile.c(178):static char *msUnits[7]={"INCHES",
>>"FEET", "MILES", "METERS", "KILOMETERS", "DD", "PIXELS"};
>>\mapserver\mapfile.c(179):static char
>>*msLayerTypes[8]={"POINT", "LINE", "POLYGON", "RASTER",
>>"ANNOTATION", "QUERY", "CIRCLE", "TILEINDEX"};
>>\mapserver\mapfile.c(182):static char
>>*msBitmapFontSizes[5]={"TINY", "SMALL", "MEDIUM", "LARGE",
>>"GIANT"};
>>\mapserver\mapfile.c(183):static char
>>*msQueryMapStyles[4]={"NORMAL", "HILITE", "SELECTED",
>>"INVERTED"};
>>\mapserver\mapfile.c(184):static char *msStatus[5]={"OFF",
>>"ON", "DEFAULT", "EMBED"};
>>\mapserver\mapfile.c(186):static char
>>*msTrueFalse[2]={"FALSE", "TRUE"};
>>\mapserver\mapfile.c(188):static char
>>*msJoinType[2]={"ONE-TO-ONE", "ONE-TO-MANY"};
>>
>>\mapserver\mapgd.c(236):static unsigned char PNGsig[8] =
>>{137, 80, 78, 71, 13, 10, 26, 10}; /* 89 50 4E 47 0D 0A 1A
>>0A hex */
>>\mapserver\mapgd.c(237):static unsigned char JPEGsig[3] =
>>{255, 216, 255}; /* FF D8 FF hex */
> 
> 
> The above are all const static data, and no problem.
> 
> 
>>\mapserver\mapgd.c(908):  static gdPoint points[38];
> 
> 
> I think this one should not be static.
> 
> 
>>\mapserver\mapgd.c(2425):  static double last_style_size;
> 
>  > \mapserver\mapgd.c(2716):  static int styleIndex, styleVis;
> 
>>\mapserver\mapgd.c(2717):  static double styleSize=0,
>>styleCoef=0, last_style_size=-1;
>>\mapserver\mapgd.c(2718):  static int last_style_c=-1,
>>last_style_stylelength=-1, last_styleVis=0;
> 
> 
> I think the above are not needing to be static, but it is a
> bit hard to tell without more careful investigation.
> 
> 
>>\mapserver\mapgdal.c(141):static int    bGDALInitialized = 0;
> 
> 
> This only changes once on initialization.  As long as msSetup()
> is called to initialize things I think we are ok.
> 
> 
>>\mapserver\mapgeos.cpp(98):GeometryFactory *gf=NULL; 
> 
> 
> Likewise, this only changes once on initialization.
> 
> 
>>\mapserver\maphttp.c(140):static int gbCurlInitialized =
>>MS_FALSE;
> 
> 
> Ditto
> 
> 
>>\mapserver\mapimagemap.c(141):static char *layerlist=NULL;
>>\mapserver\mapimagemap.c(142):static int layersize=0;
>>\mapserver\mapimagemap.c(143):static pString imgStr,
>>layerStr={ &layerlist, &layersize, 0 };
>>\mapserver\mapimagemap.c(146):static const char
>>*polyHrefFmt, *polyMOverFmt, *polyMOutFmt;
>>\mapserver\mapimagemap.c(147):static const char
>>*symbolHrefFmt, *symbolMOverFmt, *symbolMOutFmt;
>>\mapserver\mapimagemap.c(148):static const char *mapName;
>>\mapserver\mapimagemap.c(150):static int suppressEmpty=0;
>>\mapserver\mapimagemap.c(229):static int lastcolor=-1;
>>\mapserver\mapimagemap.c(273):static char* lname;
>>\mapserver\mapimagemap.c(274):static int dxf;
> 
> 
> Whew!  Well, lets just say that imagemap support (not widely
> used at all) is not threadsafe.
> 
> 
>>\mapserver\mapio.c(67):static int is_msIO_initialized =
>>MS_FALSE;
>>\mapserver\mapio.c(69):static msIOContext default_stdin_context;
>>\mapserver\mapio.c(70):static msIOContext
>>default_stdout_context;
>>\mapserver\mapio.c(71):static msIOContext
>>default_stderr_context;
>>\mapserver\mapio.c(73):static msIOContext current_stdin_context;
>>\mapserver\mapio.c(74):static msIOContext
>>current_stdout_context;
>>\mapserver\mapio.c(75):static msIOContext
>>current_stderr_context;
> 
> 
> Currently there is only one process wide set of "io handlers" for
> io.  This will almost certainly need to change at some point to be
> thread local in some fashion.  I hope to address this when I work
> on the redirectable OWS services accessable from mapscript this spring.
> 
> As things stand this is fine as long as only stdout output is being
> used, or if other mechanisms (via mapscript) are used.
> 
> 
>>\mapserver\maplexer.c(220):static YY_BUFFER_STATE
>>yy_current_buffer = 0;
>>\mapserver\maplexer.c(230):static char yy_hold_char;
>>\mapserver\maplexer.c(232):static int yy_n_chars;		/* number
>>of characters read into yy_ch_buf */
>>\mapserver\maplexer.c(238):static char *yy_c_buf_p = (char *) 0;
>>\mapserver\maplexer.c(239):static int yy_init = 1;		/*
>>whether we need to initialize */
>>\mapserver\maplexer.c(240):static int yy_start = 0;	/* start
>>state number */
>>\mapserver\maplexer.c(306):static yyconst short int
>>yy_accept[2406] =
>>\mapserver\maplexer.c(575):static yyconst int yy_ec[256] =
>>\mapserver\maplexer.c(607):static yyconst int yy_meta[52] =
>>\mapserver\maplexer.c(617):static yyconst short int
>>yy_base[2420] =
>>\mapserver\maplexer.c(887):static yyconst short int
>>yy_def[2420] =
>>\mapserver\maplexer.c(1157):static yyconst short int
>>yy_nxt[2740] =
>>\mapserver\maplexer.c(1462):static yyconst short int
>>yy_chk[2740] =
>>\mapserver\maplexer.c(1767):static yy_state_type
>>yy_last_accepting_state;
>>\mapserver\maplexer.c(1768):static char *yy_last_accepting_cpos;
>>\mapserver\maplexer.c(1866):static int yy_start_stack_ptr = 0;
>>\mapserver\maplexer.c(1867):static int yy_start_stack_depth = 0;
>>\mapserver\maplexer.c(1868):static int *yy_start_stack = 0;
> 
> 
> I believe Steve suggested we can address this with newer
> versions of bison and flex invoked appropriately.
> 
> 
>>\mapserver\mapmygis.c(245):static int gBYTE_ORDER = 0;
> 
> 
> I think this could be moved into a per-layer structure, but
> the "mygis" code isn't well maintained.
> 
> 
>>\mapserver\mapogcsos.c(1974):    static char *request=NULL,
>>*service=NULL;
> 
> 
> I'm not sure if this needs to be static.  Assefa, could you
> review?
> 
> 
>>\mapserver\mapogr.cpp(840):static int bOGRDriversRegistered
>>= MS_FALSE;
> 
> 
> Usual startup initialization.
> 
> 
>>\mapserver\mapows.c(1647):  static char epsgCode[20] ="";
> 
> 
> Whew, this is used in quite a few places.  It could be made
> thread-local data or perhaps the code depending on it could
> be remodelled.
> 
> 
>>\mapserver\mapparser.c(282):static const unsigned char
>>yytranslate[] =
>>\mapserver\mapparser.c(317):static const unsigned char
>>yyprhs[] =
>>\mapserver\mapparser.c(328):static const yysigned_char yyrhs[] =
>>\mapserver\mapparser.c(354):static const unsigned short
>>yyrline[] =
>>\mapserver\mapparser.c(368):static const char *const yytname[] =
>>\mapserver\mapparser.c(381):static const unsigned short
>>yytoknum[] =
>>\mapserver\mapparser.c(391):static const unsigned char yyr1[] =
>>\mapserver\mapparser.c(402):static const unsigned char yyr2[] =
>>\mapserver\mapparser.c(415):static const unsigned char
>>yydefact[] =
>>\mapserver\mapparser.c(431):static const yysigned_char
>>yydefgoto[] =
>>\mapserver\mapparser.c(439):static const short yypact[] =
>>\mapserver\mapparser.c(455):static const yysigned_char
>>yypgoto[] =
>>\mapserver\mapparser.c(465):static const unsigned char
>>yytable[] =
>>\mapserver\mapparser.c(491):static const yysigned_char
>>yycheck[] =
>>\mapserver\mapparser.c(519):static const unsigned char
>>yystos[] =
> 
> 
> As per lexer, use new bison with right options.
> 
> 
>>\mapserver\mappluginlayer.c(46):static VTFactoryObj
>>gVirtualTableFactory = {MS_MAXLAYERS, 0, {NULL}};
> 
> 
> Intended to be global, and properly protected by lock.
> 
> 
>>\mapserver\mappool.c(206):static int connectionCount = 0;
>>\mapserver\mappool.c(207):static int connectionMax = 0;
>>\mapserver\mappool.c(208):static connectionObj *connections
>>= NULL;
> 
> 
> Intended to be global and properly protected by lock.
> 
> 
>>\mapserver\mapproject.c(889):static char *ms_proj_lib = NULL;
>>\mapserver\mapproject.c(890):static char *last_filename = NULL;
>>\mapserver\mapproject.c(918):    static int finder_installed
>>= 0;
> 
> 
> Hmm, this might need rework.
> 
> 
>>\mapserver\mapscale.c(68):static char *unitText[5]={"in",
>>"ft", "mi", "m", "km"};
>>\mapserver\mapscale.c(69):double inchesPerUnit[6]={1, 12,
>>63360.0, 39.3701, 39370.1, 4374754};
> 
> 
> const static data.
> 
> 
>>\mapserver\mapsde.c(216):static int lcacheCount = 0;
>>\mapserver\mapsde.c(217):static int lcacheMax = 0;
>>\mapserver\mapsde.c(218):static layerId *lcache = NULL;
> 
> 
> Protected by SDE lock.
> 
> 
>>\mapserver\mapshape.c(70):static int      bBigEndian;
> 
> 
> this is a one time initialization.  No danger.
> 
> 
>>\mapserver\mapsvg.c(164):    static char epsgCode[20] ="";
>>\mapserver\mapsvg.c(165):    static char *value;
> 
> 
> I'm not too sure about this one.
> 
> 
>>\mapserver\mapswf.c(97):static char gszFilename[128];
>>\mapserver\mapswf.c(98):static char gszAction[256];
>>\mapserver\mapswf.c(99):static char gszTmp[256];
> 
> 
> Or this.
> 
> 
>>\mapserver\mapsymbol.c(151):static char
>>*msCapsJoinsCorners[7]={"NONE", "BEVEL", "BUTT", "MITER",
>>"ROUND", "SQUARE", "TRIANGLE"};
> 
> 
> const static.
> 
> 
>>\mapserver\mapthread.c(196):static int thread_debug = 0;
> 
> 
> should be const static.
> 
> 
>>\mapserver\mapthread.c(198):static char *lock_names[] = 
> 
> 
> const static.
> 
> 
>>\mapserver\mapthread.c(213):static int mutexes_initialized = 0;
>>\mapserver\mapthread.c(214):static pthread_mutex_t
>>mutex_locks[TLOCK_MAX];
> 
> 
> one time init.
> 
> 
>>\mapserver\mapthread.c(223):    static pthread_mutex_t
>>core_lock = PTHREAD_MUTEX_INITIALIZER;
> 
> 
> one time init.
> 
> 
>>\mapserver\mapthread.c(294):static int mutexes_initialized = 0;
>>\mapserver\mapthread.c(295):static HANDLE
>>mutex_locks[TLOCK_MAX];
>>\mapserver\mapthread.c(305):    static HANDLE core_lock = NULL;
> 
> 
> one time init.
> 
> 
>>\mapserver\maputil.c(1068):static int tmpCount = 0;
>>\mapserver\maputil.c(1069):static char *ForcedTmpBase = NULL;
> 
> 
> These are generally only set once.  Limitations should be made clear.
> 
> 
>>\mapserver\mapwms.c(249):static char *wms_exception_format=NULL;
>>\mapserver\mapwms.c(2779):  static char *request=NULL,
>>*service=NULL, *format=NULL;
> 
> 
> not too sure.
> 
> 
>>\mapserver\md5c.c(58):static unsigned char PADDING[64] = {
>>
>>\mapserver\strptime.c(43):static const char *abb_weekdays[] = {
>>\mapserver\strptime.c(54):static const char *full_weekdays[] = {
>>\mapserver\strptime.c(65):static const char *abb_month[] = {
>>\mapserver\strptime.c(81):static const char *full_month[] = {
>>\mapserver\strptime.c(97):static const char *ampm[] = {
> 
> 
> static const.
> 
> 
>>\mapserver\gdft\gdkanji.c(103):	static int whatcode;
>>\mapserver\gdft\gdkanji.c(403):	static unsigned char
>>tmp[BUFSIZ];
>>\mapserver\gdft\gdkanji.c(489):	static unsigned char
>>tmp_dest[BUFSIZ];
> 
> 
> I don't know.  I didn't realize this directory existed.
> 
> 
>>\mapserver\gdft\gdttf.c(712):  static gdCache_head_t
>>*tweenColorCache=NULL; /****** set up tweenColorCache on
>>first call ************/
>>\mapserver\gdft\gdttf.c(852):  static gdCache_head_t
>>*fontCache=NULL; /****** initialize font engine on first
>>call ************/
>>\mapserver\gdft\gdttf.c(853):  static TT_Engine 	engine;
>>\mapserver\gdft\jisx0208.h(7):static unsigned short
>>UnicodeTbl[][94] = {
> 
> 
> Ditto.
> 
> 
> I don't really think we are in bad shape.
> 
> Best regards,



More information about the mapserver-dev mailing list