Ориентированная на многопотоковое исполнение стопка C++

Попробуйте следующее. Если я делаю это с помощью элемента управления UITableView, он работает.

import UIKit

class ViewController: UIViewController {
    @IBAction func snapTapped(_ sender: UIButton) {
        UIGraphicsBeginImageContextWithOptions(imageScrollView.bounds.size, true, 1.0)
        imageScrollView.drawHierarchy(in: CGRect(origin: CGPoint.zero, size: imageScrollView.bounds.size), afterScreenUpdates: true)
        if let image = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            myImageView.image = image
        }
    }
}
14
задан Piotr Dobrogost 11 July 2009 в 19:13
поделиться

6 ответов

Да: Boost.Thread великолепен и должен очень хорошо соответствовать вашим потребностям. (В наши дни многие люди говорят, что вы можете почти считать Boost встроенной функциональностью.)

По-прежнему нет класса, который можно было бы использовать «из коробки», но как только у вас есть примитивы синхронизации, на самом деле довольно просто реализовать собственную потоково-безопасную оболочку, например, std :: stack . Это может выглядеть примерно так (не реализуя каждый метод ...):

template <typename T> class MyThreadSafeStack {
  public:
    void push(const T& item) {
      boost::mutex::scoped_lock lock(m_mutex);
      m_stack.push(item);
    }
    void pop() {
      boost::mutex::scoped_lock lock(m_mutex);
      m_stack.pop();
    }
    T top() const { // note that we shouldn't return a reference,
                    // because another thread might pop() this
                    // object in the meanwhile
      boost::mutex::scoped_lock lock(m_mutex);
      return m_stack.top();
    }

  private:
    mutable boost::mutex m_mutex;
    std::stack<T> m_stack;
}    

Если вы новичок в C ++, изучите RAII . Относящийся к этому случаю, Boost.Thread имеет классы «блокировки области действия», чтобы было трудно выстрелить себе в ногу, забыв снять блокировку.

Если вы когда-нибудь будете писать код, подобный этому:

void doStuff() {
  myLock.lock();
  if (!condition) {
    reportError();
    myLock.unlock();
    return;
  }
  try {
    doStuffThatMayThrow();
  }
  catch (std::exception& e) {
    myLock.unlock();
    throw e;
  }
  doMoreStuff();
  myLock.unlock();
}

, тогда ты просто должен сказать нет, и вместо этого перейдите в RAII (синтаксис не из Boost):

void doStuff() {
  scoped_lock lock;
  if (!condition) {
    reportError();
    return;
  }
  doStuffThatMayThrow();
  doMoreStuff();
}

Дело в том, что когда объект scoped_lock выходит из области видимости, его деструктор освобождает ресурс - в данном случае - блокировку. Это всегда будет происходить независимо от того, выйдете ли вы из области видимости, вызвав исключение или выполнив нечетное выражение return , которое ваш коллега украдкой добавил в середине вашей функции, или просто достигнув конца функция.

21
ответ дан 1 December 2019 в 09:33
поделиться

AFAIK, нет встроенной поддержки в C ++. Вам придется синхронизировать операции стека с помощью простого инструмента синхронизации. CriticalSection будет работать, если потоки принадлежат одному и тому же процессу, в противном случае перейдите на Mutex.

1
ответ дан 1 December 2019 в 09:33
поделиться

Текущий стандарт C ++ вообще не касается потоков, поэтому ответ на ваш первый вопрос - нет. И вообще, плохая идея - встроить блокировку в базовые структуры данных, потому что у них недостаточно информации, чтобы выполнить ее правильно и / или эффективно. Вместо этого блокировка должна выполняться в классах, которые используют структуры данных - другими словами, в ваших собственных классах приложений.

4
ответ дан 1 December 2019 в 09:33
поделиться

Нет встроенного механизма для поддержки этого ни в C ++, ни в библиотеках Boost (примечание: некоторые люди написали поточно-ориентированные стеки и т. Д. В стиле Boost ]). Вам придется заимствовать некоторый код или готовить в своей собственной синхронизации.

Обратите внимание, что ваш случай, вероятно, требует защиты с несколькими читателями для одного записывающего устройства (SWMRG), в которой несколько потоков записывающего устройства могут получить доступ к стеку (но только один в определенный момент времени) и в котором несколько считывателей могут получить доступ к стеку (многие в определенный момент времени). Рихтер имеет эталонную реализацию .

1
ответ дан 1 December 2019 в 09:33
поделиться

Если вы не хотите использовать блокировку, вам нужно использовать стек без блокировки. На самом деле это не так сложно (очередь без блокировки сложнее). Вам нужен примитив сравнения-обмена для конкретной платформы, такой как InterlockedCompareExchange в Windows, но это не сложно абстрагировать.

Смотрите пример в C #:

http://www.boyet.com /Articles/LockFreeRedux.html

1
ответ дан 1 December 2019 в 09:33
поделиться

Если вы работаете в Windows, SLIST реализует стек без блокировок (со структурами SLIST_HEADER и SLIST_ENTRY ).

Алгоритм реализован с использованием довольно тривиального push / pop стек односвязных списков с использованием взаимосвязанных функций. Единственный неочевидный элемент - это увеличение счетчика, чтобы избежать проблем с ABA.

0
ответ дан 1 December 2019 в 09:33
поделиться
Другие вопросы по тегам:

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