Domanda

Ho classe A e A elenco di oggetti. A ha una funzione f che deve essere eseguito ogni X secondi (per la prima istanza ogni 1 secondo, per l'istanza secondi ogni 5 secondi, ecc). Ho una classe di pianificazione che si occupa di eseguire le funzioni al momento giusto. Quello che ho pensato di fare è di creare una nuova classe, atime, che si terrà ptr a un'istanza e il tempo deve essere eseguito un :: f. Lo scheduler terrà una coda min priorità atime.

  1. Fare si pensa che è la corretta attuazione?
  2. dovrebbe atime essere una classe annidata dello scheduler?
È stato utile?

Soluzione

Da ciò che si descrive, suona come potrebbe funzionare: -)

class IMHO ATime appartiene allo scheduler oltre ad A. E 'necessario che lo scheduler per fare il suo lavoro, e non è necessaria per A. In realtà, A (e il resto del mondo) non è necessario nemmeno della sua esistenza - in modo da mettere una classe annidata privata del scheduler sarebbe opportuno per me

.

Altri suggerimenti

Questo può essere un po 'troppo avanzato, ma qui va ...

boost :: funzione e boost :: legano può essere utilizzato per implementare uno scheduler che non ha bisogno di sapere nulla di classe A. Questo renderebbe il programmatore delle più generico e riutilizzabile.

Ecco alcuni esempi di codice che illustra come quelle strutture Boost possono essere utilizzati nel vostro caso:

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

Si noti che Scheduler non sa nulla di Foo & Bar, e viceversa. Tutti Scheduler davvero vuole è un funtore "callback" che corrisponde alla firma specificato da SchedulerHandler.

Se avete bisogno di un SchedulerEvent essere cancellabile, le cose si fanno un po 'complicato perché gli oggetti boost::function non sono comparabili. Per aggirare il problema, è necessario restituire una sorta di gettone "connessione" al momento della registrazione eventi. Questo è essenzialmente ciò che fa Boost.Signal.

Spero che questo aiuti.

Questo tipo di classe è meglio realizzato una struttura privata nidificato all'interno della vostra classe scheduler, in modo da poter accedere facilmente a tutti i campi all'interno della classe scheduler. (Tutti i campi di una struct sono pubblici per impostazione predefinita.)

Per quanto riguarda la seconda parte (e la domanda nel titolo), IMO è completamente una questione di gusto. Si potrebbe altrettanto bene scegliere di ridurre la confusione nella definizione della classe di pianificazione, e mettere in un atime subnamespace con un nome di avviso (come detail) per impedire alle persone di utilizzarlo. Dopo tutto, se è utile solo per la pianificazione, non c'è molto bisogno di nasconderlo troppo -. Nessuno sta andando a voler utilizzare comunque

Forse potrebbe essere diverso in C ++ 0x (credo di aver sentito alcune voci come sta andando a cambiare le regole di accessibilità fra nidificato e genitore di classe, o giù di lì, nel qual caso la nidificazione potrebbe essere più utile).

Per genericità si potrebbe anche voler fare uso di modelli, e magari finire con Scheduler<A> (utilizzando un TimedOperation<A>) (o una miriade di perfezionamenti potenziali / generalizzazioni di questo)?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top