Я пишу DLL в C++Builder XE6, которая создает отдельный поток (производный от TThread) для получения данных JSON с сервера REST каждые X секунд (с использованием TIdHTTP) и анализа данных JSON.
Поток заполняет простую структуру (без динамически выделяемых данных) проанализированными данными JSON в методе Execute()
потока:
typedef struct
{
char MyString[40 + 1];
double MyDouble;
bool MyBool;
} TMyStruct;
Поток должен хранить структуру в виде списка, например std::vector
:
#include <vector>
std::vector<TMyStruct> MyList;
Поток добавит TMyStruct в список:
TMyStruct Data;
...
MyList.push_back(Data);
Список будет охраняться TCriticalSection
для предотвращения повреждения данных.
DLL экспортирует функцию для извлечения TMyStruct
из MyList
.
bool __declspec(dllexport) __stdcall GetMyStruct (int Index, TMyStruct* Data)
{
...
}
Единственное, не знаю куда деть MyList
...
Если я сделаю MyList
глобальную переменную, она будет находиться в памяти основного потока и GetMyStruct()
сможет получить к ней прямой доступ. Как поток получает доступ к MyList
?
Если я сделаю MyList
членом производного от TThread
класса, он будет расположен в памяти потока, и поток сможет получить к нему прямой доступ. Как GetMyStruct()
получает доступ к MyList
?
Каков наилучший/предпочтительный/распространенный способ хранения MyList
и доступа к нему в другом потоке?
If I make
MyList
a global variable, it is located in the main thread's memory andGetMyStruct()
can access it directly. How does the thread accessMyList
?
Точно так же. Все потоки в процессе могут свободно обращаться к глобальным переменным внутри этого процесса. Например:
#include <vector>
#include <System.SyncObjs.hpp>
typedef struct
{
char MyString[40 + 1];
double MyDouble;
bool MyBool;
} TMyStruct;
std::vector<TMyStruct> MyList;
TCriticalSection *Lock = NULL; // why not std::mutex instead?
class TMyThread : public TThread
{
...
};
TMyThread *Thread = NULL;
...
void __fastcall TMyThread::Execute()
{
TMyStruct Data;
...
Lock->Enter();
try {
MyList.push_back(Data);
}
__finally {
Lock->Leave();
}
...
}
...
void __declspec(dllexport) __stdcall StartThread ()
{
Lock = new TCriticalSection;
Thread = new TMyThread;
}
void __declspec(dllexport) __stdcall StopThread ()
{
if (Thread) {
Thread->Terminate();
Thread->WaitFor();
delete Thread;
Thread = NULL;
}
if (Lock) {
delete Lock;
Lock = NULL;
}
}
bool __declspec(dllexport) __stdcall GetMyStruct (int Index, TMyStruct* Data)
{
if (!(Lock && Thread)) return false;
Lock->Enter();
try {
*Data = MyList[Index];
}
__finally {
Lock->Leave();
}
return true;
}
If I make
MyList
a member of theTThread
-derived class, it is located in the thread's memory and the thread can access it directly. How doesGetMyStruct()
accessMyList
?
Доступ к нему через указатель на объект потока. Например:
#include <vector>
#include <System.SyncObjs.hpp>
typedef struct
{
char MyString[40 + 1];
double MyDouble;
bool MyBool;
} TMyStruct;
class TMyThread : public TThread
{
protected:
void __fastcall Execute();
public:
__fastcall TMyThread();
__fastcall ~TMyThread();
std::vector<TMyStruct> MyList;
TCriticalSection *Lock;
};
TMyThread *Thread = NULL;
...
__fastcall TMyThread::TMyThread()
: TThread(false)
{
Lock = new TCriticalSection;
}
__fastcall TMyThread::~TMyThread()
{
delete Lock;
}
void __fastcall TMyThread::Execute()
{
TMyStruct Data;
...
Lock->Enter();
try {
MyList.push_back(Data);
}
__finally {
Lock->Leave();
}
...
}
void __declspec(dllexport) __stdcall StartThread ()
{
Thread = new TMyThread;
}
void __declspec(dllexport) __stdcall StopThread ()
{
if (Thread) {
Thread->Terminate();
Thread->WaitFor();
delete Thread;
Thread = NULL;
}
}
bool __declspec(dllexport) __stdcall GetMyStruct (int Index, TMyStruct* Data)
{
if (!Thread) return false;
Thread->Lock->Enter();
try {
*Data = Thread->MyList[Index];
}
__finally {
Thread->Lock->Leave();
}
return true;
}
What is the best/prefered/common way to store
MyList
and access it in a different thread?
Это полностью зависит от вас, исходя из ваших конкретных потребностей и дизайна проекта.
std::mutex
. Я выполнил поиск файла mutex
в папке «include», но не нашел. В подпапке dinkumware есть algorithm
... yvals.h
, но нет mutex
.
@MartinNijhoff std::mutex
был представлен в C++ 11 в заголовке <mutex>
. Только компиляторы на основе Clang поддерживают C++11, а не «классический» компилятор Borland. Поэтому убедитесь, что ваш проект настроен соответствующим образом. Компиляторы Clang C++11 были впервые представлены в XE3.
Иногда я склонен слишком много думать... Спасибо за помощь, Реми.