3

我有 A 类和 A 对象列表。A 有一个函数 f 应该每 X 秒执行一次(对于第一个实例每 1 秒执行一次,对于 seconds 实例每 5 秒执行一次,等等)。我有一个调度程序类,负责在正确的时间执行这些功能。我想做的是创建一个新类 ATime,它将 ptr 保存到 A 实例以及应该执行 A::f 的时间。调度器将持有 Atime 的最小优先级队列。

  1. 你认为这是正确的实现吗?
  2. ATime 应该是调度程序的嵌套类吗?
4

4 回答 4

4

根据您的描述,听起来它可以工作:-)

恕我直言,类ATime属于调度程序而不是 A。调度程序需要它来完成它的工作,而 A 不需要它。事实上,A(和世界其他地方)甚至不需要知道它的存在 -所以把它放在调度程序的私有嵌套类对我来说是合适的。

于 2010-03-13T20:15:14.073 回答
1

这可能有点太高级了,但是这里......

boost::functionboost::bind可用于实现不需要了解任何关于 A 类的调度程序。这将使您的调度程序更加通用和可重用。

以下是一些示例代码,说明了如何在您的案例中使用这些 Boost 工具:

#include <ctime>
#include <queue>
#include <boost/function.hpp>
#include <boost/bind.hpp>

struct Foo
{
    void onScheduler(time_t time) {/*...*/}
};

struct Bar
{
    void onScheduler(time_t time) {/*...*/}
};

typedef boost::function<void (time_t)> SchedulerHandler;

struct SchedulerEvent
{
    bool operator<(const SchedulerEvent& rhs) const {return when < rhs.when;}

    SchedulerHandler handler;
    time_t when;
};

class Scheduler
{
public:
    void schedule(SchedulerHandler handler, time_t when)
    {
        SchedulerEvent event = {handler, when};
        queue_.push(event);
    }

private:
    std::priority_queue<SchedulerEvent> queue_;
    void onNextEvent()
    {
        const SchedulerEvent& next = queue_.top();
        next.handler(next.when);
        queue_.pop();
    }
};

int main()
{
    Scheduler s;
    Foo f1, f2;
    Bar b1, b2;

    time_t now = time(0);
    s.schedule(boost::bind(&Foo::onScheduler, &f1, _1), now + 1);
    s.schedule(boost::bind(&Foo::onScheduler, &f2, _1), now + 2);
    s.schedule(boost::bind(&Bar::onScheduler, &b1, _1), now + 3);
    s.schedule(boost::bind(&Bar::onScheduler, &b2, _1), now + 4);

    // Do scheduling...

    return 0;
}

请注意,对&Scheduler一无所知,反之亦然。真正想要的是一个与指定的签名匹配的“回调”函子。FooBarSchedulerSchedulerHandler

如果您需要 aSchedulerEvent可以取消,事情会变得有点复杂,因为boost::function对象是不可比较的。为了解决这个问题,您需要在注册事件时返回某种“连接”令牌。这本质上就是 Boost.Signal 所做的。

希望这可以帮助。

于 2010-03-13T22:59:54.010 回答
0

这种类最好是嵌套在调度程序类中的私有结构,因此您可以轻松访问调度程序类中的所有字段。(默认情况下,结构的所有字段都是公共的。)

于 2010-03-13T20:20:49.740 回答
0

至于第二部分(以及标题中的问题),IMO 完全是个人喜好问题。您也可以选择减少 Scheduler 类定义中的混乱,并将 ATime 放在带有警告名称(如detail)的子命名空间中,以防止人们使用它。毕竟,如果它只对调度器有用,没有必要隐藏太多——反正没人会想要使用它。

也许在 C++0x 中可能会有所不同(我想我听说过一些谣言,它将如何改变嵌套类和父类之间的可访问性规则,或者这样,在这种情况下嵌套可能更值得)。

为了通用性,您可能还想使用模板,并且可能以Scheduler<A>(使用 a TimedOperation<A>)(或无数潜在的改进/概括)结束?

于 2010-03-13T21:13:20.657 回答