threadwrap.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       threadwrap.cc
00003 ///             RAII Wrapper for a single thread.
00004 ///
00005 
00006 /*
00007     Copyright (C) 2009, Nicolas VIVIEN
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018     See the GNU General Public License in the COPYING file at the
00019     root directory of this project for more details.
00020 */
00021 
00022 #include "threadwrap.h"
00023 #include "error.h"
00024 #include <sys/socket.h>
00025 
00026 namespace Barry {
00027 
00028 void *callback_wrapper(void *data)
00029 {
00030         Barry::Thread::CallbackData *cbdata = (Barry::Thread::CallbackData*) data;
00031 
00032         return (*cbdata->callback)(cbdata);
00033 }
00034 
00035 Thread::CallbackData::CallbackData(void *userdata)
00036         : callback(0)
00037         , stopflag(false)
00038         , userdata(userdata)
00039 {
00040 }
00041 
00042 Thread::Thread(int socket,
00043                 void *(*callback)(Barry::Thread::CallbackData *data),
00044                 void *userdata)
00045         : m_socket(socket)
00046 {
00047         m_data = new CallbackData(userdata);
00048         m_data->callback = callback;
00049 
00050         int ret = pthread_create(&thread, NULL, callback_wrapper, m_data);
00051         if( ret ) {
00052                 delete m_data;
00053                 throw Barry::ErrnoError("Thread: pthread_create failed.", ret);
00054         }
00055 }
00056 
00057 Thread::~Thread()
00058 {
00059         if( pthread_join(thread, NULL) == 0 ) {
00060                 // successful join, thread is dead, free to free
00061                 delete m_data;
00062         }
00063         else {
00064                 // thread is in la-la land, must leak m_data here for safety
00065         }
00066 }
00067 
00068 void Thread::StopFlag()
00069 {
00070         // http://stackoverflow.com/questions/2486335/wake-up-thread-blocked-on-accept-call
00071 
00072         // set flag first, before waking thread
00073         m_data->stopflag = true;
00074 
00075         // shutdown the socket, but leave the fd valid, thereby waking up
00076         // the thread if it is blocked on accept()
00077         shutdown(m_socket, SHUT_RDWR);
00078 }
00079 
00080 } // namespace Barry
00081