diff options
author | David Percy <david.percy@mongodb.com> | 2014-12-08 11:51:39 -0500 |
---|---|---|
committer | David Percy <david.percy@mongodb.com> | 2014-12-12 15:24:57 -0500 |
commit | 3f5b7737b18294c39aba78e84e45fb5e41bb706b (patch) | |
tree | 0da4c464259842dad25051fecf4a3fc3e695b748 | |
parent | de3b0d465b342e3a5cef629b46f3cf00b742bfd9 (diff) | |
download | mongo-3f5b7737b18294c39aba78e84e45fb5e41bb706b.tar.gz |
SERVER-16196 Port CountDownLatch to v8-3.25
-rw-r--r-- | src/mongo/scripting/v8-3.25_utils.cpp | 97 | ||||
-rw-r--r-- | src/mongo/scripting/v8_utils.cpp | 39 |
2 files changed, 114 insertions, 22 deletions
diff --git a/src/mongo/scripting/v8-3.25_utils.cpp b/src/mongo/scripting/v8-3.25_utils.cpp index 016d90834b4..1b10c8e601b 100644 --- a/src/mongo/scripting/v8-3.25_utils.cpp +++ b/src/mongo/scripting/v8-3.25_utils.cpp @@ -32,6 +32,8 @@ #include "mongo/scripting/v8-3.25_utils.h" #include <boost/smart_ptr.hpp> +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/mutex.hpp> #include <boost/thread/thread.hpp> #include <boost/thread/xtime.hpp> #include <iostream> @@ -240,6 +242,94 @@ namespace mongo { shared_ptr<SharedData> _sharedData; }; + class CountDownLatchHolder { + private: + struct Latch { + Latch(int32_t count) : count(count) {} + boost::condition_variable cv; + boost::mutex mutex; + int32_t count; + }; + + boost::shared_ptr<Latch> get(int32_t desc) { + boost::lock_guard<boost::mutex> lock(mutex); + Map::iterator iter = _latches.find(desc); + jsassert(iter != _latches.end(), "not a valid CountDownLatch descriptor"); + return iter->second; + } + + typedef std::map< int32_t, boost::shared_ptr<Latch> > Map; + Map _latches; + boost::mutex _mutex; + int32_t _counter; + public: + CountDownLatchHolder() : _counter(0) {} + int32_t make(int32_t count) { + jsassert(count >= 0, "argument must be >= 0"); + boost::lock_guard<boost::mutex> lock(_mutex); + int32_t desc = ++_counter; + _latches.insert(std::make_pair(desc, boost::make_shared<Latch>(count))); + return desc; + } + void await(int32_t desc) { + boost::shared_ptr<Latch> latch = get(desc); + boost::unique_lock<boost::mutex> lock(latch->mutex); + while (latch->count != 0) { + latch->cv.wait(lock); + } + } + void countDown(int32_t desc) { + boost::shared_ptr<Latch> latch = get(desc); + boost::unique_lock<boost::mutex> lock(latch->mutex); + if (latch->count > 0) { + latch->count--; + } + if (latch->count == 0) { + latch->cv.notify_all(); + } + } + int32_t getCount(int32_t desc) { + boost::shared_ptr<Latch> latch = get(desc); + boost::unique_lock<boost::mutex> lock(latch->mutex); + return latch->count; + } + }; + namespace { + CountDownLatchHolder globalCountDownLatchHolder; + } + + v8::Local<v8::Value> CountDownLatchNew(V8Scope* scope, + const v8::FunctionCallbackInfo<v8::Value>& args) { + jsassert(args.Length() == 1, "need exactly one argument"); + jsassert(args[0]->IsInt32(), "argument must be an integer"); + int32_t count = v8::Local<v8::Integer>::Cast(args[0])->Value(); + return v8::Int32::New(scope->getIsolate(), globalCountDownLatchHolder.make(count)); + } + + v8::Local<v8::Value> CountDownLatchAwait(V8Scope* scope, + const v8::FunctionCallbackInfo<v8::Value>& args) { + jsassert(args.Length() == 1, "need exactly one argument"); + jsassert(args[0]->IsInt32(), "argument must be an integer"); + globalCountDownLatchHolder.await(args[0]->ToInt32()->Value()); + return v8::Undefined(scope->getIsolate()); + } + + v8::Local<v8::Value> CountDownLatchCountDown(V8Scope* scope, + const v8::FunctionCallbackInfo<v8::Value>& args) { + jsassert(args.Length() == 1, "need exactly one argument"); + jsassert(args[0]->IsInt32(), "argument must be an integer"); + globalCountDownLatchHolder.countDown(args[0]->ToInt32()->Value()); + return v8::Undefined(scope->getIsolate()); + } + + v8::Local<v8::Value> CountDownLatchGetCount(V8Scope* scope, + const v8::FunctionCallbackInfo<v8::Value>& args) { + jsassert(args.Length() == 1, "need exactly one argument"); + jsassert(args[0]->IsInt32(), "argument must be an integer"); + return v8::Int32::New(scope->getIsolate(), + globalCountDownLatchHolder.getCount(args[0]->ToInt32()->Value())); + } + JSThreadConfig *thisConfig(V8Scope* scope, const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Local<v8::External> c = v8::Local<v8::External>::Cast( args.This()->GetHiddenValue(v8::String::NewFromUtf8(scope->getIsolate(), @@ -325,6 +415,13 @@ namespace mongo { v8::Local<v8::Context> context) { scope->injectV8Function("_threadInject", ThreadInject, global); scope->injectV8Function("_scopedThreadInject", ScopedThreadInject, global); + + scope->setObject("CountDownLatch", BSONObj(), false); + v8::Handle<v8::Object> cdl = scope->get("CountDownLatch").As<v8::Object>(); + scope->injectV8Function("_new", CountDownLatchNew, cdl); + scope->injectV8Function("_await", CountDownLatchAwait, cdl); + scope->injectV8Function("_countDown", CountDownLatchCountDown, cdl); + scope->injectV8Function("_getCount", CountDownLatchGetCount, cdl); } v8::Local<v8::Value> v8AssertionException(const char* errorMessage) { diff --git a/src/mongo/scripting/v8_utils.cpp b/src/mongo/scripting/v8_utils.cpp index e0113c07894..5d859998e0e 100644 --- a/src/mongo/scripting/v8_utils.cpp +++ b/src/mongo/scripting/v8_utils.cpp @@ -248,39 +248,34 @@ namespace mongo { int32_t count; }; - boost::shared_ptr<Latch> get(string desc) { + boost::shared_ptr<Latch> get(int32_t desc) { boost::lock_guard<boost::mutex> lock(mutex); Map::iterator iter = _latches.find(desc); jsassert(iter != _latches.end(), "not a valid CountDownLatch descriptor"); return iter->second; } - typedef map< string, boost::shared_ptr<Latch> > Map; + typedef std::map< int32_t, boost::shared_ptr<Latch> > Map; Map _latches; boost::mutex _mutex; int32_t _counter; public: CountDownLatchHolder() : _counter(0) {} - string make(int32_t count) { + int32_t make(int32_t count) { + jsassert(count >= 0, "argument must be >= 0"); boost::lock_guard<boost::mutex> lock(_mutex); - int32_t id = ++_counter; - string desc; - { - stringstream ss; - ss << "latch" << id; - desc = ss.str(); - } - _latches.insert(make_pair(desc, boost::make_shared<Latch>(count))); + int32_t desc = ++_counter; + _latches.insert(std::make_pair(desc, boost::make_shared<Latch>(count))); return desc; } - void await(string desc) { + void await(int32_t desc) { boost::shared_ptr<Latch> latch = get(desc); boost::unique_lock<boost::mutex> lock(latch->mutex); while (latch->count != 0) { latch->cv.wait(lock); } } - void countDown(string desc) { + void countDown(int32_t desc) { boost::shared_ptr<Latch> latch = get(desc); boost::unique_lock<boost::mutex> lock(latch->mutex); if (latch->count > 0) { @@ -290,7 +285,7 @@ namespace mongo { latch->cv.notify_all(); } } - int32_t getCount(string desc) { + int32_t getCount(int32_t desc) { boost::shared_ptr<Latch> latch = get(desc); boost::unique_lock<boost::mutex> lock(latch->mutex); return latch->count; @@ -302,29 +297,29 @@ namespace mongo { v8::Handle<v8::Value> CountDownLatchNew(V8Scope* scope, const v8::Arguments& args) { jsassert(args.Length() == 1, "need exactly one argument"); - jsassert(args[0]->IsInt32(), "argument must be an int32"); + jsassert(args[0]->IsInt32(), "argument must be an integer"); int32_t count = v8::Local<v8::Integer>::Cast(args[0])->Value(); - return v8::String::New(globalCountDownLatchHolder.make(count).c_str()); + return v8::Int32::New(globalCountDownLatchHolder.make(count)); } v8::Handle<v8::Value> CountDownLatchAwait(V8Scope* scope, const v8::Arguments& args) { jsassert(args.Length() == 1, "need exactly one argument"); - jsassert(args[0]->IsString(), "argument must be a string"); - globalCountDownLatchHolder.await(toSTLString(args[0])); + jsassert(args[0]->IsInt32(), "argument must be an integer"); + globalCountDownLatchHolder.await(args[0]->ToInt32()->Value()); return v8::Undefined(); } v8::Handle<v8::Value> CountDownLatchCountDown(V8Scope* scope, const v8::Arguments& args) { jsassert(args.Length() == 1, "need exactly one argument"); - jsassert(args[0]->IsString(), "argument must be a string"); - globalCountDownLatchHolder.countDown(toSTLString(args[0])); + jsassert(args[0]->IsInt32(), "argument must be an integer"); + globalCountDownLatchHolder.countDown(args[0]->ToInt32()->Value()); return v8::Undefined(); } v8::Handle<v8::Value> CountDownLatchGetCount(V8Scope* scope, const v8::Arguments& args) { jsassert(args.Length() == 1, "need exactly one argument"); - jsassert(args[0]->IsString(), "argument must be a string"); - return v8::Int32::New(globalCountDownLatchHolder.getCount(toSTLString(args[0]))); + jsassert(args[0]->IsInt32(), "argument must be an integer"); + return v8::Int32::New(globalCountDownLatchHolder.getCount(args[0]->ToInt32()->Value())); } JSThreadConfig *thisConfig(V8Scope* scope, const v8::Arguments& args) { |