Question

J'ai la classe A et la liste des objets A. A comporte une fonction F qui doit être exécuté toutes les X secondes (pour le premier exemple toutes les 1 seconde, pour l'instance de secondes toutes les 5 secondes, etc.). J'ai une classe de planificateur qui est responsable d'exécuter les fonctions au bon moment. Ce que je pensais à faire est de créer une nouvelle classe, ATIME, qui tiendra PTR à une instance et le temps doit être exécuté A :: f. Le planificateur tiendra une file d'attente prioritaire min de Atime.

  1. Pensez-vous qu'il est la mise en œuvre correcte?
  2. aTime devrait être une classe imbriquée du programmateur?
Était-ce utile?

La solution

D'après ce que vous décrivez, sonne comme cela pourrait fonctionner: -)

classe à mon humble avis ATime appartient au planificateur plus A. Il est nécessaire pour le planificateur de faire son travail, et il est pas nécessaire pour A. En fait, A (et le reste du monde) ne doivent pas savoir même son existence - mettant ainsi une classe imbriquée privée du planificateur serait approprié pour moi

.

Autres conseils

Cela peut être un peu trop avancé, mais ici ...

boost :: fonction et boost :: bind peut être utilisé pour mettre en œuvre un planificateur de tâches n'a pas besoin de savoir quoi que ce soit au sujet de la classe A. Cela rendrait votre planificateur plus générique et réutilisable.

Voici quelques exemples de code qui illustre comment ces installations Boost peuvent être utilisés dans votre cas:

#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;
}

Notez que Scheduler ne sait rien Foo & Bar, et vice-versa. Tout Scheduler veut vraiment est un foncteur « de rappel » qui correspond à la signature spécifiée par SchedulerHandler.

Si vous avez besoin d'un SchedulerEvent être résiliable, les choses deviennent un peu compliqué parce que les objets de boost::function ne sont pas comparables. Pour contourner ce problème, vous aurez besoin de retourner une sorte de jeton « de connexion » lors de l'enregistrement des événements. Ceci est essentiellement ce qui fait Boost.Signal.

Hope this helps.

Ce genre de classe est mieux fait une struct privée nichée au sein de votre classe de programmation, de sorte que vous pouvez facilement accéder à tous les champs à l'intérieur de la classe de planificateur. (Tous les champs de struct sont publiques par défaut.)

Quant à la deuxième partie (et la question dans le titre), l'OMI, il est tout à fait une question de goût. Vous pourriez tout aussi bien choisir de réduire l'encombrement dans la définition de la classe Scheduler et placez aTime dans un sousespacedenoms avec un nom d'avertissement (comme detail) pour garder les gens de l'utiliser. Après tout, si elle est seulement utile pour le planificateur, il n'y a pas beaucoup besoin de le cacher trop -. Personne ne va vouloir l'utiliser de toute façon

Peut-être peut-être différent en C ++ 0x (je pense avoir entendu des rumeurs comment il va changer les règles d'accessibilité entre les classes imbriquées et parent, ou alors, où l'imbrication de cas pourrait être plus utile).

Pour généricité vous pouvez également utiliser des modèles, et peut-être finir avec Scheduler<A> (en utilisant un TimedOperation<A>) (ou une myriade d'améliorations possibles / généralisations de cela)?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top