C++: Много поточная обработка и подсчет ссылок

Мое решение сравнивает объекты, а не массивы. Это будет работать так же, как у Томаша, поскольку массивы являются объектами, но без предупреждения:

Object.prototype.compare_to = function(comparable){

    // Is the value being compared an object
    if(comparable instanceof Object){

        // Count the amount of properties in @comparable
        var count_of_comparable = 0;
        for(p in comparable) count_of_comparable++;

        // Loop through all the properties in @this
        for(property in this){

            // Decrements once for every property in @this
            count_of_comparable--;

            // Prevents an infinite loop
            if(property != "compare_to"){

                // Is the property in @comparable
                if(property in comparable){

                    // Is the property also an Object
                    if(this[property] instanceof Object){

                        // Compare the properties if yes
                        if(!(this[property].compare_to(comparable[property]))){

                            // Return false if the Object properties don't match
                            return false;
                        }
                    // Are the values unequal
                    } else if(this[property] !== comparable[property]){

                        // Return false if they are unequal
                        return false;
                    }
                } else {

                    // Return false if the property is not in the object being compared
                    return false;
                }
            }
        }
    } else {

        // Return false if the value is anything other than an object
        return false;
    }

    // Return true if their are as many properties in the comparable object as @this
    return count_of_comparable == 0;
}

Надеюсь, это поможет вам или кому-либо еще в поисках ответа.

6
задан Fire Lancer 16 July 2009 в 14:30
поделиться

10 ответов

Сделайте подсчет ссылок атомарным, и вам не потребуется никакой блокировки. В Windows можно использовать :: InterlockedIncrement и :: InterlockedDecrement. В C ++ 0x есть атомарный <>.

16
ответ дан 8 December 2019 в 02:22
поделиться

Если вы не знаете, что это конкретное узкое место, я бы просто использовал boost :: shared_ptr

Это очень быстро, однако есть небольшие дополнительные накладные расходы в дополнительном блоке управления, который выделено. С другой стороны, у этого есть много преимуществ:

  • Он переносится
  • Это правильно
  • Вам не нужно тратить на это свои мыслительные циклы, оставляя вам время, чтобы на самом деле сделать работу
  • Это быстро
  • Это отраслевой стандарт, и другие программисты сразу поймут его.
  • Он заставляет вас использовать boost , что, если вы этого не сделаете, вы должны быть

Также обратите внимание, вы, вероятно, не будете требуется блокировка чтения / записи для объекта с подсчетом ссылок. Разногласия минимальны, а дополнительные накладные расходы полностью подавят любые ваши преимущества.

10
ответ дан 8 December 2019 в 02:22
поделиться

osg, OpenSceneGraph имеет такую ​​структуру.

вы наследуете свои классы от osg :: Referenced, и вам наплевать на деструктор даже в многопоточности.

вы просто создайте классы как:

osg::ref_ptr<MyClass> m = new MyClass();

вместо:

MyClass* m = new MyClass();
2
ответ дан 8 December 2019 в 02:22
поделиться

Основная проблема заключается в том, что вы не получаете ссылку до возврата CreateTexture. Если вы используете такое открытое кодирование, самый простой способ справиться с этим - установить блокировку TexPool, которая также используется при освобождении ссылок перед удалением, например:

// PSEUDOCODE WARNING: --refcnt MUST be replaced by an atomic decrement-and-test
// Likewise, AddRef() MUST use an atomic increment.
void DecRef() {
    if (!--refcnt) {
        lock();
        if (!refcnt)
            delete this;
        unlock();
    }
}

и:

Texture *CreateTexture(const std::string &file)
{
    lock();

    TexPoolIterator i = TexPool.find(file);
    if(i != TexPool.end()) {
        *i->AddRef();
        unlock();
        return *i;
    }
    unlock();
    return new Texture(file);
}

Тем не менее, как и другие Как уже упоминалось, boost :: shared_ptr (также известный как std :: tr1 :: shared_ptr) реализует все это без блокировки, безопасным способом, а также имеет поддержку слабых указателей, которые помогут с вашим кешем текстур.

1
ответ дан 8 December 2019 в 02:22
поделиться

boost :: shared_ptr и Poco :: SharedPtr заключают эту идиому в отдельный интеллектуальный указатель.

Если вам нужен навязчивый подсчет ссылок, как вы продемонстрировали выше, AutoPtr Poco - хорошая работающая реализация.

] РЕДАКТИРОВАТЬ: Я бы добавил ссылки, но у меня была слишком низкая репутация. Найдите в Google любое из названий классов, и вы должны найти свой путь.

1
ответ дан 8 December 2019 в 02:22
поделиться

Если вы не хотите использовать ускорение или C ++ 0X, но по-прежнему хотите использовать безблокировочный счетчик ссылок, вы можете сделать это, включив правильный атомарный инкремент / атомный декремент для конкретной платформы ассемблерные процедуры в вашем коде. В качестве примера приведем класс AtomicCounter, который я использую для подсчета ссылок; он работает под наиболее распространенными ОС:

https://public.msli.com/lcs/muscle/html/AtomicCounter_8h_source.html

Да, это неприятный беспорядок из #ifdefs. Но это работает.

6
ответ дан 8 December 2019 в 02:22
поделиться

Вы хотели потокобезопасный или атомарный потокобезопасный? boot :: shared_ptr просто потокобезопасен. Вам все еще нужно «владеть» shared_ptr, чтобы безопасно его копировать.

Я сделал несколько экспериментальных вещей по атомарно-поточно-безопасному подсчету ссылок здесь, на http://atomic-ptr-plus.sourceforge.net/ , который может дать вам представление о том, в чем дело.

2
ответ дан 8 December 2019 в 02:22
поделиться

Ваш кеш должен использовать boost :: weak_ptr или аналогичную конструкцию.

1
ответ дан 8 December 2019 в 02:22
поделиться

Взгляните на этот pdf: http://www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf

Здесь описывается ссылка система подсчета, которая не требует блокировки. (Ну, вам нужно «приостанавливать» потоки по одному, что может считаться блокировкой.) Он также собирает циклы мусора. Недостаток в том, что это намного сложнее. Есть также несколько важных вещей, оставленных читателю в качестве упражнения. Например, что происходит, когда создается новый поток или удаляется старый, или как работать с по сути ациклическими объектами. (Если вы решите это сделать, дайте мне знать, как вы это делали.)

0
ответ дан 8 December 2019 в 02:22
поделиться

Я думаю, вам действительно нужны критические секции для этого конкретного проекта. Одно место, где это требуется, - это CreateTexture, потому что в противном случае вы рискуете иметь более одного идентичного объекта текстуры в системе. И вообще, если несколько потоков могут создавать и уничтожать одну и ту же текстуру, это делает ее «изменяемым общим состоянием».

0
ответ дан 8 December 2019 в 02:22
поделиться
Другие вопросы по тегам:

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