IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Web Perl Discussion :

Petit soucis avec Thread::Queue et une classe


Sujet :

Web Perl

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 210
    Points : 99
    Points
    99
    Par défaut Petit soucis avec Thread::Queue et une classe
    J'ai un problème avec Thread::Queue auquel je ne parvient pas a trouver de solution j'invoque ma classe comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    sub new {
        my ($class, %cnf) = @_;
        my $gd     = delete $cnf{'gd'};
        my $list   = delete $cnf{'list'};
        my $self = bless {
            graph  => $gd,
            job    => $list
        }, $class;
        return $self;
    }
    en lui passant en paramètre deux références a Thread::Queue etant donnée que j'utilise deux files d'attente comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    my $DataQueue  = Thread::Queue->new;
    my $DataQueue2 = Thread::Queue->new;
     
     
    my $vector = Vector->new( 
                  gd      => \$DataQueue2,
                  list    => \$DataQueue
    );

    j'ai essayé deux méthodes pour utiliser ces références dans ma classe rien n'y fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $self->{job}->enqueue("data");
    ${$self->{'job'}}->enqueue("data");
    je ne voie vraiment pas d'ou vient le problème

    thx

  2. #2
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Je suis sûr de rien mais ptet bien que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ($self->{job})->enqueue("data");
    ffonctionnera. Au pire, si ça marche pas, ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $var = $self->{job};
    $var->enqueue("data");
    devrait marcher.

    En fait, l'opérateur -> est associatif à droite, je pense que Perl croit que enqueue est une variable de %self. Enfin bin, dit moi si ça marche

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 210
    Points : 99
    Points
    99
    Par défaut
    merci Woufeil mai sa ne marche pas

  4. #4
    Membre chevronné
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Points : 2 004
    Points
    2 004
    Par défaut
    Rhoooooo, j'avais même pas vu la grosse erreur

    $DataQueue et $DataQueue2 sont déjà des références, pourquoi dans la table de hachage passé en paramètres à ton constructeur tu passes une référence à ces variables ? Là tu est en train de passer une référence de référence
    Passe directement $DataQueue et $DataQueue2. J'ai testé, ça marche.

  5. #5
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par vodevil
    J'ai un problème avec Thread::Queue auquel je ne parvient pas a trouver de solution j'invoque ma classe comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    sub new {
        my ($class, %cnf) = @_;
        my $gd     = delete $cnf{'gd'};
        my $list   = delete $cnf{'list'};
        my $self = bless {
            graph  => $gd,
            job    => $list
        }, $class;
        return $self;
    }
    A quoi bon les delete ? %cnf étant lexical sera de toute façon détruit à la fin de l'appel.

    Citation Envoyé par vodevil

    en lui passant en paramètre deux références a Thread::Queue etant donnée que j'utilise deux files d'attente comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    my $DataQueue  = Thread::Queue->new;
    my $DataQueue2 = Thread::Queue->new;
     
     
    my $vector = Vector->new( 
                  gd      => \$DataQueue2,
                  list    => \$DataQueue
    );
    Pourquoi passer des référence sur des références ? (un objet est déjà une référence)

    Citation Envoyé par vodevil

    j'ai essayé deux méthodes pour utiliser ces références dans ma classe rien n'y fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $self->{job}->enqueue("data");
    ${$self->{'job'}}->enqueue("data");
    je ne voie vraiment pas d'ou vient le problème

    thx
    La deuxième syntaxe devrait fonctionner, ou peut-être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    (${$self->{'job'}})->enqueue("data");
    Mais si tu fais ça dans un contexte multithread, rapelle toi que les objets ne peuvent pas être partagés. Ca peut expliquer ton problème.

    --
    Jedaï

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 210
    Points : 99
    Points
    99
    Par défaut
    Aucune des solutions ne fonctionne c'est sans doute un problème avec les threads , je vais sans doute créer ma propore méthode de file d'attente

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 210
    Points : 99
    Points
    99
    Par défaut
    J'a i fait un petit système de file d'attente qui marche meme avec des threads , mais voila j'ai un soucie d'un autre ordre je n'arrive pas a mettre une donnée en file d'attente puis a la récupérer de l'autre coté sans fermer la fonction principale . un exemple valant mieux qu'une longue et mauvaise explication voila mon code


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package Vodevil::Resource::Queue;
     
    sub new { 
      my $class = shift;
      my @queue = @_;
      return \@queue, $class;
    }
     
    sub enqueue {
      my $q = shift;
      push( @$q, @_);
    }
     
    sub dequeue { 
      my $q = shift;
      return shift @$q;
    }
     
    sub flush {
     my $q = shift;
     @$q = ();
    }
     
    sub count {
     my $q = shift;
     return scalar ( @$q );
    }


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #!/usr/bin/perl -w
    package teste;
     
    sub new {
        my ($class, %cnf) = @_;
        my $list   = $cnf{'list'};
        my $self = bless {
            job    => $list
        }, $class;
        return $self;
    }
     
     
     
    sub mettre {
    my $self = shift;
     for (0..1000000) {
       $self->{job}->enqueue( $_ );
     }
    }
     
     
    package main;
    use Vodevil::Resource::Queue;
    import teste;
     
    my $queue = Vodevil::Resource::Queue->new();
     
    my $teste = teste->new(
                  list => $queue
                );
     
       $teste->mettre();
     
     
    sub evalqueue {
     while ( scalar( @$queue ) > 0 ) {
       my $element = $queue->dequeue;
       print "$element\n";
     }
     sleep(1);
     evalqueue();
    }
     
    evalqueue();
    Enfaite le problème est que je doit attendre l'ensemble des données soit chargés par mettre() et que celui ci ce finisse pour pouvoir lire la file d'attente ce qui pose problème . Quelqu'un aurait il une idée pour pallier a ce problème ?

    merci

  8. #8
    Membre actif Avatar de scaleo
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 327
    Points : 219
    Points
    219
    Par défaut
    As tu essayé de forker le fils lance la fonction principale qui remplie la file et le père lui récupère les données

  9. #9
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    C'est une blague ? Tu ne crées même pas de thread, à quoi t'attendais-tu ? En plus tu es en train de faire de grosses bétises : recréer une classe pour les queues est inutile, je ne vois pas ce que ta classe apporte de plus (en fait elle a même moins de capacités) et en plus elle est complètement buguée (tu ne lockes jamais rien et tu es donc totalement ouvert à toutes les problèmes de synchronisations des threads...).

    Dis nous plutôt ce que tu veux faire, que nous t'expliquions quelle méthode employer.

    --
    Jedaï

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 210
    Points : 99
    Points
    99
    Par défaut
    En fait je veut juste passer des données d'un thread a l'autre, je n'y suis pas arrivé j'ai donc fait ce module pour voir d'ou pourrais bien venir le problème.

  11. #11
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    Ce code fonctionne-t-il sur ta machine ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    #! /usr/bin/perl
    use strict; use warnings;
     
    use threads;
    use Thread::Queue;
     
    my $q = Thread::Queue->new();
     
    my $t = threads->create(\&hello);
    my $t2 = threads->create(\&world);
     
    sub hello {
            $q->enqueue( "Hello", "World" );
    }
     
    sub world {
            print $q->dequeue();
            print " ";
            print $q->dequeue();
            print "\n";
    }
     
    $t->join();
    $t2->join();
    __END__
    --
    Jedaï

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 210
    Points : 99
    Points
    99
    Par défaut
    Oui ce code fonctionne parfaitement

  13. #13
    Membre actif Avatar de scaleo
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 327
    Points : 219
    Points
    219
    Par défaut
    Si j'ai bien compris sa ne marche pas avec du récursif et deux files d'attente ?

    voila une piste j'ai fait un essaie 30s juste pour voir si sa marchais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #! /usr/bin/perl
    use strict;
    use warnings;
     
    use threads;
    use Thread::Queue;
     
    my $q = Thread::Queue->new();
     
    my $t = threads->create(\&hello);
    my $n = threads->create(\&hello2);
    my $t2 = threads->create(\&world);
    my $n2 = threads->create(\&world2);
     
    sub hello {
            $q->enqueue( "Hello", "World" );
     sleep(1); # juste pour éviter un deep recurs
     hello();
    }
     
     
    sub hello2 {
            $q->enqueue( "bonjour", "le monde" );
     sleep(1); # juste pour éviter un deep recurs
     hello2();
    }
     
    sub world {
            print $q->dequeue();
            print " ";
            print $q->dequeue();
            print "\n";
      sleep(1);
      world();
    }
     
    sub world2 {
            print $q->dequeue();
            print " ";
            print $q->dequeue();
            print "\n";
      sleep(1);
      world2();
    }
     
    $t->join();
    $t2->join();
    $n->join();
    $n2->join();
    __END__

  14. #14
    Membre actif Avatar de scaleo
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 327
    Points : 219
    Points
    219
    Par défaut
    J'ai relu ton post, parce que j'avais un doute sur ma réponse .

    En fait tu as un script qui appel une classe a laquel tu passe les files d'attente et dans ton script principale tu récupère les données qui y ont été mises par la classe.

    J'ai fait un script pour comprendre ton problème et je doit avouer qu'il est très heu chiant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #!/usr/bin/perl -w
    package teste;
    use threads;
    use Thread::Queue;
     
    sub new {
        my ($class, %cnf) = @_;
        my $l    = delete $cnf{'gd'};
        my $self = bless {
            t => $l
        }, $class;
        return $self;
    }
     
    my $self;
     
    sub hello {
       $self = shift unless defined $self;
       $self->{t}->enqueue( "Hello", "World" );
     #sleep(1);
     #hello();
    }
     
     
    package main;
    use strict;
    use warnings;
    import teste;
    use threads;
    use Thread::Queue;
     
    my $q = Thread::Queue->new();
     
    my $i = teste->new( gd => $q );
     
       $i->hello();
     
    #my $t = threads->create(\&hello);
    my $t2 = threads->create(\&world);
    sub world {
            print $q->dequeue();
            print " ";
            print $q->dequeue();
            print "\n";
     world();
    }
     
    #$t->join();
    $t2->join();
    Tel quel ce code fonctionne mais et si on change la fonction hello() comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    sub hello {
       $self = shift unless defined $self;
       $self->{t}->enqueue( "Hello", "World" );
     sleep(1);
     hello();
    }

    le script bloque car il n'y a jamais de valeur de retour a $i->hello();

  15. #15
    Membre actif Avatar de scaleo
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 327
    Points : 219
    Points
    219
    Par défaut
    J'ai trouvé la solution il faut forker ,


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    #!/usr/bin/perl -w
    package teste;
    #use threads;
    #use Thread::Queue;
     
    sub new {
        my ($class, %cnf) = @_;
        my $l    = delete $cnf{'gd'};
        my $self = bless {
            t => $l
        }, $class;
        return $self;
    }
     
    my $self;
     
    sub hello {
      $self = shift unless defined $self;
      $self->{t}->enqueue( "Hello", "World" );
     sleep(1);
     hello();
    }
     
     
    package main;
    use strict;
    use warnings;
    import teste;
    use threads;
    use Thread::Queue;
     
    my $q = Thread::Queue->new();
     
    my $i = teste->new( gd => $q );
     my $pid = fork;
     
     if ( $pid == 0 )
     {
         $i->hello();
     }
      else
     {
        my $t2 = threads->create(\&world);
           $t2->join();
      }
     
     
    sub world {
            print $q->dequeue();
            print " ";
            print $q->dequeue();
            print "\n";
     world();
    }


    Donc si comme tu fait tu utilise deux files d'attente il faut forker deux fois
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
     if ( $pid == 0 ) {
         $i->hello();
     }
      else {
       # le thread n'a plus vraiment d'interet
       # my $t2 = threads->create(\&world);
       #   $t2->join();
     
        my $uid = fork;
        if ($uid == 0 ) {
         main->world();
       }
         else {
         main->filedeux();
       }
      }
    Ont peut sans doute faire plus propre mais j'ai pas trouvé

  16. #16
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Points : 8 586
    Points
    8 586
    Par défaut
    On peut faire plus propre, en fait je ne vois même pas pourquoi tu voudrais forker (ce qui foutra la pagaille dans les threads !) ... Par ailleurs tes codes sont plus qu'hasardeux, utiliser deux Thread::Queue ne pose pas de problème particulier par rapport à l'usage d'un seul... Ce code fonctionne très bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #!/usr/bin/perl -w
    package teste;
     
    sub new {
        my ($class, %cnf) = @_;
        my $list   = $cnf{'list'};
        my $self = bless {
            job    => $list
        }, $class;
        return $self;
    }
     
     
     
    sub mettre {
    my $self = shift;
     for (0..1000000) {
       $self->{job}->enqueue( $_ );
     }
     $self->{job}->enqueue( 'end');
    }
     
     
    package main;
    use strict; use warnings;
     
    use threads;
    use Thread::Queue;
     
    my $queue = Thread::Queue->new();
     
    my $teste = teste->new(
                  list => $queue
                );
     
    my $t1 = threads->create( sub { $teste->mettre() } );
    my $t2 = threads->create( \&evalqueue );
     
    sub evalqueue {
     while ( $queue->pending() > 0 ) {
       my $element = $queue->dequeue();
       return if( $element eq 'end' ); 
       print "$element\n";
     }
     sleep(1);
     evalqueue();
    }
     
    $t2->join();
    $t1->join();
    __END__
    --
    Jedaï

  17. #17
    Membre actif Avatar de scaleo
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 327
    Points : 219
    Points
    219
    Par défaut
    Effectivement c'est bien plus propre et conçis

Discussions similaires

  1. [QtCore] Petit souci avec un slot d'une classe différente
    Par Jiyuu dans le forum PyQt
    Réponses: 1
    Dernier message: 18/01/2011, 21h21
  2. [Prototype] Petit souci avec une requête
    Par spy74 dans le forum Bibliothèques & Frameworks
    Réponses: 2
    Dernier message: 14/01/2009, 18h54
  3. [VBA-E]Petit souci avec une boucle
    Par Mou dans le forum Macros et VBA Excel
    Réponses: 19
    Dernier message: 17/04/2007, 15h15
  4. Petit soucis avec une requête
    Par Jeetiz dans le forum Requêtes
    Réponses: 4
    Dernier message: 01/02/2007, 14h53
  5. petit soucie avec POE ( Component::Pool::Thread )
    Par siaoly dans le forum Modules
    Réponses: 21
    Dernier message: 22/07/2006, 18h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo