7
votes

Opérations de barrière en nsopérationQueue

Comment pouvons-nous mettre en œuvre le comportement équivalent de Dispatch_Barrier_ASync à l'aide de NsoperationQueue ou toute structure de données définie par l'utilisateur basée sur nsoperationqueue

L'exigence est, chaque fois qu'une opération barrière est soumise, il devrait attendre que toutes les opérations non barrière soumises plus tôt ont terminé leur exécution et bloque d'autres opérations soumises après cela. < / p>

  • Les opérations non barrière devraient pouvoir effectuer simultanément.
  • Les opérations de barrière doivent exécuter en série.

    NB: n'utilisant pas GCD , car il ne fournit pas (ou au moins difficile) beaucoup d'accès sur les opérations, comme annuler une opération unique, etc.


2 commentaires

Vous ne pouvez pas non plus annuler Nsoperation si c'est déjà en cours d'exécution.


@ CY-4HAH Je n'ai pas l'intention d'annuler une nsopération en cours d'exécution et ni le Dispatch_Barrier_ASync ne le fait. La fonction de barrière attendra que les opérations précédentes se terminent.


4 Réponses :


4
votes

Créer un Nsoperation C'est votre barrière, puis Utilisez : xxx

pour faire cette opération de barrière en fonction de tous ceux que vous vouloir venir avant cela.


1 commentaires

Cela remplira la moitié de mes exigences que. Mais j'ai eu l'idée. Merci. :)



3
votes

Je ne pense pas qu'il soit possible de créer un objet nsoperation qui vous donne le même type de fonctionnalité, les barrières ont plus à voir avec la manière dont la file d'attente fonctionne.

La principale différence entre l'utilisation d'une barrière et le mécanisme de dépendance des nsopérations est, dans le cas d'une barrière, la file d'attente de fil attend jusqu'à ce que tous les opérations simultanées sont terminées, puis il exécute votre barrière. Bloc, tout en veillant à ce que tous les nouveaux blocs soumis et tout blocage en attente ne fonctionne pas jusqu'à ce que le bloc critique ait été passé.

avec un nsoperationqueur , il est impossible de configurer la file d'attente de manière à appliquer une barrière appropriée: tout nsoperation S ajouté à la file d'attente avant votre Critique nsoperation doit être explicitement enregistré comme une dépendance avec le travail critique, et une fois que le travail critique a démarré, vous devez veiller explicitement le NsoperationQueue pour vous assurer que aucun autre client ne fait pression sur elle avant que le travail critique ait fini; Vous gardez la file d'attente en ajoutant le travail critique comme une dépendance pour les opérations ultérieures.

(dans le cas où vous savez qu'il n'y a qu'un seul travail critique à la fois, cela sonne quelque chose facile, mais il y aura probablement des emplois critiques NO à la fois, ce qui signifie garder une trace de Les emplois de commandes sont soumis, gérant la dépendance relative des emplois critiques par rapport à leurs emplois à charge - certains emplois critiques peuvent attendre les autres, certains doivent être exécutés dans un ordre particulier relatif aux autres ... Yikes.)

Il serait peut-être possible d'obtenir ce niveau de fonctionnalité en configurant un nsoperationqueur avec un travail concomitant max d'un, mais que Sorta défait le but de le faire, je pense. Vous pourriez également être en mesure de faire ce travail en enveloppant un nsoperationqueur dans un objet de façade qui protège nsoperations soumis "de manière critique".


1 commentaires

C'est plus ou moins ce que je pensais, mais la réponse de Clay en plus explicite. Et bien sûr, il ne peut pas mettre en œuvre exactement ce que GCD fait avec une opération de barrière. Merci pour la belle explication quand même. :)



4
votes

Ceci est plus ou moins ce que Jeffamaphone disait, mais j'ai mis un GIST qui devrait, dans un contour approximatif, faire ce que vous demandez.

i Créez un nsmutableRay code> de NsoperationQueue Code> S, qui sert de "file d'attente de files d'attente". Chaque fois que vous ajoutez un objet barrierOPERATION CODE>, vous tapez sur une file d'attente em> Suspendue em> à la fin. Qui devient l'addieue code>, à laquelle vous ajoutez des opérations ultérieures. P> xxx pré>

quand un Nsoperationqueur code> finition, il est apparu et Le prochain commence à courir. P>

- (void)popQueue
{
    @synchronized (self) {
        NSAssert([_queueOfQueues count], @"should always be one to pop");
        [_queueOfQueues removeObjectAtIndex:0];

        if ([_queueOfQueues count]) {
            // first queue is always running, all others suspended
            [(NSOperationQueue *)_queueOfQueues[0] setSuspended:NO];
        }
    }
}


3 commentaires

Non, ce n'était pas une mission, alors grades pour vous. : P. Il faisait partie de l'exigence de mon projet d'entreprise où je voulais remplacer le GCD avec NsoperationQueue pour obtenir une plus grande flexibilité et une facilité de gestion. Eh bien, j'avais l'idée de la mettre en œuvre à l'aide de dépendances, mais je voulais juste être sûr que c'est la meilleure façon possible et avait besoin d'une solution plus propre que votre réponse fournie. :)


Oh, attends, je l'obtiens. Retiré.


BTW, ici j'ai trouvé quelques autres alternatives. Les commentaires de Daniel sur Ce semble assez utile dans ce contexte.



0
votes

juste une autre solution ... ne me blesse pas.

TODO: Enregistrer l'origine Achèvement et Self.MaxConCurrentOperationCount = 1 Définit la file d'attente en série sur l'ajout. Mais devrait avant exécution. xxx


0 commentaires