通用未来/承诺的容器

时间:2010-11-01 12:10:10

标签: c++ stl

我们正在尝试生成一个将执行异步调用的库组件。 由于各种原因,这需要具有类似C的接口,因此我们提供了大量静态函数作为库的接口。

我们还需要用户控制内存。所以大多数函数看起来像

int myLibFunction(void* data, size_t data_size);

我正在尝试用更智能的Future对象替换它,以便我们不使用void指针,以便在线程之间同步对数据的访问。理想情况下,呼叫看起来像:

Future<T> {
  T m_data;
}

static int myLibDoJob1(Future<Func1Data>& data);
static int myLibDoJob2(Future<Func2Data>& data);

main()
{
   Func1Data m_data;
   Func2Data m_data2;
   Future<Func1Data> future1(m_data);
   Future<Func2Data> future2(m_data2);
   int ret=0;

   ret = myLibDoJob1(future1);
   ret = myLibDoJob2(future2);
}

这是一个相当干净的界面,界面在编译时强制类型安全。但是我遇到的问题是我正在创建一个内部执行的作业队列。但是由于Futures的大小不同,我无法创建std:队列,我原本希望能够创建一个std :: queue,其中Job包含Future *但是这是无效的。

我也试过让Job包含Future,其中所有Data类派生自ParentData也无济于事。

问题非常类似于拥有智能指针容器的问题。由于我工作的团队的性质,我将无法在库外暴露任何增强对象,如果我使Future多态,我将被一个板球棒追逐。

重要的是,库的用户端代码可以控制数据的实际位置。

此致 伊恩

2 个答案:

答案 0 :(得分:3)

您将使用C ++进行多态,或者您将使用void*重新实现多态性。解决问题的最简单方法是给Future<T>一个不依赖于T的基类。通常我这样做:

class Future {};

template<class T>
class FutureOf : public Future {};

然后,您可以创建Future*的容器并具有一些类型安全性。

答案 1 :(得分:0)

目前还不完全清楚你要做什么。但是,如果我理解正确的话,你有一堆遗留函数,并且你试图将每个函数包装在(模板)类中,并为它提供特定于类型的数据。像下面这样的东西可以做你想要的吗?

#include <iostream>
#include <list>

class AbstractFuture
{
public:
    virtual int compute() const = 0;
};

// Encapsulates function and data
template <typename F, typename T>
class Future : public AbstractFuture
{
public:
    Future(F func, T x) : func_(func), x_(x) {}
    virtual int compute() const { return func_(x_); };
private:
    const F func_;
    const T x_;
};

// Helper function template, to save all the explicit <> nonsense
// you'd need otherwise
template <typename F, typename T>
AbstractFuture *createFuture(F func, T x) { return new Future<F,T>(func, x); }

// Some data types
typedef float Func1Data;
typedef double Func2Data;

// Dummy function implementations
static int myLibDoJob1(const Func1Data& data)     { return 5; }
static int myLibDoJob2(const Func2Data& data)     { return 7; }


int main()
{
    // Data for each Future
    Func1Data x1 = 0;
    Func2Data x2 = 0;

    // Create some Futures (note, the function template makes this type-safe)
    AbstractFuture *p1 = createFuture(myLibDoJob1, x1);
    AbstractFuture *p2 = createFuture(myLibDoJob2, x2);

    // Put into a container (of pointers to base class)
    std::list<AbstractFuture *> futures;
    futures.push_back(p1);
    futures.push_back(p2);

    // Demonstrate polymorphism works
    for (std::list<AbstractFuture *>::const_iterator it = futures.begin();
         it != futures.end(); ++it)
    {
        std::cout << (*it)->compute() << std::endl;
    }

    delete p1;
    delete p2;

    return 0;
}

这可以通过智能指针更干净地完成,但这个想法应该成立。