diff options
author | Chad Austin <chad@imvu.com> | 2013-03-12 18:37:24 -0700 |
---|---|---|
committer | Jukka Jylänki <jujjyl@gmail.com> | 2013-04-12 14:25:48 +0300 |
commit | 7c49e9f8866314d688b07f99abb34ccdac442db3 (patch) | |
tree | e6f8cd72b7f922d6bf170bdee46a765f908e3adc | |
parent | de9a8d6fecd4f699b2f80d908c8c597dcc8f04bc (diff) |
:O it works. Use a sharing policy approach to autocasting pointers.
-rwxr-xr-x | src/embind/embind.js | 49 | ||||
-rwxr-xr-x | system/include/emscripten/bind.h | 91 |
2 files changed, 101 insertions, 39 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index 82b9c5d4..c52c6e4d 100755 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -482,8 +482,10 @@ function RegisteredPointer( isReference, isConst, isSmartPointer, + sharingPolicy, rawGetPointee, rawConstructor, + rawShare, rawDestructor ) { this.name = name; @@ -494,8 +496,10 @@ function RegisteredPointer( this.isReference = isReference; this.isConst = isConst; this.isSmartPointer = isSmartPointer; + this.sharingPolicy = sharingPolicy; this.rawGetPointee = rawGetPointee; this.rawConstructor = rawConstructor; + this.rawShare = rawShare; this.rawDestructor = rawDestructor; } @@ -511,7 +515,7 @@ RegisteredPointer.prototype.toWireType = function(destructors, handle) { } if (this.isSmartPointer) { - var ptr = this.rawConstructor(0, 0); + var ptr = this.rawConstructor(); destructors.push(this.rawDestructor, ptr); return ptr; } else { @@ -538,14 +542,30 @@ RegisteredPointer.prototype.toWireType = function(destructors, handle) { } var ptr = staticPointerCast(handle.$$.ptr, fromRawType, this.pointeeType.rawType); if (this.isSmartPointer) { - // If this is for smart ptr type conversion, I think it - // assumes that smart_ptr<T> has an identical binary layout to - // smart_ptr<U>. I wonder if that's untrue for any common - // smart pointer. - chad - ptr = this.rawConstructor( - ptr, - handle.$$.smartPtr); - destructors.push(this.rawDestructor, ptr); + switch (this.sharingPolicy) { + case 0: // NONE + throwBindingError('NONE sharing policy not yet supported'); + break; + + case 1: // INTRUSIVE + throwBindingError('INTRUSIVE sharing policy not yet supported'); + break; + + case 2: // BY_EMVAL + var clonedHandle = handle.clone(); + ptr = this.rawShare( + ptr, + __emval_register(function() { + clonedHandle.delete(); + }) + ); + destructors.push(this.rawDestructor, ptr); + break; + + default: + throwBindingError('Unsupporting sharing policy'); + + } } return ptr; }; @@ -932,14 +952,17 @@ function __embind_register_smart_ptr( rawType, rawPointeeType, name, + sharingPolicy, + rawGetPointee, rawConstructor, - rawDestructor, - rawGetPointee + rawShare, + rawDestructor ) { name = Pointer_stringify(name); + rawGetPointee = FUNCTION_TABLE[rawGetPointee]; rawConstructor = FUNCTION_TABLE[rawConstructor]; + rawShare = FUNCTION_TABLE[rawShare]; rawDestructor = FUNCTION_TABLE[rawDestructor]; - rawGetPointee = FUNCTION_TABLE[rawGetPointee]; whenDependentTypesAreResolved([rawPointeeType], function(pointeeType) { pointeeType = pointeeType[0]; @@ -1001,8 +1024,10 @@ function __embind_register_smart_ptr( false, false, true, + sharingPolicy, rawGetPointee, rawConstructor, + rawShare, rawDestructor); registerType(rawType, registeredPointer); pointeeType.smartPointerType = registeredPointer; diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index e3593196..6f6a6255 100755 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -11,6 +11,12 @@ #include <emscripten/wire.h> namespace emscripten { + enum class sharing_policy { + NONE = 0, + INTRUSIVE = 1, + BY_EMVAL = 2, + }; + namespace internal { typedef void (*GenericFunction)(); typedef long GenericEnumValue; @@ -97,9 +103,11 @@ namespace emscripten { TYPEID pointerType, TYPEID pointeeType, const char* pointerName, + sharing_policy sharingPolicy, + GenericFunction getPointee, GenericFunction constructor, - GenericFunction destructor, - GenericFunction getPointee); + GenericFunction share, + GenericFunction destructor); void _embind_register_class( TYPEID classType, @@ -524,38 +532,62 @@ namespace emscripten { // SMART POINTERS //////////////////////////////////////////////////////////////////////////////// + template<typename PointerType> + struct default_smart_ptr_trait { + static sharing_policy get_sharing_policy() { + return sharing_policy::NONE; + } + + static void* share(void* v) { + return 0; // no sharing + } + }; + // specialize if you have a different pointer type template<typename PointerType> - struct smart_ptr_trait { + struct smart_ptr_trait : public default_smart_ptr_trait<PointerType> { typedef typename PointerType::element_type element_type; static element_type* get(const PointerType& ptr) { return ptr.get(); } + }; + + template<typename PointeeType> + struct smart_ptr_trait<std::shared_ptr<PointeeType>> { + typedef std::shared_ptr<PointeeType> PointerType; + typedef typename PointerType::element_type element_type; - static PointerType share(const PointerType& r, element_type* ptr) { - return PointerType(r, ptr); + static element_type* get(const PointerType& ptr) { + return ptr.get(); } - }; - namespace internal { - template<typename SmartPointerType> - SmartPointerType* raw_smart_pointer_constructor( - typename smart_ptr_trait<SmartPointerType>::element_type* ptr, - SmartPointerType* basePtr - ) { - if (ptr) { - return new SmartPointerType(smart_ptr_trait<SmartPointerType>::share(*basePtr, ptr)); - } else { - return new SmartPointerType; - } + static sharing_policy get_sharing_policy() { + return sharing_policy::BY_EMVAL; } - template<typename PointerType> - typename smart_ptr_trait<PointerType>::element_type* get_pointee(const PointerType& ptr) { - return smart_ptr_trait<PointerType>::get(ptr); + static std::shared_ptr<PointeeType>* share(PointeeType* p, internal::EM_VAL v) { + return new std::shared_ptr<PointeeType>( + p, + val_deleter(val::take_ownership(v))); } - } + + private: + class val_deleter { + public: + val_deleter() = delete; + explicit val_deleter(val v) + : v(v) + {} + void operator()(void const*) { + v(); + // eventually we'll need to support emptied out val + v = val::undefined(); + } + private: + val v; + }; + }; //////////////////////////////////////////////////////////////////////////////// // CLASSES @@ -689,17 +721,22 @@ namespace emscripten { template<typename PointerType> class_& smart_ptr() { using namespace internal; - typedef typename smart_ptr_trait<PointerType>::element_type PointeeType; - + // TODO: assert that PointeeType is identical to ClassType + typedef smart_ptr_trait<PointerType> PointerTrait; + typedef typename PointerTrait::element_type PointeeType; + + _embind_register_smart_ptr( TypeID<PointerType>::get(), TypeID<PointeeType>::get(), - "SmartPtr", // TODO: generate unique name - reinterpret_cast<GenericFunction>(&raw_smart_pointer_constructor<PointerType>), - reinterpret_cast<GenericFunction>(&raw_destructor<PointerType>), - reinterpret_cast<GenericFunction>(&get_pointee<PointerType>)); + "SmartPtr", // TODO: generate unique name, if one is needed at all + PointerTrait::get_sharing_policy(), + reinterpret_cast<GenericFunction>(&PointerTrait::get), + reinterpret_cast<GenericFunction>(&operator_new<PointerType>), + reinterpret_cast<GenericFunction>(&PointerTrait::share), + reinterpret_cast<GenericFunction>(&raw_destructor<PointerType>)); return *this; }; |