aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Austin <chad@imvu.com>2013-03-12 18:37:24 -0700
committerJukka Jylänki <jujjyl@gmail.com>2013-04-12 14:25:48 +0300
commit7c49e9f8866314d688b07f99abb34ccdac442db3 (patch)
treee6f8cd72b7f922d6bf170bdee46a765f908e3adc
parentde9a8d6fecd4f699b2f80d908c8c597dcc8f04bc (diff)
:O it works. Use a sharing policy approach to autocasting pointers.
-rwxr-xr-xsrc/embind/embind.js49
-rwxr-xr-xsystem/include/emscripten/bind.h91
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;
};