ข้ามไปที่เนื้อหาหลัก

การอินเทอร์รัพท์ใน boost::thread

สืบเนื่องจากการใช้งาน std::thread ซึ่งผมคิดไปเองว่า gcc น่าจะรองรับมาตรฐาน C++11 ไปเรียบร้อยแล้ว แต่ปรากฎว่าไม่เป็นเช่นนั้นเนื่องจาก gcc ที่ใช้อยู่ในปัจจุบันเป็นรุ่นที่ 4.6 ยังไม่รองรับทั้งหมด (สถานะของมาตรฐาน c++ สำหรับ gcc 4.6 สามารถดูได้จาก Status of Experimental C++0x Support in GCC 4.6) และ std::thread ถึงแม้จะใช้งานได้บ้างแล้ว (สร้าง std::thread อ็อบเจกต์ได้ join ได้ แต่อินเทอร์รัพท์ไม่ได้) แต่ก็ยังต้องรอให้เธรดที่ถูกสร้างขึ้นจบการทำงานไปตามปรกติวิสัย ซึ่งในงานบางอย่างจำเป็นต้องใช้การอินเทอร์รัพท์เข้าช่วย ซึ่งในบทความนี้จะทดลองใช้งานไลบรารีเธรดจาก boost แทน
เหตุผลนึ่งที่เลือกไลบรารีจาก boost เนื่องจาก boost::thread นั้นเหมือนกับมาตฐาน C++11 มากทีเดียว หาก gcc อิมพลีเมนท์ std::thread พร้อมที่จะให้ใช้งานแล้วการย้ายกลับไปใช้ std::thread จะทำได้ไม่ยากนัก เริ่มจากตัวอย่างง่ายๆ กันก่อน (ลอกตัวอย่างจาก เรื่องวุ่นๆ ของ std::thread ใน C++0x)
// boost_thread.cpp
#include <iostream>
#include <boost/thread.hpp>
using namespace std;

class DoWork
{
public:
DoWork(){
  cout << "this in constructor : " << this << endl;
  this->running = false;
}

bool running;

void operator()(){
  cout << "show running by operator : " << running << endl;
  cout << "show this by operator : " << this << endl;
  sleep(2);
  cout << "show running by operator after wake up : "<< running << endl;
}

void showRunning(){
  cout << "show running : " << running << endl;
  cout << "show this in show : " << this << endl;
}
};


int main(){

//pass dw to thread by value
cout << "pass dw1 to thread" << endl;
DoWork dw1;
dw1.showRunning();
boost::thread t1(dw1);
sleep(1);
dw1.running = true;
dw1.showRunning();
sleep(1);
t1.join();

//pass dw to thread by reference
cout << endl << "pass dw2 to thread" << endl;
DoWork dw2;
dw2.showRunning();
boost::thread t2(boost::ref(dw2));
sleep(1);
dw2.running = true;
dw2.showRunning();
t2.join();

return 0;
}

คอมไพล์และเรียกทำงาน $ g++ boost_thread.cpp -lboost_thread
$ ./a.out
pass dw1 to thread
this in constructor : 0x7fff9ff7c28f
show running : 0
show this in show : 0x7fff9ff7c28f
show running by operator : 0
show this by operator : 0x25ef1f8
show running : 1
show this in show : 0x7fff9ff7c28f
show running by operator after wake up : 0

pass dw2 to thread
this in constructor : 0x7fff9ff7c26f
show running : 0
show this in show : 0x7fff9ff7c26f
show running by operator : 0
show this by operator : 0x7fff9ff7c26f
show running : 1
show this in show : 0x7fff9ff7c26f
show running by operator after wake up : 1

ตัวอย่างต่อไปนี้ใช้ทดสอบการอินเทอร์รัพท์ โคดด้านล่างเป็นตัวอย่างที่ไม่มี อินเทอร์รัพท์
//test_interupt.cpp 
#include <iostream>
using namespace std;

#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class Timer
{
public:
bool running;
Timer(){
  cout << "Construct Timer " << endl;
  this->running = false;
}

void operator()(){
  this->running = true;
  while(this->running){
   boost::posix_time::ptime current_time = boost::posix_time::microsec_clock::local_time();
   cout<<"current time:: "<<current_time<<endl;
   boost::posix_time::time_duration sleep_time = boost::posix_time::seconds(2);
   boost::this_thread::sleep(sleep_time);
  }
  
}
};


int main(){
Timer timer;
boost::thread t(boost::ref(timer));

cout << "main sleep: 10s"<<endl;
sleep(10);
  
// cout << "interrupt thread t"<<endl;
// t.interrupt();

cout << "main sleep: 10s"<<endl;
sleep(10);

cout << "set timer running = false"<<endl;
timer.running = false;
t.join();

return 0;
}

คอมไพล์และเรียกทำงาน $ g++ test_interupt.cpp -lboost_thread -lboost_date_time
$ ./a.out
Construct Timer
main sleep: 10s
current time:: 2011-Dec-12 12:13:49.554883
current time:: 2011-Dec-12 12:13:51.555281
current time:: 2011-Dec-12 12:13:53.555459
current time:: 2011-Dec-12 12:13:55.555621
current time:: 2011-Dec-12 12:13:57.555803
main sleep: 10s
current time:: 2011-Dec-12 12:13:59.555971
current time:: 2011-Dec-12 12:14:01.556132
current time:: 2011-Dec-12 12:14:03.556296
current time:: 2011-Dec-12 12:14:05.556461
current time:: 2011-Dec-12 12:14:07.556638
set timer running = false

ทดลอง เอาคอมเมนท์ บรรทดที่ 37 และ 38 ออก
37 // cout << "interrupt thread t" << endl;
38 // t.interrupt();
เป็น
37 cout << "interrupt thread t" << endl;
38 t.interrupt();
คอมไพล์และเรียกทำงานใหม่อีกครั้ง $ g++ test_interupt.cpp -lboost_thread -lboost_date_time
$ ./a.out
Construct Timer
main sleep: 10s
current time:: 2011-Dec-12 12:21:16.090885
current time:: 2011-Dec-12 12:21:18.106295
current time:: 2011-Dec-12 12:21:20.106476
current time:: 2011-Dec-12 12:21:22.106648
current time:: 2011-Dec-12 12:21:24.106809
interrupt thread t
main sleep: 10s
set timer running = false

จะสังเกตได้ว่าเธรด t จะถูกขัดจังหวะการทำงาน ส่งผลให้ไม่มีการแสดงข้อความวันและเวลาออกมาอีก
ข้อพึ่งระวัง เนื่องจาก boost::this_thread::sleep(sleep_time); มีการอิมพลิเมนท์ interrupt point เอาไว้ดังนั้นเราจึงสามารถหยุดการทำงานของเธรดได้หากเราใช้ sleep ซึ่งเป็นฟังก์ชันใน cstdlib แทนเธรดจะไม่ถูกอินเทอร์รัพท์และจะทำงานปรกติแทน
ทดลองเปลี่ยน boost::this_thread::sleep(sleep_time); ในบรรทัดที่ 23 เป็น sleep(sleep_time.total_seconds()); แทนแล้ว คอมไพล์และเรียกทำงานใหม่อีกครั้ง $ g++ test_interupt.cpp -lboost_thread -lboost_date_time
$ ./a.out
Construct Timer
main sleep: 10s
current time:: 2011-Dec-12 12:33:21.625318
current time:: 2011-Dec-12 12:33:23.625694
current time:: 2011-Dec-12 12:33:25.625857
current time:: 2011-Dec-12 12:33:27.626025
current time:: 2011-Dec-12 12:33:29.626215
interrupt thread t
main sleep: 10s
current time:: 2011-Dec-12 12:33:31.626383
current time:: 2011-Dec-12 12:33:33.626552
current time:: 2011-Dec-12 12:33:35.626737
current time:: 2011-Dec-12 12:33:37.626902
current time:: 2011-Dec-12 12:33:39.627088
set timer running = false

ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

ตัวเอ๋ยตัวผม

กลอนนี้ใช้เวลาประมาณ 20 นาทีเขียนขึ้นมาในห้องเรียนวิชาสัมนา 1 เพราะอาจารย์อยากให้แนะนำตัวเองเป็นกลอน ไม่รู้จะแต่งว่าไงเลยแต่งออกมาเป็นดอกสร้อย เห็นว่าพอใช้ได้เลยเอามาลงไว้เป็นอนุสร ๏ ตัวเอ๋ยตัวผม นิยมในพระพุทธศาสนา ตั้งจิตตั้งใจตั้งหน้า ใฝ่หาความรู้สู่ตน ตั้งใจศึกษาให้เชี่ยวชาญ ชำนาญในศาสตร์ที่ฝึกฝน ฝึกจิตฝึกสันดานให้เป็นคน เป็นชนในชาติที่ดีเอย ๚ะ๛

บันทึกการจัดงานศพ: พิธีฌาปนกิจศพ

ตรงส่วนนี้คงจะเขียนเกี่ยวกับพิธียกศพออกจากบ้าน และเกร็ดต่างๆ เล็กๆ น้อยๆ เนื่องจากที่จัดงานจะไม่นิยมไว้ศพที่วัด จะไว้ศพที่บ้าน และถ้าเป็นไปได้จะไว้ศพในบ้านเสียด้วยซ่ำ เมื่อถึงวันฌาปนกิจศพ หรือเผาศพ ก็จะมีการเซ่นไหว้ครั้งใหญ่ก่อนเคลื่อนย้ายศพไปวัดเพื่อฌาปนกิจ เครื่องเซ่นไว้จะประกอบไปด้วย ข้าว 5 ถ้วย กับข้าว 5 อย่าง หัวหมู ไก่ต้ม ไข่ต้ม หมูสามชั้นต้ม หมี่เหลืองผัด กุ้ง หอย ปู ปลา ผลไม้ 5 อย่าง ขนมขึ้น เมื่อมีการเซ่นไหว้ทุกครั้งจะต้องมี สัปรด น้ำชา 3 จอก เหล้าขาว 5 จอก(หลานๆ บอกว่าเจ็คไม่กินเหล้าขาว แต่มีคนบอกว่าเป็นการไหว้ตามประเพณี ^^ ) ซึ่งแต่ละอย่างมีความหมาย แต่ผมจำไม่ได้ต้องหาอีกครั้งนึง ตัวอย่างเครื่องเซ่นไหว้ เมื่อถึงพิธีเซ่นไหว้ จะมีการเซ่นไหว้โดยแบ่งออกเป็นคณะ แต่เพื่อความสะดวกและรวบรัดจึงมีการไหว้เพียงไม่กี่คณะ ซึ่งก็เหมือนเดิมคือผู้ที่มีศักดิ์สูงกว่าจะไม่รวมการเซ่นไหว้ครั้งนี้ คณะแรกจะเป็นผู้ไกล้ชิดผู้ตายมากที่สุดเริ่มตั้งแต่ลูกและภรรยา หลังจากนั้นก็จะเป็นน้องๆ แล้วก็หลานๆ และก็มิตรรักและผู้คนที่นับถือผู้ตาย หากเป็นเมื่อสมัยก่อนนั้น ต้องแยกออกเป็นเขย เป็นสะไภ้ ไหว้กันหลายยกหล

ด้วยระลึกถึงคุณย่า บันทึกจากความทรงจำ

บันทึกนี้เขียนขึ้นเพื่อบันทึกความทรงจำของผมที่มีต่อคุณย่าที่ล่วงลับไปแล้วอย่างไม่มีวันหวนคืน คุณย่าเปรียบเหมือนฟางเส้นสุดท้ายที่ร้อยครอบครัวใหญ่ของเราเอาไว้ไม่ให้แตกแยก หลังจากที่เสียคุณปู่ไปเมื่อ 23 ปีก่อน เนื่องจากบริเวณจังหวัดกระบี่ ตรัง พังงา ภูเก็ต มีชาวจีนอาศัยอยู่มาก แต่มักจะเป็นชาวจีนที่อพยพมาไทยนานแล้ว จากการการสังเกตของผม ชาวจีนแถบนี้โดยมากน่าจะเป็นชาว เปอรานากัน หรือชาวจีนที่อพยพมาจากจีนแล้วตั้งถิ่นฐานอยู่ในแหลมลายูหรืออินโดนีเซีย แล้วหลังจากนั้นจึงอพยพมาอาศัยต่อที่ประเทศไทย จากการบอกเล่าของคุณแม่ ก๋งเคยเล่าให้ฟังว่าตอนยังเด็กเคยแจวเรือจ้างอยู่ที่ปีนัง คุณย่าเคยเล่าว่าเป็นชาวฮกเกี้ยน อีกทั้วจากรูปวาดคุณย่าทวดที่มีการเกล้ามวยผม สวมเสื้อคอลึก ส่วนทางบ้านมีการใช้คำเรียกจีนผสมไทยถิ่นใต้อยู่มาก ผู้หญิงทุกคนนิยมสวมผ้าปาเต๊ะ เสื้อลูกไม้ (เสื้อฉลุลายดอกไม้) อาหารการกินเป็นแบบชาวไทยถิ่นใต้ทุกประการ (กินน้ำพริก แกงส้มเก่งกันทุกคน ยกเว้นก๋ง :D) อีกทั้งก๋งเกิดที่ดินแดนแถบนี้ไม่ได้เดินทางมาจากเมืองจีน (บางทีเรียก เตี่ยต่อเตี่ย คือ ทวดมาจากจีน ส่วนสถานที่เกิดไม่แน่ใจว่าเป็นปีนังหรือไทย)