diff options
Diffstat (limited to 'scripting')
-rw-r--r-- | scripting/engine.cpp | 39 | ||||
-rw-r--r-- | scripting/engine.h | 1 | ||||
-rw-r--r-- | scripting/engine_spidermonkey.cpp | 21 |
3 files changed, 53 insertions, 8 deletions
diff --git a/scripting/engine.cpp b/scripting/engine.cpp index 5d783160431..d34b90aa578 100644 --- a/scripting/engine.cpp +++ b/scripting/engine.cpp @@ -50,15 +50,19 @@ namespace mongo { class ScopeCache { public: + + ScopeCache(){ + _magic = 17; + } ~ScopeCache(){ + assert( _magic == 17 ); + _magic = 1; + if ( inShutdown() ) return; - - for ( PoolToScopes::iterator i=_pools.begin() ; i != _pools.end(); i++ ){ - for ( list<Scope*>::iterator j=i->second.begin(); j != i->second.end(); j++ ) - delete *j; - } + + clear(); } void done( const string& pool , Scope * s ){ @@ -84,10 +88,26 @@ namespace mongo { s->reset(); return s; } + + void clear(){ + set<Scope*> seen; + + for ( PoolToScopes::iterator i=_pools.begin() ; i != _pools.end(); i++ ){ + for ( list<Scope*>::iterator j=i->second.begin(); j != i->second.end(); j++ ){ + Scope * s = *j; + assert( ! seen.count( s ) ); + delete s; + seen.insert( s ); + } + } + + _pools.clear(); + } private: PoolToScopes _pools; mutex _mutex; + int _magic; }; thread_specific_ptr<ScopeCache> scopeCache; @@ -191,11 +211,18 @@ namespace mongo { if ( ! s ){ s = createScope(); } - + auto_ptr<Scope> p; p.reset( new PooledScope( pool , s ) ); return p; } + void ScriptEngine::threadDone(){ + ScopeCache * sc = scopeCache.get(); + if ( sc ){ + sc->clear(); + } + } + ScriptEngine * globalScriptEngine; } diff --git a/scripting/engine.h b/scripting/engine.h index 5e0e452c8d8..8475d52c950 100644 --- a/scripting/engine.h +++ b/scripting/engine.h @@ -78,6 +78,7 @@ namespace mongo { static void setup(); auto_ptr<Scope> getPooledScope( const string& pool ); + void threadDone(); }; extern ScriptEngine * globalScriptEngine; diff --git a/scripting/engine_spidermonkey.cpp b/scripting/engine_spidermonkey.cpp index 1379b8f2783..70d0785b78a 100644 --- a/scripting/engine_spidermonkey.cpp +++ b/scripting/engine_spidermonkey.cpp @@ -12,8 +12,8 @@ namespace mongo { boost::thread_specific_ptr<SMScope> currentScope( dontDeleteScope ); - boost::mutex smmutex; -#define smlock boostlock ___lk( smmutex ); + boost::recursive_mutex smmutex; +#define smlock recursive_boostlock ___lk( smmutex ); #define GETHOLDER(x,o) ((BSONHolder*)JS_GetPrivate( x , o )) @@ -921,6 +921,7 @@ namespace mongo { } void init( BSONObj * data ){ + smlock; if ( ! data ) return; @@ -934,6 +935,7 @@ namespace mongo { } void externalSetup(){ + smlock; uassert( "already local connected" , ! _localConnect ); if ( _externalSetup ) return; @@ -942,6 +944,7 @@ namespace mongo { } void localConnect( const char * dbName ){ + smlock; uassert( "already setup for external db" , ! _externalSetup ); if ( _localConnect ){ uassert( "connected to different db" , _dbName == dbName ); @@ -959,12 +962,14 @@ namespace mongo { // ----- getters ------ double getNumber( const char *field ){ + smlock; jsval val; assert( JS_GetProperty( _context , _global , field , &val ) ); return _convertor->toNumber( val ); } string getString( const char *field ){ + smlock; jsval val; assert( JS_GetProperty( _context , _global , field , &val ) ); JSString * s = JS_ValueToString( _context , val ); @@ -972,18 +977,22 @@ namespace mongo { } bool getBoolean( const char *field ){ + smlock; return _convertor->getBoolean( _global , field ); } BSONObj getObject( const char *field ){ + smlock; return _convertor->toObject( _convertor->getProperty( _global , field ) ); } JSObject * getJSObject( const char * field ){ + smlock; return _convertor->getJSObject( _global , field ); } int type( const char *field ){ + smlock; jsval val; assert( JS_GetProperty( _context , _global , field , &val ) ); @@ -1013,26 +1022,31 @@ namespace mongo { // ----- setters ------ void setNumber( const char *field , double val ){ + smlock; jsval v = _convertor->toval( val ); assert( JS_SetProperty( _context , _global , field , &v ) ); } void setString( const char *field , const char * val ){ + smlock; jsval v = _convertor->toval( val ); assert( JS_SetProperty( _context , _global , field , &v ) ); } void setObject( const char *field , const BSONObj& obj , bool readOnly ){ + smlock; jsval v = _convertor->toval( &obj , readOnly ); JS_SetProperty( _context , _global , field , &v ); } void setBoolean( const char *field , bool val ){ + smlock; jsval v = BOOLEAN_TO_JSVAL( val ); assert( JS_SetProperty( _context , _global , field , &v ) ); } void setThis( const BSONObj * obj ){ + smlock; if ( _this ) JS_RemoveRoot( _context , &_this ); @@ -1044,6 +1058,7 @@ namespace mongo { // ---- functions ----- ScriptingFunction createFunction( const char * code ){ + smlock; precall(); return (ScriptingFunction)_convertor->compileFunction( code ); } @@ -1091,6 +1106,7 @@ namespace mongo { } bool exec( const string& code , const string& name = "(anon)" , bool printResult = false , bool reportError = true , bool assertOnError = true, int timeoutMs = 0 ){ + smlock; precall(); jsval ret = JSVAL_VOID; @@ -1156,6 +1172,7 @@ namespace mongo { } void injectNative( const char *field, NativeFunction func ){ + smlock; string name = field; _convertor->setProperty( _global , (name + "_").c_str() , PRIVATE_TO_JSVAL( func ) ); |