From: <he...@us...> - 2011-03-26 02:16:43
|
Revision: 264 http://simspark.svn.sourceforge.net/simspark/?rev=264&view=rev Author: hedayat Date: 2011-03-26 02:16:36 +0000 (Sat, 26 Mar 2011) Log Message: ----------- * S-Expression library is now thread-safe. It was the source of crashes in multi-threaded mode Modified Paths: -------------- trunk/spark/ChangeLog trunk/spark/plugin/rubysceneimporter/rubysceneimporter.cpp trunk/spark/plugin/rubysceneimporter/rubysceneimporter.h trunk/spark/plugin/sexpparser/sexpparser.cpp trunk/spark/plugin/sexpparser/sexpparser.h trunk/spark/plugin/sparkmonitor/sparkmonitorclient.cpp trunk/spark/plugin/sparkmonitor/sparkmonitorclient.h trunk/spark/plugin/sparkmonitor/sparkmonitorlogfileserver.cpp trunk/spark/plugin/sparkmonitor/sparkmonitorlogfileserver.h trunk/spark/utility/sfsexp/io.c trunk/spark/utility/sfsexp/parser.c trunk/spark/utility/sfsexp/sexp.c trunk/spark/utility/sfsexp/sexp.h trunk/spark/utility/sfsexp/sexp_ops.c trunk/spark/utility/sfsexp/sexp_ops.h Modified: trunk/spark/ChangeLog =================================================================== --- trunk/spark/ChangeLog 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/ChangeLog 2011-03-26 02:16:36 UTC (rev 264) @@ -1,5 +1,24 @@ 2011-03-26 Hedayat Vatankhah <hed...@gm...> + * plugin/sexpparser/sexpparser.h: + * plugin/sexpparser/sexpparser.cpp: + * plugin/rubysceneimporter/rubysceneimporter.h: + * plugin/rubysceneimporter/rubysceneimporter.cpp: + * plugin/sparkmonitor/sparkmonitorclient.h: + * plugin/sparkmonitor/sparkmonitorclient.cpp: + * plugin/sparkmonitor/sparkmonitorlogfileserver.h: + * plugin/sparkmonitor/sparkmonitorlogfileserver.cpp: + - updated to be compatible with the reentrant s-expression library + + * utility/sfsexp/sexp.h: + * utility/sfsexp/sexp.c: + * utility/sfsexp/parser.c: + * utility/sfsexp/io.c: + * utility/sfsexp/sexp_ops.c: + * utility/sfsexp/sexp_ops.h: + - s-expression library is now reentrant and thread-safe. solves many + crashes in multi-threaded mode + * NEWS: * RELEASE: - updated for 0.2.2 release Modified: trunk/spark/plugin/rubysceneimporter/rubysceneimporter.cpp =================================================================== --- trunk/spark/plugin/rubysceneimporter/rubysceneimporter.cpp 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/plugin/rubysceneimporter/rubysceneimporter.cpp 2011-03-26 02:16:36 UTC (rev 264) @@ -86,10 +86,12 @@ mUpdateSceneDict = false; InitTranslationTable(); + mSexpMemory = init_sexp_memory(); } RubySceneImporter::~RubySceneImporter() { + destroy_sexp_memory(mSexpMemory); } void RubySceneImporter::SetUnlinkOnCompleteScenes(bool unlink) @@ -180,7 +182,8 @@ { // parse s-expressions pcont_t* pcont = init_continuation(const_cast<char*>(scene)); - sexp_t* sexp = iparse_sexp(const_cast<char*>(scene),size,pcont); + sexp_t* sexp = iparse_sexp(mSexpMemory, + const_cast<char*>(scene), size, pcont); // read scene magic and version if ( @@ -190,16 +193,16 @@ (mVersionMinor != 1) ) { - destroy_sexp(sexp); - destroy_continuation(pcont); + destroy_sexp(mSexpMemory, sexp); + destroy_continuation(mSexpMemory, pcont); return false; } // advance to next sexpression- the scene graph PushParameter(parameter); - destroy_sexp(sexp); - sexp = iparse_sexp(const_cast<char*>(scene),size,pcont); + destroy_sexp(mSexpMemory, sexp); + sexp = iparse_sexp(mSexpMemory, const_cast<char*>(scene), size, pcont); if (sexp == 0) { @@ -223,8 +226,8 @@ ReadDeltaGraph(sexp,root) : ReadGraph(sexp,root); - destroy_sexp(sexp); - destroy_continuation(pcont); + destroy_sexp(mSexpMemory, sexp); + destroy_continuation(mSexpMemory, pcont); InvokeMethods(); PopParameter(); @@ -489,7 +492,7 @@ { return false; } - } + } else { if (! EvalParameter(sexp->list, atom)) Modified: trunk/spark/plugin/rubysceneimporter/rubysceneimporter.h =================================================================== --- trunk/spark/plugin/rubysceneimporter/rubysceneimporter.h 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/plugin/rubysceneimporter/rubysceneimporter.h 2011-03-26 02:16:36 UTC (rev 264) @@ -140,6 +140,9 @@ /** the abbreviaton table */ TTranslationTable mTranslationTable; + + /** the s-expression library memory management object */ + sexp_mem_t *mSexpMemory; }; DECLARE_CLASS(RubySceneImporter); Modified: trunk/spark/plugin/sexpparser/sexpparser.cpp =================================================================== --- trunk/spark/plugin/sexpparser/sexpparser.cpp 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/plugin/sexpparser/sexpparser.cpp 2011-03-26 02:16:36 UTC (rev 264) @@ -30,10 +30,12 @@ SexpParser::SexpParser() : BaseParser() { + mSexpMemory = init_sexp_memory(); } SexpParser::~SexpParser() { + destroy_sexp_memory(mSexpMemory); } boost::shared_ptr<PredicateList> @@ -49,16 +51,18 @@ char* c = const_cast<char*>(input.c_str()); pcont_t* pcont = init_continuation(c); - sexp_t* sexp = iparse_sexp(c,static_cast<int>(input.size()),pcont); + sexp_t* sexp = iparse_sexp(mSexpMemory, c, static_cast<int>(input.size()), + pcont); while (sexp != 0) { SexpToPredicate(predList,sexp); - destroy_sexp(sexp); - sexp = iparse_sexp(c,static_cast<int>(input.size()),pcont); + destroy_sexp(mSexpMemory, sexp); + sexp = iparse_sexp(mSexpMemory, c, static_cast<int>(input.size()), + pcont); } - destroy_continuation(pcont); + destroy_continuation(mSexpMemory, pcont); return predList; } Modified: trunk/spark/plugin/sexpparser/sexpparser.h =================================================================== --- trunk/spark/plugin/sexpparser/sexpparser.h 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/plugin/sexpparser/sexpparser.h 2011-03-26 02:16:36 UTC (rev 264) @@ -48,6 +48,10 @@ void PredicateToString(std::stringstream& ss, const oxygen::Predicate& predicate); + +private: + /** the s-expression library memory management object */ + sexp_mem_t *mSexpMemory; }; DECLARE_CLASS(SexpParser); Modified: trunk/spark/plugin/sparkmonitor/sparkmonitorclient.cpp =================================================================== --- trunk/spark/plugin/sparkmonitor/sparkmonitorclient.cpp 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/plugin/sparkmonitor/sparkmonitorclient.cpp 2011-03-26 02:16:36 UTC (rev 264) @@ -38,10 +38,12 @@ SparkMonitorClient::SparkMonitorClient() : NetClient() { + mSexpMemory = init_sexp_memory(); } SparkMonitorClient::~SparkMonitorClient() { + destroy_sexp_memory(mSexpMemory); } void SparkMonitorClient::OnLink() @@ -192,7 +194,7 @@ mActiveScene = mSceneServer->GetActiveScene(); mActiveScene->UpdateCache(); - + if (mActiveScene.get() == 0) { return; @@ -220,12 +222,12 @@ char* msgBuf = const_cast<char*>(msg.c_str()); pcont_t* pcont = init_continuation(msgBuf); - sexp_t* sexp_custom = iparse_sexp(msgBuf,msg.size(),pcont); + sexp_t* sexp_custom = iparse_sexp(mSexpMemory, msgBuf, msg.size(), pcont); if (sexp_custom == 0) { - destroy_sexp(sexp_custom); - destroy_continuation(pcont); + destroy_sexp(mSexpMemory, sexp_custom); + destroy_continuation(mSexpMemory, pcont); return; } @@ -234,9 +236,9 @@ mSceneImporter->ParseScene(string(pcont->lastPos), mManagedScene, boost::shared_ptr<ParameterList>()); - + mActiveScene->SetModified(true); - destroy_sexp(sexp_custom); - destroy_continuation(pcont); + destroy_sexp(mSexpMemory, sexp_custom); + destroy_continuation(mSexpMemory, pcont); } Modified: trunk/spark/plugin/sparkmonitor/sparkmonitorclient.h =================================================================== --- trunk/spark/plugin/sparkmonitor/sparkmonitorclient.h 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/plugin/sparkmonitor/sparkmonitorclient.h 2011-03-26 02:16:36 UTC (rev 264) @@ -72,6 +72,9 @@ /** the root node of the managed scene */ boost::shared_ptr<oxygen::BaseNode> mManagedScene; + + /** the s-expression library memory management object */ + sexp_mem_t *mSexpMemory; }; DECLARE_CLASS(SparkMonitorClient); Modified: trunk/spark/plugin/sparkmonitor/sparkmonitorlogfileserver.cpp =================================================================== --- trunk/spark/plugin/sparkmonitor/sparkmonitorlogfileserver.cpp 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/plugin/sparkmonitor/sparkmonitorlogfileserver.cpp 2011-03-26 02:16:36 UTC (rev 264) @@ -44,10 +44,12 @@ mForwardStep = false; mStepDelay = 0; mBackwardPlayback = false; + mSexpMemory = init_sexp_memory(); } SparkMonitorLogFileServer::~SparkMonitorLogFileServer() { + destroy_sexp_memory(mSexpMemory); } void SparkMonitorLogFileServer::OnLink() @@ -136,7 +138,7 @@ { ParseMessage(msg); } - + #ifdef WIN32 Sleep(mStepDelay / 1000); #else @@ -225,7 +227,7 @@ { return; } - + mActiveScene = mSceneServer->GetActiveScene(); if (mActiveScene.get() == 0) @@ -255,12 +257,12 @@ char* msgBuf = const_cast<char*>(msg.c_str()); pcont_t* pcont = init_continuation(msgBuf); - sexp_t* sexp_custom = iparse_sexp(msgBuf,msg.size(),pcont); + sexp_t* sexp_custom = iparse_sexp(mSexpMemory, msgBuf, msg.size(), pcont); if (sexp_custom == 0) { - destroy_sexp(sexp_custom); - destroy_continuation(pcont); + destroy_sexp(mSexpMemory, sexp_custom); + destroy_continuation(mSexpMemory, pcont); return; } @@ -270,8 +272,8 @@ mManagedScene, boost::shared_ptr<ParameterList>()); - destroy_sexp(sexp_custom); - destroy_continuation(pcont); + destroy_sexp(mSexpMemory, sexp_custom); + destroy_continuation(mSexpMemory, pcont); } void Modified: trunk/spark/plugin/sparkmonitor/sparkmonitorlogfileserver.h =================================================================== --- trunk/spark/plugin/sparkmonitor/sparkmonitorlogfileserver.h 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/plugin/sparkmonitor/sparkmonitorlogfileserver.h 2011-03-26 02:16:36 UTC (rev 264) @@ -114,6 +114,9 @@ /** cached reference to the script server */ boost::shared_ptr<zeitgeist::ScriptServer> mScriptServer; + + /** the s-expression library memory management object */ + sexp_mem_t *mSexpMemory; }; DECLARE_CLASS(SparkMonitorLogFileServer); Modified: trunk/spark/utility/sfsexp/io.c =================================================================== --- trunk/spark/utility/sfsexp/io.c 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/utility/sfsexp/io.c 2011-03-26 02:16:36 UTC (rev 264) @@ -66,17 +66,17 @@ /** * */ -void destroy_iowrap(sexp_iowrap_t *iow) { +void destroy_iowrap(sexp_mem_t *smem, sexp_iowrap_t *iow) { if (iow == NULL) return; /* idiot */ - destroy_continuation(iow->cc); + destroy_continuation(smem, iow->cc); free(iow); } /** * */ -sexp_t *read_one_sexp(sexp_iowrap_t *iow) { +sexp_t *read_one_sexp(sexp_mem_t *smem, sexp_iowrap_t *iow) { sexp_t *sx = NULL; if (iow->cnt == 0) { @@ -84,7 +84,7 @@ if (iow->cnt == 0) return NULL; } - iow->cc = cparse_sexp(iow->buf,iow->cnt,iow->cc); + iow->cc = cparse_sexp(smem, iow->buf,iow->cnt,iow->cc); while (iow->cc->last_sexp == NULL) { if (iow->cc->error != 0) { @@ -97,7 +97,7 @@ if (iow->cnt == 0) return NULL; - iow->cc = cparse_sexp(iow->buf,iow->cnt,iow->cc); + iow->cc = cparse_sexp(smem, iow->buf,iow->cnt,iow->cc); } sx = iow->cc->last_sexp; Modified: trunk/spark/utility/sfsexp/parser.c =================================================================== --- trunk/spark/utility/sfsexp/parser.c 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/utility/sfsexp/parser.c 2011-03-26 02:16:36 UTC (rev 264) @@ -70,48 +70,33 @@ parse_data_t; /** - * parse_data_t stack - similar malloc prevention to sexp_t_cache. - */ -faststack_t *pd_cache; - -/** - * The global <I>sexp_t_cache</I> is a faststack implementing a cache of - * pre-alloced s-expression element entities. Odds are a user should never - * touch this. If you do, you're on your own. This is used internally by - * the parser and related code to store unused but allocated sexp_t elements. - * This should be left alone and manipulated only by the sexp_t_allocate and - * sexp_t_deallocate functions. Touching the stack is bad. - */ -faststack_t *sexp_t_cache; - -/** * sexp_t allocation */ #ifdef _NO_MEMORY_MANAGEMENT_ sexp_t * -sexp_t_allocate() { +sexp_t_allocate(smem) { sexp_t *sx = (sexp_t *) calloc(1, sizeof(sexp_t)); assert(sx != NULL); return(sx); } #else sexp_t * -sexp_t_allocate() { +sexp_t_allocate(sexp_mem_t *smem) { sexp_t *sx; stack_lvl_t *l; - if (sexp_t_cache == NULL) { - sexp_t_cache = make_stack(); + if (smem->sexp_t_cache == NULL) { + smem->sexp_t_cache = make_stack(); sx = (sexp_t *)malloc(sizeof(sexp_t)); assert(sx != NULL); sx->next = sx->list = NULL; } else { - if (empty_stack(sexp_t_cache)) { + if (empty_stack(smem->sexp_t_cache)) { sx = (sexp_t *)malloc(sizeof(sexp_t)); assert(sx != NULL); sx->next = sx->list = NULL; } else { - l = pop(sexp_t_cache); + l = pop(smem->sexp_t_cache); sx = (sexp_t *)l->data; } } @@ -130,8 +115,8 @@ } #else void -sexp_t_deallocate(sexp_t *s) { - if (sexp_t_cache == NULL) sexp_t_cache = make_stack(); +sexp_t_deallocate(sexp_mem_t *smem, sexp_t *s) { + if (smem->sexp_t_cache == NULL) smem->sexp_t_cache = make_stack(); if (s == NULL) return; @@ -142,39 +127,39 @@ s->val = NULL; - sexp_t_cache = push(sexp_t_cache, s); + smem->sexp_t_cache = push(smem->sexp_t_cache, s); } #endif /** * cleanup the sexp library. Note this is implemented HERE since we need - * to know about pd_cache, which is local to this file. + * to know about smem->pd_cache, which is local to this file. */ #ifdef _NO_MEMORY_MANAGEMENT_ void sexp_cleanup() { } #else -void sexp_cleanup() { +void sexp_cleanup(sexp_mem_t *smem) { stack_lvl_t *l; - if (pd_cache != NULL) { - l = pd_cache->top; + if (smem->pd_cache != NULL) { + l = smem->pd_cache->top; while (l != NULL) { free(l->data); l = l->below; } - destroy_stack(pd_cache); - pd_cache = NULL; + destroy_stack(smem->pd_cache); + smem->pd_cache = NULL; } - if (sexp_t_cache != NULL) { - l = sexp_t_cache->top; + if (smem->sexp_t_cache != NULL) { + l = smem->sexp_t_cache->top; while (l != NULL) { free(l->data); l = l->below; } - destroy_stack(sexp_t_cache); - sexp_t_cache = NULL; + destroy_stack(smem->sexp_t_cache); + smem->sexp_t_cache = NULL; } } #endif @@ -183,20 +168,20 @@ * allocation */ parse_data_t * -pd_allocate() { +pd_allocate(sexp_mem_t *smem) { parse_data_t *p; stack_lvl_t *l; - if (pd_cache == NULL) { - pd_cache = make_stack(); + if (smem->pd_cache == NULL) { + smem->pd_cache = make_stack(); p = (parse_data_t *)malloc(sizeof(parse_data_t)); assert(p!=NULL); } else { - if (empty_stack(pd_cache)) { + if (empty_stack(smem->pd_cache)) { p = (parse_data_t *)malloc(sizeof(parse_data_t)); assert(p!=NULL); } else { - l = pop(pd_cache); + l = pop(smem->pd_cache); p = (parse_data_t *)l->data; } } @@ -208,10 +193,10 @@ * de-allocation */ void -pd_deallocate(parse_data_t *p) { - if (pd_cache == NULL) pd_cache = make_stack(); +pd_deallocate(sexp_mem_t *smem, parse_data_t *p) { + if (smem->pd_cache == NULL) smem->pd_cache = make_stack(); - pd_cache = push(pd_cache, p); + smem->pd_cache = push(smem->pd_cache, p); } /** @@ -220,7 +205,7 @@ * buffers, stacks, etc.. */ void -destroy_continuation (pcont_t * pc) +destroy_continuation (sexp_mem_t *smem, pcont_t * pc) { stack_lvl_t *lvl; parse_data_t *lvl_data; @@ -244,11 +229,11 @@ */ if (lvl_data != NULL) { lvl_data->lst = NULL; - destroy_sexp(lvl_data->fst); + destroy_sexp(smem, lvl_data->fst); lvl_data->fst = NULL; /* free(lvl_data); */ - pd_deallocate(lvl_data); + pd_deallocate(smem, lvl_data); lvl->data = lvl_data = NULL; } @@ -283,17 +268,17 @@ * than one will act up. */ sexp_t * -parse_sexp (char *s, int len) +parse_sexp (sexp_mem_t *smem, char *s, int len) { pcont_t *pc = NULL; sexp_t *sx = NULL; if (len < 1 || s == NULL) return NULL; /* empty string - return */ - pc = cparse_sexp (s, len, pc); + pc = cparse_sexp (smem, s, len, pc); sx = pc->last_sexp; - destroy_continuation(pc); + destroy_continuation(smem, pc); return sx; } @@ -343,7 +328,7 @@ * repeated calls. */ sexp_t * -iparse_sexp (char *s, int len, pcont_t *cc) { +iparse_sexp (sexp_mem_t *smem, char *s, int len, pcont_t *cc) { pcont_t *pc; sexp_t *sx = NULL; @@ -356,7 +341,7 @@ } /* call the parser */ - pc = cparse_sexp(s,len,cc); + pc = cparse_sexp(smem, s,len,cc); if (cc->last_sexp != NULL) { sx = cc->last_sexp; @@ -376,7 +361,7 @@ * Continuation based parser - the guts of the package. */ pcont_t * -cparse_sexp (char *str, int len, pcont_t *lc) +cparse_sexp (sexp_mem_t *smem, char *str, int len, pcont_t *lc) { char *t, *s; register unsigned int binexpected = 0; @@ -567,7 +552,7 @@ /* open paren */ depth++; - sx = sexp_t_allocate(); + sx = sexp_t_allocate(smem); assert(sx!=NULL); elts++; sx->ty = SEXP_LIST; @@ -577,7 +562,7 @@ if (stack->height < 1) { - data = pd_allocate(); + data = pd_allocate(smem); assert(data!=NULL); data->fst = data->lst = sx; push (stack, data); @@ -592,7 +577,7 @@ data->lst = sx; } - data = pd_allocate(); + data = pd_allocate(smem); assert(data!=NULL); data->fst = data->lst = NULL; push (stack, data); @@ -637,7 +622,7 @@ data = (parse_data_t *) lvl->data; sx = data->fst; /* free (data); */ - pd_deallocate(data); + pd_deallocate(smem, data); lvl->data = NULL; if (stack->top != NULL) @@ -672,7 +657,7 @@ data = (parse_data_t *) lvl->data; sx = data->fst; /* free (data); */ - pd_deallocate(data); + pd_deallocate(smem, data); lvl->data = NULL; } cc->last_sexp = sx; @@ -707,7 +692,7 @@ vcur[0] = '\0'; val_used++; - sx = sexp_t_allocate(); + sx = sexp_t_allocate(smem); assert(sx!=NULL); elts++; sx->ty = SEXP_VALUE; @@ -839,7 +824,7 @@ vcur[0] = '\0'; val_used++; - sx = sexp_t_allocate(); + sx = sexp_t_allocate(smem); assert(sx!=NULL); elts++; sx->ty = SEXP_VALUE; @@ -994,7 +979,7 @@ { state = 1; vcur[0] = '\0'; - sx = sexp_t_allocate(); + sx = sexp_t_allocate(smem); assert(sx!=NULL); elts++; sx->ty = SEXP_VALUE; @@ -1165,7 +1150,7 @@ if (binread == binexpected) { /* state = 1 -- create a sexp_t and head back */ - sx = sexp_t_allocate(); + sx = sexp_t_allocate(smem); assert(sx!=NULL); elts++; sx->ty = SEXP_VALUE; @@ -1239,7 +1224,7 @@ data = (parse_data_t *) lvl->data; sx = data->fst; /* free (data); */ - pd_deallocate(data); + pd_deallocate(smem, data); lvl->data = NULL; } cc->last_sexp = sx; Modified: trunk/spark/utility/sfsexp/sexp.c =================================================================== --- trunk/spark/utility/sfsexp/sexp.c 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/utility/sfsexp/sexp.c 2011-03-26 02:16:36 UTC (rev 264) @@ -41,27 +41,41 @@ #define snprintf _snprintf #endif +sexp_mem_t *init_sexp_memory() +{ + sexp_mem_t *smem = malloc(sizeof(sexp_mem_t)); + smem->pd_cache = NULL; + smem->sexp_t_cache = NULL; + return smem; +} + +void destroy_sexp_memory(sexp_mem_t *smem) +{ + if (smem) + free(smem); +} + /** * Recursively walk an s-expression and free it. */ void -destroy_sexp (sexp_t * s) +destroy_sexp (sexp_mem_t *smem, sexp_t * s) { if (s == NULL) return; if (s->ty == SEXP_LIST) - destroy_sexp (s->list); + destroy_sexp (smem, s->list); if (s->ty == SEXP_VALUE && s->val != NULL) free(s->val); s->val = NULL; - destroy_sexp (s->next); + destroy_sexp (smem, s->next); s->next = s->list = NULL; - sexp_t_deallocate(s); + sexp_t_deallocate(smem, s); } /** @@ -69,7 +83,7 @@ * representation of the s-expression. Fills the buffer. */ int -print_sexp (char *buf, int size, sexp_t * sx) +print_sexp (sexp_mem_t *smem, char *buf, int size, sexp_t * sx) { int retval; int sz; @@ -86,7 +100,7 @@ return -1; } - fakehead = sexp_t_allocate(); + fakehead = sexp_t_allocate(smem); assert(fakehead!=NULL); /* duplicate the head to prevent going down a sx->next path @@ -302,7 +316,7 @@ } destroy_stack (stack); - sexp_t_deallocate(fakehead); + sexp_t_deallocate(smem, fakehead); return retval; } @@ -312,7 +326,7 @@ * representation of the s-expression. Fills the buffer. */ int -print_sexp_cstr (CSTRING **s, sexp_t *sx, int ss, int gs) +print_sexp_cstr (sexp_mem_t *smem, CSTRING **s, sexp_t *sx, int ss, int gs) { int retval; char *tc; @@ -333,7 +347,7 @@ _s = snew(ss); sgrowsize(gs); - fakehead = sexp_t_allocate(); + fakehead = sexp_t_allocate(smem); assert(fakehead!=NULL); /* duplicate the head to prevent going down a sx->next path @@ -457,7 +471,7 @@ retval = _s->curlen; destroy_stack (stack); - sexp_t_deallocate(fakehead); + sexp_t_deallocate(smem, fakehead); return retval; } @@ -465,8 +479,8 @@ /** * Allocate a new sexp_t element representing a list. */ -sexp_t *new_sexp_list(sexp_t *l) { - sexp_t *sx = sexp_t_allocate(); +sexp_t *new_sexp_list(sexp_mem_t *smem, sexp_t *l) { + sexp_t *sx = sexp_t_allocate(smem); sx->ty = SEXP_LIST; @@ -482,8 +496,8 @@ /** * allocate a new sexp_t element representing a value */ -sexp_t *new_sexp_atom(char *buf, int bs) { - sexp_t *sx = sexp_t_allocate(); +sexp_t *new_sexp_atom(sexp_mem_t *smem, char *buf, int bs) { + sexp_t *sx = sexp_t_allocate(smem); sx->ty = SEXP_VALUE; Modified: trunk/spark/utility/sfsexp/sexp.h =================================================================== --- trunk/spark/utility/sfsexp/sexp.h 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/utility/sfsexp/sexp.h 2011-03-26 02:16:36 UTC (rev 264) @@ -200,6 +200,24 @@ /* STRUCTURES */ /*============*/ +typedef struct sexp_mem +{ + /** + * parse_data_t stack - similar malloc prevention to sexp_t_cache. + */ + faststack_t *pd_cache; + + /** + * The global <I>sexp_t_cache</I> is a faststack implementing a cache of + * pre-alloced s-expression element entities. Odds are a user should never + * touch this. If you do, you're on your own. This is used internally by + * the parser and related code to store unused but allocated sexp_t elements. + * This should be left alone and manipulated only by the sexp_t_allocate and + * sexp_t_deallocate functions. Touching the stack is bad. + */ + faststack_t *sexp_t_cache; +} sexp_mem_t; + /** * An s-expression is represented as a linked structure of elements, * where each element is either an <I>atom</I> or <I>list</I>. An @@ -550,14 +568,14 @@ * sexp_t_deallocate to deallocate them and put them in the pool.</I> * Also, if the stack has not been initialized yet, this does so. */ - sexp_t *sexp_t_allocate(); + sexp_t *sexp_t_allocate(sexp_mem_t *smem); /** * given a malloc'd sexp_t element, put it back into the already-allocated * element stack. This method will allocate a stack if one has not been * allocated already. */ - void sexp_t_deallocate(sexp_t *s); + void sexp_t_deallocate(sexp_mem_t *smem, sexp_t *s); /** * In the event that someone wants us to release ALL of the memory used @@ -565,7 +583,7 @@ * this, the caches will be persistent for the lifetime of the library * user. */ - void sexp_cleanup(); + void sexp_cleanup(sexp_mem_t *smem); /** * print a sexp_t struct as a string in the LISP style. If the buffer @@ -575,7 +593,7 @@ * value is -1 and the contents of the buffer should not be assumed to * contain any useful information. */ - int print_sexp(char *loc, int size, sexp_t *e); + int print_sexp(sexp_mem_t *smem, char *loc, int size, sexp_t *e); /** * print a sexp_t structure to a buffer, growing it as necessary instead @@ -583,17 +601,17 @@ * to tune for performance reasons are <tt>ss</tt> and <tt>gs</tt> - the * buffer start size and growth size. */ - int print_sexp_cstr(CSTRING **s, sexp_t *e, int ss, int gs); + int print_sexp_cstr(sexp_mem_t *smem, CSTRING **s, sexp_t *e, int ss, int gs); /** * Allocate a new sexp_t element representing a list. */ - sexp_t *new_sexp_list(sexp_t *l); + sexp_t *new_sexp_list(sexp_mem_t *smem, sexp_t *l); /** * allocate a new sexp_t element representing a value */ - sexp_t *new_sexp_atom(char *buf, int bs); + sexp_t *new_sexp_atom(sexp_mem_t *smem, char *buf, int bs); /** * create an initial continuation for parsing the given string @@ -604,7 +622,7 @@ * destroy a continuation. This involves cleaning up what it contains, * and cleaning up the continuation itself. */ - void destroy_continuation (pcont_t * pc); + void destroy_continuation (sexp_mem_t *smem, pcont_t * pc); /** * create an IO wrapper structure around a file descriptor. @@ -614,7 +632,7 @@ /** * destroy an IO wrapper structure */ - void destroy_iowrap(sexp_iowrap_t *iow); + void destroy_iowrap(sexp_mem_t *smem, sexp_iowrap_t *iow); /** * given and IO wrapper handle, read one s-expression off of it. this @@ -622,24 +640,24 @@ * guarantee that under the covers an IO read actually is occuring. * returning null implies no s-expression was able to be read. */ - sexp_t *read_one_sexp(sexp_iowrap_t *iow); + sexp_t *read_one_sexp(sexp_mem_t *smem, sexp_iowrap_t *iow); /** * wrapper around parser for compatibility. */ - sexp_t *parse_sexp(char *s, int len); + sexp_t *parse_sexp(sexp_mem_t *smem, char *s, int len); /** * wrapper around parser for friendlier continuation use * pre-condition : continuation (cc) is NON-NULL! */ - sexp_t *iparse_sexp(char *s, int len, pcont_t *cc); + sexp_t *iparse_sexp(sexp_mem_t *smem, char *s, int len, pcont_t *cc); /** * given a LISP style s-expression string, parse it into a set of * connected sexp_t structures. */ - pcont_t *cparse_sexp(char *s, int len, pcont_t *pc); + pcont_t *cparse_sexp(sexp_mem_t *smem, char *s, int len, pcont_t *pc); /** * given a sexp_t structure, free the memory it uses (and recursively free @@ -649,8 +667,11 @@ * pre-allocated elements. This is an optimization to speed up the * parser to eliminate wasteful free and re-malloc calls. */ - void destroy_sexp(sexp_t *s); + void destroy_sexp(sexp_mem_t *smem, sexp_t *s); + sexp_mem_t *init_sexp_memory(); + void destroy_sexp_memory(sexp_mem_t *smem); + /* this is for C++ users */ #ifdef __cplusplus } Modified: trunk/spark/utility/sfsexp/sexp_ops.c =================================================================== --- trunk/spark/utility/sfsexp/sexp_ops.c 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/utility/sfsexp/sexp_ops.c 2011-03-26 02:16:36 UTC (rev 264) @@ -121,12 +121,12 @@ /** * Copy an s-expression. */ -sexp_t *copy_sexp(sexp_t *s) { +sexp_t *copy_sexp(sexp_mem_t *smem, sexp_t *s) { sexp_t *snew; if (s == NULL) return NULL; - snew = sexp_t_allocate(); + snew = sexp_t_allocate(smem); assert(snew != NULL); snew->ty = s->ty; @@ -143,11 +143,11 @@ strcpy(snew->val,s->val); snew->list = NULL; } else { - snew->list = copy_sexp(s->list); + snew->list = copy_sexp(smem, s->list); } snew->line = s->line; - snew->next = copy_sexp(s->next); + snew->next = copy_sexp(smem, s->next); return snew; } @@ -156,31 +156,31 @@ * Cons: Concatenate two s-expressions together, without references to the * originals. */ -sexp_t *cons_sexp(sexp_t *r, sexp_t *l) { +sexp_t *cons_sexp(sexp_mem_t *smem, sexp_t *r, sexp_t *l) { sexp_t *cr, *cl, *t; - cr = copy_sexp(r); + cr = copy_sexp(smem, r); if (cr->ty == SEXP_VALUE) { fprintf(stderr,"Cannot cons non-lists.\n"); - destroy_sexp(cr); + destroy_sexp(smem, cr); return NULL; } else { t = cr->list; while (t != NULL && t->next != NULL) t = t->next; } - cl = copy_sexp(l); + cl = copy_sexp(smem, l); if (cl->ty == SEXP_LIST) { if (t != NULL && cl != NULL) { t->next = cl->list; /* free(cl); */ /* memory leak fix: SMJ, 4/24/2002 */ - sexp_t_deallocate(cl); + sexp_t_deallocate(smem, cl); } } else { fprintf(stderr,"Cannot cons non-lists.\n"); - destroy_sexp(cr); - destroy_sexp(cl); + destroy_sexp(smem, cr); + destroy_sexp(smem, cl); return NULL; } @@ -190,7 +190,7 @@ /** * car: similar to head, except this is a copy and not just a reference. */ -sexp_t *car_sexp(sexp_t *s) { +sexp_t *car_sexp(sexp_mem_t *smem, sexp_t *s) { sexp_t *cr, *ocr; /* really dumb - calling on null */ @@ -206,14 +206,14 @@ } /* ocr = (sexp_t *)malloc(sizeof(sexp_t));*/ - ocr = sexp_t_allocate(); + ocr = sexp_t_allocate(smem); assert(ocr != NULL); ocr->ty = SEXP_LIST; ocr->next = NULL; /* allocate the new sexp_t */ /* cr = (sexp_t *)malloc(sizeof(sexp_t)); */ - cr = sexp_t_allocate(); + cr = sexp_t_allocate(smem); assert(cr != NULL); ocr->list = cr; @@ -226,7 +226,7 @@ } else { cr->ty = SEXP_LIST; cr->next = NULL; - cr->list = copy_sexp(s->list->list); + cr->list = copy_sexp(smem, s->list->list); } return ocr; @@ -235,7 +235,7 @@ /** * cdr: similar to tail, except this is a copy and not just a reference. */ -sexp_t *cdr_sexp(sexp_t *s) { +sexp_t *cdr_sexp(sexp_mem_t *smem, sexp_t *s) { sexp_t *cd; /* really dumb */ @@ -251,12 +251,12 @@ } /* cd = (sexp_t *)malloc(sizeof(sexp_t)); */ - cd = sexp_t_allocate(); + cd = sexp_t_allocate(smem); assert(cd != NULL); cd->ty = SEXP_LIST; cd->next = NULL; - cd->list = copy_sexp(s->list->next); + cd->list = copy_sexp(smem, s->list->next); cd->line = s->line; return cd; } Modified: trunk/spark/utility/sfsexp/sexp_ops.h =================================================================== --- trunk/spark/utility/sfsexp/sexp_ops.h 2011-03-25 22:43:15 UTC (rev 263) +++ trunk/spark/utility/sfsexp/sexp_ops.h 2011-03-26 02:16:36 UTC (rev 264) @@ -47,22 +47,22 @@ /*========*/ /* MACROS */ /*========*/ - + /** * Return the head of a list \a s by reference, not copy. */ #define hd_sexp(s) ((s)->list) - + /** * Return the tail of a list \a s by reference, not copy. */ -#define tl_sexp(s) ((s)->list->next) - +#define tl_sexp(s) ((s)->list->next) + /** * Return the element following the argument \a s. */ #define next_sexp(s) ((s)->next) - + /** * Reset the continuation \a c by setting the \c lastPos pointer to * \c NULL. @@ -71,11 +71,11 @@ /** * Find an atom in a sexpression data structure and return a pointer to - * it. Return NULL if the string doesn't occur anywhere as an atom. + * it. Return NULL if the string doesn't occur anywhere as an atom. * This is a depth-first search algorithm. */ sexp_t *find_sexp(char *name, sexp_t *start); - + /** * Breadth first search for s-expressions. Depth first search will find * the first occurance of a string in an s-expression by basically finding @@ -93,30 +93,30 @@ * to the end of the ->next linked list from that point. */ int sexp_list_length(sexp_t *sx); - + /** * Copy an s-expression. This is a deep copy - so the resulting s-expression * shares no pointers with the original. The new one can be changed without * damaging the contents of the original. */ - sexp_t *copy_sexp(sexp_t *s); - + sexp_t *copy_sexp(sexp_mem_t *smem, sexp_t *s); + /** * Cons: Concatenate two s-expressions together, without references to the * originals. */ - sexp_t *cons_sexp(sexp_t *r, sexp_t *l); - + sexp_t *cons_sexp(sexp_mem_t *smem, sexp_t *r, sexp_t *l); + /** * car: Like hd(), but returning a copy of the head, not a reference to it. */ - sexp_t *car_sexp(sexp_t *s); - + sexp_t *car_sexp(sexp_mem_t *smem, sexp_t *s); + /** * cdr: Like tl(), but returning a copy of the tail, not a reference to it. */ - sexp_t *cdr_sexp(sexp_t *s); - + sexp_t *cdr_sexp(sexp_mem_t *smem, sexp_t *s); + #ifdef __cplusplus } #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |