2011-09-20 7 views
8

Dopo aver letto this document sulla sicurezza dei thread, ho la sensazione che manchi qualcosa nella documentazione, o la mia lettura o il mio ragionamento.Sicurezza dei thread con i tag dei modelli

Diamo un semplice esempio:

class HelloWorldNode(template.Node): 
    def render(self, context): 
     return "O HAI LOL" 

@register.tag(name="hello_world") 
def hello_world(parser, tokens): 
    """ 
    Greets the world with wide-eyed awe. 
    """ 
    return HelloWorldNode() 

Compresi questo codice per creare una nuova istanza della classe HelloWorldNode ogni volta che viene utilizzato il tag hello_world. Altri esempi riguardanti il ​​passaggio di argomenti al costruttore, in questo modo:

class HelloWorldNode(template.Node): 
    def __init__(self, message): 
     self.message = message 

    def render(self, context): 
     return "O HAI LOL " + message 

@register.tag(name="hello_world") 
def hello_world(parser, tokens): 
    """ 
    Greets the world with wide-eyed awe. 
    """ 

    message = tokens.split_contents()[1] 

    return HelloWorldNode(message) 

Così, quando viene eseguita hello_world, viene creata una nuova istanza di HelloWorldNode, e il dizionario dell'istanza ha un attributo message. Questa istanza sicuramente deve essere utilizzata solo per il rendering della sola istanza del tag, in quanto il suo utilizzo per altri rendering significherebbe che i dati ad esso associati non sarebbero corretti. Se così non fosse, gli argomenti verrebbero confusi tra diversi usi del tag.

Guardando in altri esempi la documentazione, ecco un esempio semplificato da here:

def do_current_time(parser, token): 
    tag_name, format_string = token.split_contents() 
    return CurrentTimeNode(format_string[1:-1]) 

Dato che questo prende i dati dai gettoni passati alla funzione, l'unico modo che CurrentTimeNode può funzionare è che uno nuovo viene istanziato ogni volta che viene invocato do_current_time.

Torna alla pagina della documentazione, in cui la dissonanza si inserisce. Questa è 'cattiva'.

class CycleNode(Node): 
    def __init__(self, cyclevars): 
     self.cycle_iter = itertools.cycle(cyclevars) 
    def render(self, context): 
     return self.cycle_iter.next() 

Il dottore dice che due pagine utilizzando lo stesso tag potrebbero poi sperimentare condizioni di gara se entrambi utilizzano lo stesso nodo. Non capisco come il rendering di due modelli possa finire per condividere la stessa istanza se entrambi istanziano autonomamente il proprio.

Il modo per risolvere questo, dice la documentazione è in questo modo:

class CycleNode(Node): 
    def __init__(self, cyclevars): 
     self.cyclevars = cyclevars 
    def render(self, context): 
     if self not in context.render_context: 
      context.render_context[self] = itertools.cycle(self.cyclevars) 
     cycle_iter = context.render_context[self] 
     return cycle_iter.next() 

Questo sembra indice context.render_context con self. L'implicazione di che deve essere che self viene utilizzato per identificare l'istanza in uno dei due modi:

  1. self riferimenti una specifica istanza della classe in tutto il sistema
  2. self riferimenti quella classe solo, e al fine per fare riferimento all'istanza è necessario un contesto di rendering

Se 1 è vero, perché non associare semplicemente i dati a self?

Se 2 è true e il contesto di rendering è "associato al contesto del modello attualmente sottoposto a rendering", come è possibile distinguere tra due istanze del tag del modello sulla stessa pagina?

Il nodo viene istanziato singolarmente ogni volta che viene richiamato il tag? Se sì, perché i problemi di concorrenza? Se no, perché no?

risposta

0

Ottenuto con una lettura più ravvicinata di this.

Il modello viene compilato quando viene caricato. Qualsiasi argomento passato alla funzione tag è 'statico'. Sono stringhe letterali o sono stringhe che vengono utilizzate come identificatori per cercare variabili associate nel contesto di rendering.

Pertanto, l'oggetto Nodo viene istanziato per ogni tag e rimane in sospeso pronto per l'uso ogni volta che viene utilizzato il modello (e naturalmente il modello può essere utilizzato in qualsiasi numero di thread).

Così la self nella mia domanda è l'identità del nodo specifico all'interno del modello. In combinazione con il contesto di rendering, questo fornisce un'identità univoca su cui appendere le variabili di istanza.

Problemi correlati