Прежде всего, вы должны знать, что библиотека pthread (aka POSIX threads) представляет собой библиотеку потоков для систем POSIX, которая в наши дни является самой современной операционной системой. кроме для Windows; но <windows.h>
- это очень большой заголовок только для Windows, поэтому вы никогда не должны смешивать их в одной и той же программе, если только вы не развиваетесь против уровня эмуляции или совместимости или подобного (например, с Cygwin в Windows или с Wine in Linux).
Независимо от того, какую библиотеку потоков вы используете, ответ остается тем же. Оба POSIX pthread_create()
и Windows CreateThread()
/_beginthreadex()
принимают параметр void*
, который передается вашей процедуре потока. Но вам не нужно фактически передавать реальное значение указателя, если вы этого не хотите - ОС рассматривает его как непрозрачный blob и передает его без изменений. Таким образом, пока данные, которые вы хотите передать, не больше, чем указатель, вы можете просто перенести его на указатель на пути и отбросить его обратно с другой стороны.
Например, если вы хотите передать целое число процедуры резьбы:
int theAnswer = 42;
pthread_create(..., &thread_proc, (void *)(intptr_t)theAnswer);
...
void *thread_proc(void *param) {
int theAnswer = (int)(intptr_t)param; // Contains 42
...
}
Ваш пример передает значение double
, который на 64-битных системах, вероятно, будет такой же размер, как указатель, так что вы могли бы снять тот же трюк, например с union
; но он, безусловно, будет больше, чем указатель на 32-битных системах.
Для того чтобы передать информацию, отличную от указателя, к процедуре потока, вам нужно поместить эти данные в память и затем передать, ну, указатель на эти данные. Сложная часть управляет этой памятью, особенно в случае создания нескольких потоков с использованием той же процедуры потока.
Общей ошибкой является выделение этих данных в стеке и создание нескольких потоков в цикле, аргумент которого указывает на данные стека. Тем не менее, все эти потоки будут указывать на те же данные стека, и фактические данные, которые они заканчивают чтением, становятся большим условием гонки с большим количеством Неопределенного Поведения.
Правильный способ управления памятью - динамически распределять его для каждого потока, а затем отвечать за освобождение памяти за новый поток. Каждый поток получает свою собственную копию данных, утечка памяти не происходит, и там нет условий гонки.
Вот пример, который будет работать независимо от того, больше или меньше double
, чем указатель (т., как 32-битные, так и 64-битные системы):
// Allocate dynamic memory for the thread parameter. If you want to pass more
// than one value, create a struct instead.
double *theAnswer = new double(42.0);
pthread_create(..., &thread_proc, theAnswer);
...
void *thread_proc(void *param) {
// Order of operations here is important: dereference the value first, then
// free the memory
double *theAnswerPtr = (double *)param;
double theAnswer = *theAnswer;
delete theAnswerPtr;
// theAnswer is now 42.0, use it
...
}
Это очень поможет, если вы пометите это на каком языке вы используете. Но, как правило, простой шаблон заключается в создании 'struct', который содержит все параметры, необходимые для передачи в поток. Выделите экземпляр этой структуры, заполните ее, передайте указатель на нее в поток и разрешите потоку освободить ее, когда она будет выполнена с ней. –