Как разделить последовательные очереди отправки между классами? - PullRequest
4 голосов
/ 26 июля 2011

Я заметил, что они не возвращают указатели при создании, а являются реальными объектами. Итак, чтобы получить указатель, я пытаюсь объявить это так:

dispatch_queue_t* queue;
*queue = dispatch_queue_create("double_buffer_protection_queue", DISPATCH_QUEUE_SERIAL);

Программист C ++ во мне говорит, что это должно работать, но выдает ошибку BAD_ACCESS, поэтому я полагаю, что я подхожу к этому неправильно.

Если мне нужна последовательная очередь, к которой может обращаться любой объект в моей программе, как мне это сделать? Код, который я показал выше, предназначен для использования в классе AppDelegate.

Ответы [ 2 ]

4 голосов
/ 30 июля 2011

Из GCD Reference : typedef struct dispatch_queue_s *dispatch_queue_t;

Может быть, я лаю не на том дереве, но моя интуиция подсказала бы мне, что более идиоматичным решением может быть использование функции dispatch_once внутри метода класса, чтобы получить очередь, в которую могут отправлять работу несколько экземпляров класса (это не C ++ но вы поняли основную идею):

+ (dispatch_queue_t)sharedQueue
{
    static dispatch_once_t pred;
    static dispatch_queue_t sharedDispatchQueue;

    dispatch_once(&pred, ^{
        sharedDispatchQueue = dispatch_queue_create("theSharedQueue", NULL);
    });

    return sharedDispatchQueue;
}

dispatch_once гарантирует, что создание очереди происходит только один раз за все время выполнения, поэтому вы можете безопасно и дешево вызывать [YourClass sharedQueue] так часто, как вам нужно, в любом месте.

Однако моя интуиция также сказала бы, что разделение очередей между классами / объектами пахнет немного плохо. Если вы просто хотите, чтобы очередь всего приложения отправляла разные задания, хватит ли глобальной очереди? Если вы хотите интенсивно работать с большими коллекциями объектов, я бы инстинктивно создал для них отдельную очередь. Может быть, есть более элегантный способ делать то, что вы хотите?

1 голос
/ 26 июля 2011

В Grand Central Dispatch использование реальных объектов является правильным способом. Например,

class Manager
{
    Manager()
    {
        m_queue = dispatch_queue_create("double_buffer_protection_queue", DISPATCH_QUEUE_SERIAL);

        m_worker = new Worker(m_queue);
    }

    ~Manager()
    {
        dispatch_release(m_queue);
        delete m_worker;
    }

    dispatch_queue_t m_queue;
    Worker *m_worker;
}

И тогда другой владелец очереди должен сохранить и освободить ее сам, как объекты Objective-C.

class Worker
{
    Worker(dispatch_queue_t queue)
    // Worker(dispatch_queue_t &queue) /* reference might be ok. */
    {
        m_queue = queue;
        dispatch_retain(m_queue);
    }

    ~Worker()
    {
        dispatch_release(m_queue);
    }

    dispatch_queue_t m_queue;
}
...