2015-01-21 12 views
7

Are các nhà thầu cấp phát-lấy tiêu chuẩn promise/packaged_task phải sử dụng cấp phát cho chỉ đối tượng trạng thái riêng của mình, hoặc điều này nên được đảm bảo cho tất cả (nội bộ) đối tượng liên quan?allocators Tuỳ chỉnh so với lời hứa và nhiệm vụ đóng gói

[futures.promise]: "... phân bổ bộ nhớ cho tình trạng chia sẻ"
[futures.task.members]: "... phân bổ bộ nhớ cần thiết để lưu trữ các cấu trúc dữ liệu nội bộ"

Cụ thể là các lỗi hoặc tính năng dưới đây?

* MSVC 2013,4, Tăng 1,57, short_alloc.h by Howard Hinnant

Ví dụ 1

#define BOOST_THREAD_VERSION 4 
#include <boost/thread/future.hpp> 
#include "short_alloc.h" 
#include <cstdio> 

void *operator new(std::size_t s) { 
    printf("alloc %Iu\n", s); 
    return malloc(s); 
} 

void operator delete(void *p) { 
    free(p); 
} 

int main() { 

    const int N = 1024; 
    arena<N> a; 
    short_alloc< int, N > al(a); 

    printf("[promise]\n"); 
    auto p = boost::promise<int>(std::allocator_arg, al); 
    p.set_value(123); 

    printf("[packaged_task]\n"); 
    auto q = boost::packaged_task< int() >(std::allocator_arg, al, [] { return 123; }); 
    q(); 

    return 0; 

} 

Output:

... 
[promise] 
alloc 8 
alloc 12 
alloc 8 
alloc 24 
[packaged_task] 
alloc 8 
alloc 12 
alloc 8 
alloc 24 

FWIW, đầu ra bằng bộ cấp mặc định là

... 
[promise] 
alloc 144 
alloc 8 
alloc 12 
alloc 8 
alloc 16 
[packaged_task] 
alloc 160 
alloc 8 
alloc 12 
alloc 8 
alloc 16 

Ví dụ 2

AFAICT, MSVC của std::mutex không phân bổ đống không thể tránh khỏi, và do đó, thì std::promise trong đó sử dụng nó. Đây có phải là hành vi tuân thủ không?

+4

Tại sao bạn sử dụng 'boost' trong mã mẫu của mình và nói về hành vi được chỉ định bởi' std'? Tại sao không sử dụng 'std'? – Yakk

+1

@Yakk: http://www.boost.org/doc/libs/1_57_0/doc/html/thread/compliance.html – vpozdyayev

+0

@Yakk: Ngoài ra, tôi đã thử std; xem ví dụ 2. Trên thực tế, tôi đã thử std đầu tiên, sau đó quay để tăng với hy vọng nhận được sử dụng nhiều hơn của các cấp phát tùy chỉnh --- nhưng than ôi. – vpozdyayev

Trả lời

1

N.B. có một số vấn đề với mã của bạn. Trong C++ 14 nếu bạn thay thế operator delete(void*) thì bạn cũng phải thay thế operator delete(void*, std::size)t). Bạn có thể sử dụng một macro tính năng thử nghiệm để xem nếu trình biên dịch đòi hỏi rằng:

void operator delete(void *p) { 
    free(p); 
} 
#if __cpp_sized_deallocation 
// Also define sized-deallocation function: 
void operator delete(void *p, std::size_t) { 
    free(p); 
} 
#endif 

Thứ hai định dạng printf specifier chính xác cho size_tzu không u, vì vậy bạn nên sử dụng %Izu.

AFAICT, MSVC std::mutex thực hiện phân bổ đống không thể tránh khỏi và do đó, std::promise sử dụng nó. Đây có phải là hành vi tuân thủ không?

Chắc chắn có vấn đề liệu std::mutex có nên sử dụng phân bổ động hay không. Nhà xây dựng của nó không thể, bởi vì nó phải là constexpr. Nó có thể trì hoãn việc phân bổ cho đến khi cuộc gọi đầu tiên đến lock() hoặc try_lock() nhưng lock() không liệt kê không thành công để lấy tài nguyên dưới dạng điều kiện lỗi hợp lệ, và có nghĩa là try_lock() không thể khóa một mutex không được kiểm soát nếu nó không thể phân bổ tài nguyên cần thiết . Điều đó được cho phép, nếu bạn nheo mắt, nhưng không lý tưởng.

Nhưng liên quan đến câu hỏi chính của bạn, như bạn trích dẫn, tiêu chuẩn chỉ nói điều này cho promise:

Các constructor thứ hai sử dụng bộ cấp phát a phân bổ bộ nhớ cho tình trạng chia sẻ.

Điều đó không nói bất kỳ điều gì về tài nguyên khác cần thiết theo lời hứa. Giả sử rằng bất kỳ đối tượng đồng bộ nào như mutexes là một phần của trạng thái chia sẻ, không phải lời hứa, nhưng từ ngữ đó không yêu cầu cấp phát được sử dụng cho bộ nhớ mà các thành viên được chia sẻ yêu cầu, chỉ cho bộ nhớ cần thiết bởi trạng thái chia sẻ chinh no.

Đối với packaged_task từ ngữ rộng hơn và ngụ ý rằng tất cả trạng thái nội bộ nên sử dụng trình phân bổ, mặc dù nó có thể được lập luận rằng nó có nghĩa là người cấp phát được sử dụng để lấy bộ nhớ cho tác vụ được lưu trữ và trạng thái chia sẻ. trạng thái chia sẻ không phải sử dụng bộ cấp phát. Tóm lại, tôi không nghĩ rằng tiêu chuẩn là 100% rõ ràng cho dù thực hiện MSVC được cho phép, nhưng IMHO một thực hiện mà không cần thêm bộ nhớ từ malloc hoặc new là tốt hơn (và đó là cách thực hiện libstdC++ <future>).

Các vấn đề liên quan