2012-01-16 32 views
9

Không sử dụng trực tiếp boost::threadboost::bind, có cách nào để thực hiện tương đương với mã sau không?Tăng tương đương với tiêu chuẩn :: async()

std::string func() 
{ 
    std::string str("Hello from async task!"); 
    return str; 
} 

int main() 
{ 
    auto ftr = std::async(&func); 
    std::cout << "Hello from main!"; 
    std::string str = ftr.get(); 
    std::cout << str << std::endl;  
    return 0; 
} 

Cụ thể, phần này: auto ftr = std::async(&func);?

Trả lời

8

Chắc chắn. Chỉ cần thực hiện async<T>(std::function<T()>) trả về một tương lai gọi func() thời điểm nó được chờ đợi lần đầu tiên. Bạn sẽ không nhận được bất kỳ asynchronicity, nhưng API không thực sự đảm bảo rằng các chức năng sẽ chạy không đồng bộ, do đó, đó không phải là một vấn đề.

Nếu bạn có quyền truy cập vào thư viện luồng dành riêng cho hệ điều hành, bạn cũng có thể sử dụng thư viện đó.

Lưu ý, tuy nhiên, lưu trữ ngoại lệ không thể triển khai được một cách hợp lý; nó đòi hỏi sự hỗ trợ bổ sung từ việc thực hiện C++, trừ khi bạn có thể hạn chế các ngoại lệ được hỗ trợ cho các trường hợp có chức năng sao chép đa hình. Xem this question để biết thêm thông tin.

Việc thực hiện cuối cùng có thể nhìn một chút như thế này (chưa được kiểm tra):

// NOTE - we assume a SINGLE THREADED environment 

template<typename T> 
class myfuture_detail { 
    mutable boost::variant<T, boost::function<T()> > val; 

public: 
    myfuture_detail(const boost::function<T()> &f) 
     : val(f) { } 

    const T &get() const { 
     if (T *t = boost::get<T>(&val)) { 
      return *t; 
     } else { 
      boost::function<T()> f = *boost::get<boost::function<T> >(&val); 
      val = f(); 

      T *t = boost::get<T>(&val); 
      assert(t); 

      return *t; 
     } 
    } 
}; 

template<typename T> 
class myfuture { 
    boost::shared_ptr<myfuture_detail<T> > ptr; 

public: 
    myfuture(const boost::function<T()> &f) 
     : ptr(boost::make_shared<myfuture_detail<T> >(f)) 
    {} 

    myfuture() { } 

    const T &get() const { 
     return ptr->get(); 
    } 
}; 
+0

Cảm ơn bạn đã trả lời chi tiết! Tôi là một cái gì đó của một người mới về lập trình meta vì vậy tôi không chắc chắn làm thế nào điều này có thể được sử dụng trong cùng một cách như ví dụ trong OP ... Ví dụ, nơi sẽ tương đương với 'std :: async () 'đi vào nó? Liệu lớp 'myfuture' có cần bằng cách nào đó bị ràng buộc với một' boost :: thread' không? –

+1

Điều này không thực sự không đồng bộ. 'std :: async' của hợp đồng không thực sự guarentee rằng thói quen async sẽ chạy ... không đồng bộ. Hãy xem xét nếu thread async không bao giờ được lên lịch cho đến khi bạn nhận được '.get()' - nó có hiệu quả đồng bộ. Đây là những gì tôi đã làm ở đây - vì bạn không có chủ đề, tôi chỉ giả vờ như nó đang chạy không đồng bộ và chỉ xảy ra để không nhận được bất cứ điều gì được thực hiện cho đến khi bạn tìm kiếm kết quả. – bdonlan

+0

"* Lưu ý, tuy nhiên, lưu trữ ngoại lệ không thể được triển khai một cách hợp lý *" Không [Boost.Exception] (http://www.boost.org/libs/exception/) có làm được điều này không? – ildjarn

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