Попробуйте следующее. Если я делаю это с помощью элемента управления 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
}
}
}
Да: 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
, которое ваш коллега украдкой добавил в середине вашей функции, или просто достигнув конца функция.
AFAIK, нет встроенной поддержки в C ++. Вам придется синхронизировать операции стека с помощью простого инструмента синхронизации. CriticalSection будет работать, если потоки принадлежат одному и тому же процессу, в противном случае перейдите на Mutex.
Текущий стандарт C ++ вообще не касается потоков, поэтому ответ на ваш первый вопрос - нет. И вообще, плохая идея - встроить блокировку в базовые структуры данных, потому что у них недостаточно информации, чтобы выполнить ее правильно и / или эффективно. Вместо этого блокировка должна выполняться в классах, которые используют структуры данных - другими словами, в ваших собственных классах приложений.
Нет встроенного механизма для поддержки этого ни в C ++, ни в библиотеках Boost (примечание: некоторые люди написали поточно-ориентированные стеки и т. Д. В стиле Boost ]). Вам придется заимствовать некоторый код или готовить в своей собственной синхронизации.
Обратите внимание, что ваш случай, вероятно, требует защиты с несколькими читателями для одного записывающего устройства (SWMRG), в которой несколько потоков записывающего устройства могут получить доступ к стеку (но только один в определенный момент времени) и в котором несколько считывателей могут получить доступ к стеку (многие в определенный момент времени). Рихтер имеет эталонную реализацию .
Если вы не хотите использовать блокировку, вам нужно использовать стек без блокировки. На самом деле это не так сложно (очередь без блокировки сложнее). Вам нужен примитив сравнения-обмена для конкретной платформы, такой как InterlockedCompareExchange в Windows, но это не сложно абстрагировать.
Смотрите пример в C #:
Если вы работаете в Windows, SLIST реализует стек без блокировок (со структурами SLIST_HEADER и SLIST_ENTRY
).
Алгоритм реализован с использованием довольно тривиального push / pop стек односвязных списков с использованием взаимосвязанных функций. Единственный неочевидный элемент - это увеличение счетчика, чтобы избежать проблем с ABA.