Я реализую GlobalAlloc
, чтобы всегда выравнивать выделения по границам 4096 байт и чтобы размеры были кратны 64 байтам. Это обеспечит лучшую совместимость с OpenCL, в частности буферы нулевого копирования с графикой Intel.
Документация и источник AllocRef
(реализованный System
) говорят, что возвращаемое значение для alloc
в System
равно Result<NonNull<u8>, AllocErr>
. Однако компилятор жалуется на несоответствие типов. Притворяясь, что alloc
действительно возвращает *mut u8
, и программирование как таковое компилируется, но теперь IDE (IntelliJ) жалуется.
Поскольку я использую ночную сборку Rust и очень новичок в Rust, я не могу сказать, связано ли это просто с устаревшей документацией и установленным исходным кодом, ошибкой в IDE или чем-то еще, чего я не понимаю. .
#![feature(allocator_api)]
use std::alloc::System;
use std::alloc::{handle_alloc_error, AllocRef, GlobalAlloc, Layout};
use std::ptr::NonNull;
struct OpenCLConsideringAlloc;
unsafe impl GlobalAlloc for OpenCLConsideringAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
match System.alloc(to_ocl_considering_layout(layout)) {
Ok(v) => v.as_ptr(),
Err(e) => match System.alloc(layout) {
Ok(ptr) => ptr.as_ptr(),
Err(e) => handle_alloc_error(layout),
},
}
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
System.dealloc(
NonNull::new_unchecked(ptr),
to_ocl_considering_layout(layout),
);
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
match System.alloc_zeroed(to_ocl_considering_layout(layout)) {
Ok(ptr) => ptr.as_ptr(),
Err(e) => match System.alloc_zeroed(layout) {
Ok(ptr) => ptr.as_ptr(),
Err(e) => handle_alloc_error(layout),
},
}
}
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
match System.realloc(
NonNull::new_unchecked(ptr),
to_ocl_considering_layout(layout),
new_size,
) {
Ok(ptr) => ptr.as_ptr(),
Err(e) => match System.realloc(NonNull::new_unchecked(ptr), layout, new_size) {
Ok(ptr) => ptr.as_ptr(),
Err(e) => handle_alloc_error(layout),
},
}
}
}
//Attempts to round-up size up to a multiple of 64, forces 4096-byte alignment for large
//allocations, 64-byte alignment for intermediate sizes, default for small allocations.
#[inline]
fn to_ocl_considering_layout(any_layout: Layout) -> Layout {
let alignment: usize = match any_layout.size() {
0..=1024 => any_layout.align(),
1025..=65536 => 64,
_ => 4096
};
match Layout::from_size_align(
((any_layout.size() as i64 + 63_i64) & -64_i64) as usize,
alignment
) {
Ok(layout) => layout,
Err(e) => any_layout,
}
}
#[global_allocator]
static GLOBAL: OpenCLConsideringAlloc = OpenCLConsideringAlloc;
Ошибка компилятора:
error[E0308]: mismatched types
--> src/lib.rs:12:13
|
11 | match System.alloc(to_ocl_considering_layout(layout)) {
| ----------------------------------------------- this expression has type `*mut u8`
12 | Ok(v) => v.as_ptr(),
| ^^^^^ expected *-ptr, found enum `std::result::Result`
|
= note: expected raw pointer `*mut u8`
found enum `std::result::Result<_, _>`
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
}
Выход rustup show
:
Default host: x86_64-pc-windows-gnu
rustup home: C:\Users\username\.rustup
nightly-x86_64-pc-windows-gnu (default)
rustc 1.43.0-nightly (6d0e58bff 2020-02-23)
System
реализуетAllocRef
иGlobalAlloc
, оба из которых имеют методalloc
. Вы звонитеGlobalAlloc::alloc
. На это отвечают ответы Как устранить неоднозначность признаков в Rust?. Если нет, отредактируйте свой вопрос, чтобы объяснить различия. В противном случае мы можем пометить этот вопрос как уже отвеченный. - person Shepmaster   schedule 26.02.2020System
наAllocRef
) также дает более полезную ошибку компилятора:error[E0034]: multiple applicable items in scope
. Это ответ на мой вопрос, спасибо @Shepmaster и @Stargateur! - person Tonnz   schedule 26.02.2020