1 /* 2 * This file is part of Licq, an instant messaging client for UNIX. 3 * Copyright (C) 2010-2011, 2013 Licq developers <licq-dev@googlegroups.com> 4 * 5 * Licq is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * Licq is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with Licq; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 #ifndef LICQDAEMON_PLUGINTHREAD_H 21 #define LICQDAEMON_PLUGINTHREAD_H 22 23 #include "utils/dynamiclibrary.h" 24 25 #include <boost/noncopyable.hpp> 26 #include <boost/shared_ptr.hpp> 27 #include <pthread.h> 28 29 namespace LicqDaemon 30 { 31 32 /** 33 * The PluginThread class starts a new thread and loads, initializes and starts 34 * the plugin in that thread. By loading the plugin in the same thread as it is 35 * later run in we hope to avoid problems with libraries' initialization 36 * routines not being run in the "main" thread. 37 */ 38 class PluginThread : private boost::noncopyable 39 { 40 public: 41 typedef boost::shared_ptr<PluginThread> Ptr; 42 43 struct Data; 44 45 /** 46 * Create a new PluginThread instance, but without starting a new thread for 47 * it. Instead make it use the current thread (i.e. the caller's thread). The 48 * caller's execution will continue in a new thread with the entry point 49 * given in @a newThreadEntry. The argument to @a newThreadEntry will be the 50 * newly created PluginThread instance. 51 */ 52 static int createWithCurrentThread(int (*newThreadEntry)(PluginThread::Ptr)); 53 54 PluginThread(); 55 ~PluginThread(); 56 57 /** 58 * Stop thread if startPlugin() hasn't been called. Mostly for unit test. 59 */ 60 void stop(); 61 62 /** 63 * Wait for the thread to exit. 64 * @return The thread's exit value. If the thread has been canceled, the 65 * return value is PTHREAD_CANCELED. 66 */ 67 void* join(); 68 69 void cancel(); 70 bool isThread(const pthread_t& thread) const; 71 72 DynamicLibrary::Ptr loadPlugin(const std::string& path); 73 void createPlugin(void (*pluginCreate)(void*), void* argument); 74 bool initPlugin(bool (*pluginInit)(void*), void* argument); 75 void startPlugin(void* (*pluginStart)(void*), void* argument); 76 77 private: 78 explicit PluginThread(bool); 79 void waitForThreadToStart(); 80 81 struct NewThreadData; 82 static void* newThreadEntry(void* data); 83 84 const bool myIsThreadOwner; 85 pthread_t myThread; 86 Data* myData; 87 void* myExitValue; 88 }; 89 90 } // namespace LicqDaemon 91 92 #endif 93