#include <boost/python/detail/prefix.hpp>
#include <boost/mpl/lambda.hpp> // #including this first is an intel6 workaround
+#include <boost/cstdint.hpp>
#include <boost/python/object/class.hpp>
#include <boost/python/object/instance.hpp>
{
if (static_data_object.tp_dict == 0)
{
- Py_TYPE(&static_data_object) = &PyType_Type;
+ Py_SET_TYPE(&static_data_object, &PyType_Type);
static_data_object.tp_base = &PyProperty_Type;
if (PyType_Ready(&static_data_object))
return 0;
{
if (class_metatype_object.tp_dict == 0)
{
- Py_TYPE(&class_metatype_object) = &PyType_Type;
+ Py_SET_TYPE(&class_metatype_object, &PyType_Type);
class_metatype_object.tp_base = &PyType_Type;
if (PyType_Ready(&class_metatype_object))
return type_handle();
// like, so we'll store the total size of the object
// there. A negative number indicates that the extra
// instance memory is not yet allocated to any holders.
-#if PY_VERSION_HEX >= 0x02060000
- Py_SIZE(result) =
-#else
- result->ob_size =
-#endif
- -(static_cast<int>(offsetof(instance<>,storage) + instance_size));
+ Py_SET_SIZE(result,-static_cast<int>(offsetof(instance<>,storage) + instance_size));
}
return (PyObject*)result;
}
{
if (class_type_object.tp_dict == 0)
{
- Py_TYPE(&class_type_object) = incref(class_metatype().get());
+ Py_SET_TYPE(&class_type_object, incref(class_metatype().get()));
class_type_object.tp_base = &PyBaseObject_Type;
if (PyType_Ready(&class_type_object))
return type_handle();
} // namespace objects
-void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size)
+typedef unsigned int alignment_marker_t;
+
+void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size, std::size_t alignment)
{
assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
objects::instance<>* self = (objects::instance<>*)self_;
- int total_size_needed = holder_offset + holder_size;
+ int total_size_needed = holder_offset + holder_size + alignment - 1;
if (-Py_SIZE(self) >= total_size_needed)
{
// holder_offset should at least point into the variable-sized part
assert(holder_offset >= offsetof(objects::instance<>,storage));
+ size_t allocated = holder_size + alignment;
+ void* storage = (char*)self + holder_offset;
+ void* aligned_storage = ::boost::alignment::align(alignment, holder_size, storage, allocated);
+
// Record the fact that the storage is occupied, noting where it starts
- Py_SIZE(self) = holder_offset;
- return (char*)self + holder_offset;
+ const size_t offset = reinterpret_cast<uintptr_t>(aligned_storage) - reinterpret_cast<uintptr_t>(storage) + holder_offset;
+ Py_SET_SIZE(self, offset);
+ return (char*)self + offset;
}
else
{
- void* const result = PyMem_Malloc(holder_size);
- if (result == 0)
+ const size_t base_allocation = sizeof(alignment_marker_t) + holder_size + alignment - 1;
+ void* const base_storage = PyMem_Malloc(base_allocation);
+ if (base_storage == 0)
throw std::bad_alloc();
- return result;
+
+ const uintptr_t x = reinterpret_cast<uintptr_t>(base_storage) + sizeof(alignment_marker_t);
+ //this has problems for x -> max(void *)
+ //const size_t padding = alignment - ((x + sizeof(alignment_marker_t)) % alignment);
+ //only works for alignments with alignments of powers of 2, but no edge conditions
+ const uintptr_t padding = alignment == 1 ? 0 : ( alignment - (x & (alignment - 1)) );
+ const size_t aligned_offset = sizeof(alignment_marker_t) + padding;
+ void* const aligned_storage = (char *)base_storage + aligned_offset;
+ BOOST_ASSERT((char *) aligned_storage + holder_size <= (char *)base_storage + base_allocation);
+ alignment_marker_t* const marker_storage = reinterpret_cast<alignment_marker_t *>((char *)aligned_storage - sizeof(alignment_marker_t));
+ *marker_storage = static_cast<alignment_marker_t>(padding);
+ return aligned_storage;
}
}
objects::instance<>* self = (objects::instance<>*)self_;
if (storage != (char*)self + Py_SIZE(self))
{
- PyMem_Free(storage);
+ alignment_marker_t* marker_storage = reinterpret_cast<alignment_marker_t *>((char *)storage - sizeof(alignment_marker_t));
+ void *malloced_storage = (char *) storage - sizeof(alignment_marker_t) - (*marker_storage);
+ PyMem_Free(malloced_storage);
}
}