如何实现一个简单的事件队列

How to implement a simple event queue?

本文关键字:一个 简单 事件队列 实现 何实现      更新时间:2023-10-16

所以,我首先在谷歌上搜索了大量内容,但所有的解决方案似乎都非常复杂。所以,我想我会问这里,看看这项任务是否真的需要我遇到的那种方法。。。

所以,假设我有一个Event类。我希望它有一个time变量和一个functionToExecuteAtTime函数指针/变量/魔术代码,可以将任何旧函数传递给这个类。

此外,我希望将事件保存在一个优先级队列中,该队列按时间顺序排列事件并执行它们"承载"的功能。但是暂时忘记这一点

像这样的。。。

class Agent
{
    public:
    int id;
    float cash;
    Agent::Agent
    {
        cash = 100;
    }
}
class uberSystem
{
    public:
    float assets;
    int supplyOfDeadlyPoison;
    float poisonCost;
    std::vector<Agent> agents;
    uberSystem::uberSystem
    {
        assets = 100000;
        supplyOfDeadlyPoison = 100000;
        poisonCost = 8;
        for(int i = 0; i < 100; i++)
        {
        Agent newAgent;
        newAgent.id = i;
        agents.push_back(newAgent)
        }
     }
};

class Event
{
    public:
    int time;
    SOMETHING_THAT_LETS_ME_HOLD_FUNCTIONS myFunction;
    Event::Event(int t, SOMETHING_THAT_LETS_ME_HOLD_FUNCTIONS func)
    {
         time = t;
         myFunction = func;
    }
}
int uselessFunction()
{
    return 42;
}
void buyPoisonAndKillAgent(Agent &myAgent, uberSystem &mySystem)//obviously not good...
{
    myAgent.cash -= mySystem.poisonCost;
    mySystem.assets += mySystem.poisonCost;
    mySystem.agents.erase(mySystem.agents.begin()+myAgent.id);
    mySystem.supplyOfDeadlyPoison -= 1;
}

int main()
{
    uberSystem newSystem;
   // Event newEvent(100, uselessFunction());//make a new event
    Event newEvent(100, buyPoisonAndKillAgent(newSystem.agents[5], newSystem));
    newEvent.myFunction;//run the bloody function
    return 0;
}

好吧,现在我打字的时候,这看起来像是一厢情愿的想法。那么,我该如何实现呢?函数指针是可行的吗?还是有什么更好的方法我还没找到?

哦,显然我确实有std::function可用。。。我一直都不在石器时代!

谢谢!

您可以有一个基类事件(由@EdHeal提出),然后有一个模板子类存储您的函数指针:

class Event {
public:
  int time;
  Event(int t) : time(t) {}
  virtual ~Event(){}
  virtual void myFunction() = 0;
};
template<typename TFunc>
class TEvent : public Event {
public:
  TFunc func;
  TEvent(int t, TFunc f) : Event(t), func(f) {} 
  void myFunction() { func(); }
};
template<typename TFunc>
auto_ptr<Event> make_event(int time, TFunc func) {
    return std::auto_ptr<Event>(new TEvent<TFunc>(time,func));
}

使用辅助函数make_event,可以很容易地调用并自动推导类型:

void useless() {std::cout << "Func A";}
struct functor {
  void operator()() {std::cout << "Functor B";} 
};
struct paramFunctor {
  paramFunctor(int x, double y): result(0), m_x(x), m_y(y){}
  void operator()() {
    std::cout << "Params: x:" << m_x << ", y:" << m_y << "n";
  } 
  long long result;
private:
  int m_x;
  double m_y;
};
int main() {
  auto_ptr<Event> e1 = make_event(10,useless);
  auto_ptr<Event> e2 = make_event(100,functor());
  auto_ptr<Event> e2 = make_event(100,paramFunctor(1,2.0));
  // your code goes here
  e1->myFunction();
  e2->myFunction();
  e3->myFunction();
  return 0;
}

当然,如果可以访问C++11(或TR1,或boost),则根本不需要所有这些(正如其他答案所描述的)

为什么不做这个

class Event {
    private:
       int time;
    public:
       Event(int t) : time(t)  { }
       virtual void DoEvent() = 0;
};
class MyEVent: public Event {
    public:
        MyEvent(int t) : Event(t) { }
        void DoEvent() { std::cout << "Event  called" << std::endl;
};

然后

int main() {
    MyEvent e(100);
    e.DoEvent();
    return 0;
}

这看起来更简单,您可以奢侈地添加事件所需的任何数据。

对于列表,您使用Event指针,例如Event *e = new MyEvent(100)

保存泛型函数或闭包的最简单方法是使用std::function;在没有C++11的情况下,boost::function是一个很好的占位符

这产生:

class Event {
public:
private:
    std::time_t time;
    boost::function<void()> function;
}; // class Event

注意,函数的签名需要精确:void()是一个不带参数、不返回任何内容的函数。

此外,请注意,您可以任意谓词、函子类或lambda,只要其中一个operator()与预期签名匹配即可。

相关文章: