![]() |
RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* js_wrapped.cc 00002 Jeremy Barnes, 15 July 2010 00003 Copyright (c) 2010 Datacratic. All rights reserved. 00004 00005 Implementation of javascript wrapper. 00006 00007 Some code is from node_object_wrap.h, from node.js. Its license is 00008 included here: 00009 00010 Copyright 2009, 2010 Ryan Lienhart Dahl. All rights reserved. 00011 Permission is hereby granted, free of charge, to any person obtaining a copy 00012 of this software and associated documentation files (the "Software"), to 00013 deal in the Software without restriction, including without limitation the 00014 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 00015 sell copies of the Software, and to permit persons to whom the Software is 00016 furnished to do so, subject to the following conditions: 00017 00018 The above copyright notice and this permission notice shall be included in 00019 all copies or substantial portions of the Software. 00020 00021 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00022 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00023 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00024 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00025 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00026 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 00027 IN THE SOFTWARE. 00028 */ 00029 00030 #include "js_wrapped.h" 00031 #include <iostream> 00032 00033 00034 using namespace std; 00035 using namespace v8; 00036 00037 00038 namespace Datacratic { 00039 namespace JS { 00040 00041 00042 const std::type_info & getWrapperTypeInfo(v8::Handle<v8::Value> handle) 00043 { 00044 ExcAssert(!handle.IsEmpty()); 00045 ExcAssert(handle->IsObject()); 00046 00047 v8::Handle<v8::Object> object(v8::Object::Cast(*handle)); 00048 00049 ExcAssert(object->InternalFieldCount() == 2); 00050 00051 return *static_cast<const std::type_info *> 00052 (v8::Handle<v8::External>::Cast 00053 (object->GetInternalField(1))->Value()); 00054 } 00055 00056 00057 00058 /*****************************************************************************/ 00059 /* JSWRAPPEDBASE */ 00060 /*****************************************************************************/ 00061 00062 JSWrappedBase:: 00063 ~JSWrappedBase () 00064 { 00065 if (js_object_.IsEmpty()) return; 00066 ExcAssert(js_object_.IsNearDeath()); 00067 js_object_->SetInternalField(0, v8::Undefined()); 00068 js_object_->SetInternalField(1, v8::Undefined()); 00069 js_object_.Dispose(); 00070 js_object_.Clear(); 00071 } 00072 00073 void 00074 JSWrappedBase:: 00075 wrap(v8::Handle<v8::Object> handle, 00076 size_t size_in_bytes, 00077 const std::type_info & wrappedType) 00078 { 00079 size_in_bytes_ = size_in_bytes; 00080 ExcAssert(js_object_.IsEmpty()); 00081 00082 if (handle->InternalFieldCount() == 0) { 00083 throw ML::Exception("InternalFieldCount is zero; are you forgetting " 00084 "to use 'new' for " + getJsTypeName()); 00085 } 00086 00087 ExcAssert(handle->InternalFieldCount() == 2); 00088 00089 js_object_ = v8::Persistent<v8::Object>::New(handle); 00090 js_object_->SetInternalField(0, v8::External::New(this)); 00091 js_object_->SetInternalField(1, v8::External::New((void *)&wrappedType)); 00092 v8::V8::AdjustAmountOfExternalAllocatedMemory(size_in_bytes); 00093 registerForGarbageCollection(); 00094 } 00095 00096 void 00097 JSWrappedBase:: 00098 registerForGarbageCollection() 00099 { 00100 js_object_.MakeWeak(this, getGarbageCollectionCallback()); 00101 } 00102 00103 void 00104 JSWrappedBase:: 00105 ref() 00106 { 00107 ExcAssert(!js_object_.IsEmpty()); 00108 refs_++; 00109 js_object_.ClearWeak(); 00110 } 00111 00112 void 00113 JSWrappedBase:: 00114 unref() 00115 { 00116 ExcAssert(!js_object_.IsEmpty()); 00117 ExcAssert(!js_object_.IsWeak()); 00118 ExcAssert(refs_ > 0); 00119 if (--refs_ == 0) { registerForGarbageCollection(); } 00120 } 00121 00122 void 00123 JSWrappedBase:: 00124 dispose() 00125 { 00126 //cerr << "disposing of " << ML::type_name(*this) << " at " << this 00127 // << endl; 00128 delete this; 00129 } 00130 00131 v8::WeakReferenceCallback 00132 JSWrappedBase:: 00133 getGarbageCollectionCallback() const 00134 { 00135 return garbageCollectionCallback; 00136 } 00137 00138 void 00139 JSWrappedBase:: 00140 garbageCollectionCallback(v8::Persistent<v8::Value> value, void * data) 00141 { 00142 try { 00143 JSWrappedBase * obj = reinterpret_cast<JSWrappedBase *>(data); 00144 ExcAssert(value == obj->js_object_); 00145 ExcAssert(!obj->refs_); 00146 if (value.IsNearDeath()) { 00147 v8::V8::AdjustAmountOfExternalAllocatedMemory(-obj->size_in_bytes_); 00148 obj->size_in_bytes_ = 0; 00149 obj->dispose(); 00150 } 00151 } catch (const std::exception & exc) { 00152 cerr << "WARNING: exception thrown in GC: " << exc.what() << endl; 00153 } catch (...) { 00154 cerr << "WARNING: exception thrown in GC: unknown" << endl; 00155 } 00156 } 00157 00158 } // namespace JS 00159 } // namespace Datacratic