2010-01-13 13 views
2

J'ai un wrapper autour d'un fichier std :: deque que j'utilise pour mettre en file d'attente des données audio (en entrant dans les blocs via libavcodec, si cela est important).Ajouter un bloc d'éléments à la fin de std :: deque

C'est la fonction qui prend un tampon de données 16 bits et ajoute à la deque

void AVAudioBuffer::enqueue(int16_t* src, size_t num, double pts) { 
    // Save current size of buffer 
    size_t size = data_buffer_.size(); 

    lock(); 
    data_buffer_.insert(data_buffer_.end(), src, src+num); 
    unlock(); 

// Push PTS value onto queue 
if (pts != AV_NOPTS_VALUE) { 
    pts_values_.push_back(pair<int,double>(size, pts)); 
    } 
} 

Définitions de verrouillage/déverrouillage:

void lock()  { SDL_mutexP(mute_access_);  } 
void unlock()  { SDL_mutexV(mute_access_);  } 

Mon problème est, lorsque le data_buffer_ L'instruction .insert est incluse dans le code, le thread dans lequel cette fonction se trouve s'exécutera une fois puis se verrouillera. Si je supprime le code, cela fonctionne. J'ai essayé de remplacer l'insertion par une itération manuelle des données src, en appelant push_back() pour chaque élément, ce qui provoque également le verrouillage du thread.

Est-ce une manière valide d'ajouter des données à un deque? Je l'ai essayé dans un programme de test et cela a semblé fonctionner correctement, et la documentation semble impliquer que tout va bien. Pourquoi cela ferait-il mourir mon fil?

Informations mises à jour: Des messages d'erreur ont été ajoutés lorsque le verrouillage/déverrouillage a échoué, et les deux réussissent très bien. Je les ai instrumentés pour vérifier qu'ils sont exécutés par paires, et ils le sont. Ça doit être quelque chose avec l'appel deque :: insert qui gâche les choses, je peux l'enlever et les choses bougent à nouveau.

Mise à jour: J'ai trouvé le problème, je refactorisé le code et a raté une constante de sorte que le dequeue vérifiait toujours aussi complète, ce qui provoque une boucle = (

+0

Qu'entendez-vous par "provoque le thread à verrouiller"? Si vous le regardez dans le débogueur, où est-il "verrouillé" (callstack)? –

+0

Désolé les fonctions lock()/unlock() sont des wrappers autour des mutex SDL, je mettrai à jour le poste avec leurs définitions. –

+0

Pouvez-vous poster du code plus ou moins complet, y compris la partie deque et les fonctions de verrouillage/déverrouillage. Vous n'utilisez pas la taille et pts vars dans le code affiché, donc vous ne montrez probablement pas quelque chose d'important qui pourrait conduire à la découverte :) –

Répondre

0

sonne comme vous avez besoin de verrouillage de fil Si un autre thread est en train de lire. (et donc la mise à jour) de la file d'attente puis tu dois le verrouiller

oups - il y a un verrou il y a Je pense que le verrou ne fonctionne pas ou que le lecteur ne verrouille

est-ce que le verrou de fil de lecteur. Etes-vous sûr que le verrou est effectivement verrouillé?

1

Cette méthode d'insertion dans un deque est parfaitement valide.

La source de votre blocage est probablement dans le verrouillage lui-même. Tous les accès à data_buffer_ doivent être synchronisés (lecture et écriture), y compris l'appel à data_buffer_.size(). Si un thread lit depuis data_buffer_ alors qu'un autre thread y écrit, vous pouvez obtenir un comportement aléatoire non défini.

Si, après la fixation, il se bloque toujours, recherchez des paires de verrouillage()/déverrouillage() ou des blocages inadéquats. Je suppose également que vous utilisez des verrous atomiques.

En regardant votre code mis à jour, vous devez également synchroniser les accès à pts_values_.

+0

C'est ce qui m'intéressait, devinez en l'absence de ce que ce soit un mauvais appel, je vais juste devoir creuser pour comprendre où il se bloque. –

1

Étant donné que l'utilisation du langage STL est correcte comme indiqué, je suggère de regarder de plus près la synchronisation. Les fonctions de mutex SDL renvoient -1 en cas d'erreur. Mettez une vérification pour cela dans le lock() et unlock() et déclencher une exception, par exemple. Vous pouvez également enregistrer un ID de thread sur l'entrée dans ces fonctions.

Je vérifie également que les valeurs d'entrée sont correctes - make num ne dépasse pas le tampon d'entrée.

Un plug pour les bonnes techniques C++ - prenez l'habitude d'utiliser RAII pour la gestion des verrous.C'est ce que les destructeurs C++ ont été inventés pour :)

+0

Ajout de messages d'erreur si le statut de l'un ou l'autre est -1, et il semble que le verrouillage et le déverrouillage fonctionnent correctement. –