:O it works. Use a sharing policy approach to autocasting pointers.

This commit is contained in:
Chad Austin 2013-03-12 18:37:24 -07:00 коммит произвёл Jukka Jylänki
Родитель de9a8d6fec
Коммит 7c49e9f886
2 изменённых файлов: 104 добавлений и 42 удалений

Просмотреть файл

@ -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(
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,
handle.$$.smartPtr);
__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);
rawConstructor = FUNCTION_TABLE[rawConstructor];
rawDestructor = FUNCTION_TABLE[rawDestructor];
rawGetPointee = FUNCTION_TABLE[rawGetPointee];
rawConstructor = FUNCTION_TABLE[rawConstructor];
rawShare = FUNCTION_TABLE[rawShare];
rawDestructor = FUNCTION_TABLE[rawDestructor];
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;

Просмотреть файл

@ -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 element_type* get(const PointerType& ptr) {
return ptr.get();
}
static PointerType share(const PointerType& r, element_type* ptr) {
return PointerType(r, ptr);
static sharing_policy get_sharing_policy() {
return sharing_policy::BY_EMVAL;
}
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;
};
};
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;
}
}
template<typename PointerType>
typename smart_ptr_trait<PointerType>::element_type* get_pointee(const PointerType& ptr) {
return smart_ptr_trait<PointerType>::get(ptr);
}
}
////////////////////////////////////////////////////////////////////////////////
// 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;
};