HandyJSON
- еще один вариант для работы с JSON для вас. https://github.com/alibaba/handyjson
Он отделяет JSON от объекта напрямую. Нет необходимости указывать отношение отображения, нет необходимости наследовать из NSObject. Просто определите свой чистый-быстрый класс / struct и десериальный JSON.
class Animal: HandyJSON { var name: String? var id: String? var num: Int? required init() {} } let jsonString = "{\"name\":\"cat\",\"id\":\"12345\",\"num\":180}" if let animal = JSONDeserializer.deserializeFrom(jsonString) { print(animal) }
Вы никогда не упоминали тип finished_flag...
Если это - прямой bool, то это могло бы работать, но это - конечно, плохая практика по нескольким причинам. Во-первых, некоторые компиляторы будут кэшировать чтения finished_flag переменной, так как компилятор не всегда берет то, что это пишется в другим потоком. Можно обойти это путем объявления bool энергозависимого, но это берет нас в неправильном направлении. Даже если бы чтения и записи происходят, как Вы ожидали бы, нет ничего, чтобы мешать планировщику ОС чередовать два потока половина пути посредством чтения / запись. Это не могло бы быть такой проблемой здесь, где у Вас есть чтение того и одна запись op в отдельных потоках, но это - хорошая идея запуститься, поскольку Вы означаете продолжать.
Если, с другой стороны, это - ориентированный на многопотоковое исполнение тип, как CEvent в MFC (или equivilent в повышении) затем, необходимо быть в порядке. Это - лучший подход: используйте ориентированные на многопотоковое исполнение объекты синхронизации для коммуникации межпотока, даже для простых флагов.
Вместо того, чтобы использовать членскую переменную, чтобы сигнализировать, что поток сделан, почему бы не использовать a condition
? Вы, уже пользуются библиотеками повышения, и condition
часть библиотеки потока.
Попробуйте. Это позволяет рабочему потоку 'сигнализировать', что это, закончился, и основной поток может проверить во время выполнения, если условие было сообщено и затем делает то, что это должно сделать с завершенной работой. В ссылке существуют примеры.
Как общий случай я был бы фирн делать предположение, что ресурс будет только изменен потоком. Вы могли бы знать то, для чего это, однако кто-то еще не мог бы - порождение никаких концов горя, поскольку основной поток думает, что работа сделана и пытается получить доступ к данным, которые не корректны! Это могло бы даже удалить его, в то время как рабочий поток все еще использует его и заставляет приложение отказывать. Используя a condition
поможет этому.
Взгляд на thread
документация, Вы могли также звонить thread.timed_join
в основном потоке. timed_join
будет ожидать указанной суммы для потока для 'присоединений' (соединение означает, что поток имеет finsihed),
Если Вы действительно хотите войти в детали коммуникации между потоками через общую память, даже объявляя, что энергозависимая переменная не будет достаточно, даже если компилятор действительно будет использовать соответствующую семантику доступа, чтобы гарантировать, что это не получит устаревшую версию данных после проверки флага. ЦП может выпустить чтения и пишет не в порядке как долго (x86, обычно не делает, но PPC определенно делает) и нет ничего в C++ 9x, который позволяет компилятору генерировать код для упорядочивания доступов памяти соответственно.
Серия Effective Concurrency Herb Sutter имеет чрезвычайно подробно взгляд на то, как мир C++ пересекает многоядерный/многопроцессорный мир.
Я не означаю быть предполагаемым, но кажется, что цель Вашей finished_flag переменной состоит в том, чтобы приостановить основной поток (в какой-то момент), пока поток thrd не завершился.
Самый легкий способ сделать это должно использовать повышение:: поток:: соединение
// launch the thread...
thrd = new boost::thread(boost::bind(&myclass::mymethod, this, &finished_flag);
// ... do other things maybe ...
// wait for the thread to complete
thrd.join();
При установке потока флаг (или сигнал событие), прежде чем это выйдет, является состоянием состязания. Поток не обязательно возвратился к ОС все же и может все еще выполняться.
Например, рассмотрите программу, которая загружает динамическую библиотеку (псевдокод):
lib = loadLibrary("someLibrary");
fun = getFunction("someFunction");
fun();
unloadLibrary(lib);
И давайте предположим, что эта библиотека использует Ваш поток:
void someFunction() {
volatile bool finished_flag = false;
thrd = new boost::thread(boost::bind(&myclass::mymethod, this, &finished_flag);
while(!finished_flag) { // ignore the polling loop, it's besides the point
sleep();
}
delete thrd;
}
void myclass::mymethod() {
// do stuff
finished_flag = true;
}
Когда myclass::mymethod()
наборы finished_flag
кому: true
, myclass::mymethod()
еще не возвратился. По крайней мере это все еще должно выполнить какую-то инструкцию "по возврату" (если не намного больше: деструкторы, управление обработчиком исключений, и т.д.). Если выполнение потока myclass::mymethod()
предвосхищен перед той точкой, someFunction()
возвратится к программе вызова, и программа вызова разгрузит библиотеку. Когда выполнение потока myclass::mymethod()
как планируют, будет работать снова, адрес, содержащий инструкцию "по возврату", больше не действителен, и катастрофические отказы программы.
Решение было бы для someFunction()
звонить thrd->join()
перед возвратом. Это гарантировало бы, что поток возвратился к ОС и больше не выполняется.