আপনি যখন ভেরিয়েবল ঘোষণা করেন thread_local
তখন প্রতিটি থ্রেডের নিজস্ব অনুলিপি থাকে। আপনি যখন নাম দ্বারা এটি উল্লেখ করেন, তারপরে বর্তমান থ্রেডের সাথে সম্পর্কিত অনুলিপিটি ব্যবহৃত হয়। যেমন
thread_local int i=0;
void f(int newval){
i=newval;
}
void g(){
std::cout<<i;
}
void threadfunc(int id){
f(id);
++i;
g();
}
int main(){
i=9;
std::thread t1(threadfunc,1);
std::thread t2(threadfunc,2);
std::thread t3(threadfunc,3);
t1.join();
t2.join();
t3.join();
std::cout<<i<<std::endl;
}
এই কোডটি "2349", "3249", "4239", "4329", "2439" বা "3429" আউটপুট দেবে, তবে আর কিছুই নয়। প্রতিটি থ্রেডের নিজস্ব অনুলিপি থাকে i
, যা বরাদ্দ করা হয়, বর্ধিত হয় এবং তারপরে মুদ্রিত হয়। থ্রেড চলমানটির main
নিজস্ব অনুলিপিও রয়েছে, যা শুরুতে বরাদ্দ করা হয় এবং তারপরে অপরিবর্তিত থাকে। এই অনুলিপিগুলি সম্পূর্ণ স্বাধীন, এবং প্রত্যেকের আলাদা আলাদা ঠিকানা রয়েছে।
এটি কেবলমাত্র সেই নামটিই সেই ক্ষেত্রে বিশেষ --- --- যদি আপনি কোনও thread_local
ভেরিয়েবলের ঠিকানা নেন তবে আপনার কেবল একটি সাধারণ পয়েন্টারের কাছে একটি সাধারণ পয়েন্টার রয়েছে যা আপনি অবাধে থ্রেডের মধ্যে দিয়ে যেতে পারেন। যেমন
thread_local int i=0;
void thread_func(int*p){
*p=42;
}
int main(){
i=9;
std::thread t(thread_func,&i);
t.join();
std::cout<<i<<std::endl;
}
যেহেতু ঠিকানাটি i
থ্রেড ফাংশনে প্রেরণ করা হয়েছে, তারপরে i
মূল থ্রেডের অন্তর্ভুক্ত থাকা অনুলিপিটি যদিও তা অর্পণ করা যেতে পারে thread_local
। এই প্রোগ্রামটি এভাবে "42" আউটপুট দেয়। যদি আপনি এটি করেন, তবে আপনার যত্ন নেওয়া দরকার যে *p
থ্রেডটি তার নিজস্ব হওয়া থ্রেডটি বের হয়ে যাওয়ার পরে অ্যাক্সেস করা হয়নি, অন্যথায় আপনি পয়েন্ট-টু অবজেক্টটি নষ্ট হয়ে যাওয়ার মতো অন্যান্য ক্ষেত্রে যেমন ঝুঁকির পয়েন্টার এবং অপরিজ্ঞাত আচরণ পান।
thread_local
ভেরিয়েবলগুলি "প্রথম ব্যবহারের আগে" আরম্ভ করা হয়, সুতরাং যদি তারা কোনও প্রদত্ত থ্রেড দ্বারা স্পর্শ না হয় তবে সেগুলি অগত্যা আর কখনও শুরু করা হয় না। এটি thread_local
সম্পূর্ণরূপে স্ব-অন্তর্ভুক্ত এবং সেগুলির কোনওটির সাথে স্পর্শ না করে এমন থ্রেডের জন্য প্রোগ্রামের প্রতিটি পরিবর্তনশীল নির্মাণ এড়াতে কম্পাইলারদের অনুমতি দেওয়া । যেমন
struct my_class{
my_class(){
std::cout<<"hello";
}
~my_class(){
std::cout<<"goodbye";
}
};
void f(){
thread_local my_class unused;
}
void do_nothing(){}
int main(){
std::thread t1(do_nothing);
t1.join();
}
এই প্রোগ্রামটিতে 2 টি থ্রেড রয়েছে: মূল থ্রেড এবং ম্যানুয়ালি তৈরি থ্রেড। কোনও থ্রেড কল করে না f
, তাই thread_local
বস্তুটি কখনই ব্যবহৃত হয় না। সুতরাং এটি নির্ধারিত নয় যে সংকলক 0, 1 বা 2 my_class
টির উদাহরণ তৈরি করে কিনা এবং আউটপুট "", "হ্যালোহেলোগুডবিগুডবি" বা "হেলোগুডবি" হতে পারে।
strtok
।strtok
এমনকি একক থ্রেডযুক্ত পরিবেশে নষ্ট হয়ে গেছে।