nlib
exi/multithread/multithread.cpp

複数のスレッドで(別個の)XMLパーサーを利用するサンプルです。

XMLパーサーによるメモリ利用を安全かつ高速にするために、スレッド毎に別々のメモリ空間を利用するように実装されています。 どれか1つのスレッドで動作するXMLパーサーがメモリを使いすぎた等の場合でも、他のスレッドのXMLパーサーを道連れにしない、といったメリットがあります。

マルチスレッド環境下で利用する場合、具体的に以下の点に注意するようにしてください。

/*--------------------------------------------------------------------------------*
Project: CrossRoad
Copyright (C)Nintendo All rights reserved.
These coded instructions, statements, and computer programs contain proprietary
information of Nintendo and/or its licensed developers and are protected by
national and international copyright laws. They may not be disclosed to third
parties or copied or duplicated in any form, in whole or in part, without the
prior written consent of Nintendo.
The content herein is highly confidential and should be handled accordingly.
*--------------------------------------------------------------------------------*/
#include <string.h>
using nlib_ns::exi::XmlStreamWriter;
using nlib_ns::exi::XmlStreamReader;
using nlib_ns::exi::XmlStreamReaderSettings;
using nlib_ns::exi::ExiAllocator;
#define M(x) NLIB_EXI_UTF8(x)
static void ParseXml(XmlStreamReader* reader) {
while (reader->HasNext()) {
XmlStreamReader::XmlStreamConstants e = reader->Next();
switch (e) {
case XmlStreamReader::START_ELEMENT:
nlib_printf("[thread=%d]: StartElement(%s)\n", tid, M(reader->GetLocalName()));
break;
case XmlStreamReader::END_ELEMENT:
nlib_printf("[thread=%d]: EndElement(%s)\n", tid, M(reader->GetLocalName()));
break;
case XmlStreamReader::CHARACTERS:
nlib_printf("[thread=%d]: Characters(%s)\n", tid, M(reader->GetText()));
break;
default:
break;
}
}
}
static void ThreadA(void*) {
// This thread reads the xml below:
const char myxml[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
"<ROOT>"
" <ITEM1>TEXT1</ITEM1>"
" <ITEM2>"
" <SUB1>TEXT2</SUB1>"
" <SUB2>TEXT3</SUB2>"
" </ITEM2>"
"</ROOT>";
// Initializes the per thread allocator.
void* buffer = malloc(1024 * 128);
if (!buffer) return;
if (ExiAllocator::Init(buffer, 1024 * 128) != 0) return;
// Note that the instances of XmlStreamReader, XmlStreamWriter are not thread-safe.
MemoryInputStream istr(myxml, strlen(myxml));
XmlStreamReaderSettings is;
UniquePtr<XmlStreamReader> r(XmlStreamReader::Create(&istr, is));
if (!r.get()) {
ExiAllocator::Finalize();
free(buffer);
return;
}
ParseXml(r.get());
r->Close();
r.reset(); // You have to delete the objects before you destroy the allocator.
ExiAllocator::Finalize();
free(buffer);
}
static void ThreadB(void*) {
// This thread reads the xml below:
const char myxml[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
"<root>"
" <item1>text1</item1>"
" <item2>"
" <sub1>text2</sub1>"
" <sub2>text3</sub2>"
" </item2>"
"</root>";
// Initializes the per thread allocator.
void* buffer = malloc(1024 * 128);
if (!buffer) return;
if (ExiAllocator::Init(buffer, 1024 * 128) != 0) return;
// Note that the instances of XmlStreamReader, XmlStreamWriter are not thread-safe.
MemoryInputStream istr(myxml, strlen(myxml));
XmlStreamReaderSettings is;
UniquePtr<XmlStreamReader> r(XmlStreamReader::Create(&istr, is));
if (!r.get()) {
ExiAllocator::Finalize();
free(buffer);
return;
}
ParseXml(r.get());
r->Close();
r.reset(); // You have to delete the objects before you destroy the allocator.
ExiAllocator::Finalize();
free(buffer);
}
bool SampleMain(int, char**) {
nlib_printf("Two threads read different XMLs independently\n\n");
nlib_thread th_a, th_b;
e = nlib_thread_create(&th_a, NULL, ThreadA, NULL);
if (e != 0) return false;
e = nlib_thread_create(&th_b, NULL, ThreadB, NULL);
if (e != 0) {
return false;
}
return true;
}
NLIB_MAINFUNC