Метод drawLayer делегата CALayer не вызывается

То, что вы читаете, не означает, что вы думаете, что это значит. Прежде всего, попробуйте страницу msdn для самой shared_ptr .

Прокрутите вниз в раздел «Замечания», и вы попадете в мясо проблемы. В принципе, shared_ptr<> указывает на «блок управления», который отслеживает, сколько объектов shared_ptr<> фактически указывают на объект «Real». Поэтому, когда вы это делаете:

shared_ptr ptr1 = make_shared();

Пока есть только один вызов для выделения памяти здесь через make_shared, есть два «логических» блока, которые вы не должны относиться к ним одинаково. Одним из них является int, в котором хранится фактическое значение, а другое - блок управления, в котором хранится все shared_ptr<> «магия», которая заставляет его работать.

Это только сам блок управления, является потокобезопасным.

Я положил это на свою линию для акцента. Содержимое shared_ptr не является потокобезопасным и не записывается в тот же экземпляр shared_ptr. Вот что продемонстрировать, что я имею в виду:

// In main()
shared_ptr global_instance = make_shared();
// (launch all other threads AFTER global_instance is fully constructed)

//In thread 1
shared_ptr local_instance = global_instance;

Это прекрасно, на самом деле вы можете делать это во всех потоках столько, сколько хотите. И тогда, когда local_instance разрушается (выходить из области видимости), он также является потокобезопасным. Кто-то может получить доступ к global_instance, и это не изменит ситуацию. Фрагмент, который вы вытащили из msdn, в основном означает, что «доступ к блоку управления является потокобезопасным», поэтому другие экземпляры shared_ptr<> могут быть созданы и уничтожены на разных потоках столько, сколько необходимо.

//In thread 1
local_instance = make_shared();

Это хорошо. Он будет воздействовать на объект global_instance, но только косвенно. Контрольный блок, на который он указывает, будет уменьшаться, но делается поточно-безопасным способом. local_instance больше не будет указывать на тот же объект (или контрольный блок), как это делает global_instance.

//In thread 2
global_instance = make_shared();

Это почти наверняка не очень хорошо, если global_instance доступен из любых других потоков (что вы говорите, что делаете). Для этого нужна блокировка, если вы делаете это, потому что пишете там, где живет global_instance, а не только чтение от него. Поэтому запись в объект из нескольких потоков является плохим, если только вы не охраняете его через блокировку. Таким образом, вы можете читать из global_instance объекта, назначая из него новые shared_ptr<> объекты, но вы не можете его записать.

// In thread 3
*global_instance = 3;
int a = *global_instance;

// In thread 4
*global_instance = 7;

Значение a не определено. Это может быть 7, или может быть 3, или это может быть что-то еще. Безопасность потоков экземпляров shared_ptr<> применяется только к управлению экземплярами shared_ptr<>, которые были инициализированы друг от друга, а не тем, на что они указывают.

Чтобы подчеркнуть, что я имею в виду, посмотрите на это:

shared_ptr global_instance = make_shared(0);

void thread_fcn();

int main(int argc, char** argv)
{
    thread thread1(thread_fcn);
    thread thread2(thread_fcn);
    ...
    thread thread10(thread_fcn);

    chrono::milliseconds duration(10000);
    this_thread::sleep_for(duration);

    return;
}

void thread_fcn()
{
    // This is thread-safe and will work fine, though it's useless.  Many
    // short-lived pointers will be created and destroyed.
    for(int i = 0; i < 10000; i++)
    {
        shared_ptr temp = global_instance;
    }

    // This is not thread-safe.  While all the threads are the same, the
    // "final" value of this is almost certainly NOT going to be
    // number_of_threads*10000 = 100,000.  It'll be something else.
    for(int i = 0; i < 10000; i++)
    {
        *global_instance = *global_instance + 1;
    }
}

A shared_ptr<> - механизм, гарантирующий, что владельцы нескольких объектов гарантируют разрушение объекта, а не механизм для обеспечения нескольких потоков может получить доступ к объекту правильно. Вам еще нужен отдельный механизм синхронизации для безопасного использования в нескольких потоках (например, std :: mutex ).

Лучший способ подумать об этом IMO - это то, что shared_ptr<> делает что несколько копий, указывающих на одну и ту же память, не имеют проблем с синхронизацией самого , но ничего не делают для объекта, на который указывает. Относитесь к этому так.

13
задан Julian D. 1 August 2013 в 17:48
поделиться

1 ответ

drawLayer: inContext: не будет вызываться, если ваш кадр CGRectZero или вне экрана. Кроме того, если ваш CALayer не прикреплен к существующему экранному слою, он никогда не будет рисоваться, независимо от того, сколько раз вы вызываете setNeedsDisplay

23
ответ дан 1 December 2019 в 17:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: