summaryrefslogtreecommitdiff
path: root/scripting
diff options
context:
space:
mode:
Diffstat (limited to 'scripting')
-rw-r--r--scripting/engine.cpp39
-rw-r--r--scripting/engine.h1
-rw-r--r--scripting/engine_spidermonkey.cpp21
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 ) );