00001 /*************************************************************************** 00002 * Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider, * 00003 * Matthias Hardt, Guido Madaus * 00004 * * 00005 * Copyright (C) 2007-2008 BerLinux Solutions GbR * 00006 * Stefan Schwarzer & Guido Madaus * 00007 * * 00008 * Copyright (C) 2009-2013 BerLinux Solutions GmbH * 00009 * * 00010 * Authors: * 00011 * Stefan Schwarzer <stefan.schwarzer@diskohq.org>, * 00012 * Matthias Hardt <matthias.hardt@diskohq.org>, * 00013 * Jens Schneider <jens.schneider@diskohq.org>, * 00014 * Guido Madaus <guido.madaus@diskohq.org>, * 00015 * Patrick Helterhoff <patrick.helterhoff@diskohq.org>, * 00016 * René Bählkow <rene.baehlkow@diskohq.org> * 00017 * * 00018 * This library is free software; you can redistribute it and/or * 00019 * modify it under the terms of the GNU Lesser General Public * 00020 * License version 2.1 as published by the Free Software Foundation. * 00021 * * 00022 * This library is distributed in the hope that it will be useful, * 00023 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00025 * Lesser General Public License for more details. * 00026 * * 00027 * You should have received a copy of the GNU Lesser General Public * 00028 * License along with this library; if not, write to the * 00029 * Free Software Foundation, Inc., * 00030 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00031 **************************************************************************/ 00032 00033 #ifndef MMSTHREADSERVER_H_ 00034 #define MMSTHREADSERVER_H_ 00035 00036 #include "mmstools/mmsthread.h" 00037 00038 #include <sigc++/sigc++.h> 00039 00040 //! This class is the base class for all threads which works as a server. 00041 /*! 00042 This class includes the base functionality e.g. the handshake between server and client threads. 00043 You can use the onProcessData() callback if you do not want to derive your own class from MMSThreadServer. 00044 \author Jens Schneider 00045 */ 00046 class MMSThreadServer : public MMSThread { 00047 private: 00048 //! id of the server thread 00049 pthread_t server_tid; 00050 00051 //! describes one item/request in the queue 00052 typedef struct { 00053 //! variable for conditional handling 00054 pthread_cond_t cond; 00055 //! mutex for conditional handling 00056 pthread_mutex_t mutex; 00057 //! data to send 00058 void *in_data; 00059 //! length of the in_data 00060 int in_data_len; 00061 //! receive buffer 00062 void **out_data; 00063 //! length of the out_data 00064 int *out_data_len; 00065 } MMSTS_QUEUE_ITEM; 00066 00067 //! request queue (ring buffer) 00068 MMSTS_QUEUE_ITEM **queue; 00069 00070 //! number of items in the queue 00071 int queue_size; 00072 00073 //! current item in the queue (read pointer) 00074 int queue_rp; 00075 00076 //! first free item in the queue (write pointer) 00077 int queue_wp; 00078 00079 //! mark the ring buffer as full 00080 bool buffer_full; 00081 00082 //! variable for conditional handling (server side) 00083 pthread_cond_t cond; 00084 00085 //! mutex for conditional handling (server side) 00086 pthread_mutex_t mutex; 00087 00088 //! in non-blocking mode the caller of trigger() will get control directly after triggering 00089 //! and do not wait until server has finished processData() 00090 bool blocking; 00091 00092 //! server thread 00093 void threadMain(); 00094 00095 public: 00096 //! constructor 00097 /*! 00098 \param queue_size maximum items in the queue 00099 \param identity identity of the server thread used for logging etc. 00100 \param blocking blocking or non-blocking mode, see trigger() 00101 \note In non-blocking mode the caller of trigger() will get control directly after triggering 00102 and do not wait until server has finished processData() of the previous trigger() call. 00103 */ 00104 MMSThreadServer(int queue_size = 1000, string identity = "MMSThreadServer", bool blocking = true); 00105 00106 //! destructor 00107 ~MMSThreadServer(); 00108 00109 //! Start the server thread. 00110 /*! 00111 This method starts the server thread. This has to be done before the first trigger() call. 00112 \return true if successful 00113 \note The method returns false, if the server is already started. 00114 */ 00115 bool start(); 00116 00117 //! Process a new event from the client. 00118 /* 00119 This method will be called in the server loop. 00120 A derived class should overwrite this method with own code which should run in the server context. 00121 \param in_data pointer to data to put to the server 00122 \param in_data_len length of in_data 00123 \param out_data address of a pointer to receive data from the server 00124 \param out_data_len address of a integer to get the length of out_data 00125 */ 00126 virtual void processData(void *in_data, int in_data_len, void **out_data, int *out_data_len); 00127 00128 //! Trigger a new event to the server. 00129 /*! 00130 This method sends data (in_data) from the caller (client) thread to the 00131 server thread. 00132 If MMSThreadServer runs in blocking mode (see constructor), the caller 00133 of trigger() will be blocked and is waiting for the answer from the server. 00134 If MMSThreadServer runs in non-blocking mode, the caller of trigger() will 00135 get control immediately and do not wait until server has finished processData() 00136 of the previous trigger() call. 00137 \param in_data pointer to data to put to the server 00138 \param in_data_len length of in_data 00139 \param out_data address of a pointer to receive data from the server 00140 \param out_data_len address of a integer to get the length of out_data 00141 \return true if successful 00142 \note If server's queue is full, the caller is blocked until enough space in the queue. 00143 \note The handling of out_data and out_data_len is dependend on the implementation 00144 of the processData() method which is done in classes derived from MMSThreadServer. 00145 \note If MMSThreadServer runs in non-blocking mode, out_data and out_data_len are not supported. 00146 */ 00147 bool trigger(void *in_data, int in_data_len, void **out_data = NULL, int *out_data_len = NULL); 00148 00149 //! Set one or more callbacks for the onProcessData event. 00150 /*! 00151 The connected callbacks will be called from MMSThreadServer::processData() and will be run 00152 within the context of server thread. 00153 00154 A callback method must be defined like this: 00155 00156 void myclass::mycallbackmethod(void *in_data, int in_data_len, void **out_data, int *out_data_len); 00157 00158 \param in_data pointer to data to put to the server 00159 \param in_data_len length of in_data 00160 \param out_data address of a pointer to receive data from the server 00161 \param out_data_len address of a integer to get the length of out_data 00162 00163 To connect your callback to onProcessData do this: 00164 00165 sigc::connection connection; 00166 connection = mythreadserver->onProcessData.connect(sigc::mem_fun(myobject,&myclass::mycallbackmethod)); 00167 00168 To disconnect your callback do this: 00169 00170 connection.disconnect(); 00171 00172 Please note: 00173 00174 You HAVE TO disconnect myobject from onProcessData BEFORE myobject will be deleted!!! 00175 Else an abnormal program termination can occur. 00176 You HAVE TO call the disconnect() method of sigc::connection explicitly. The destructor will NOT do this!!! 00177 */ 00178 sigc::signal<void, void *, int, void **, int *> onProcessData; 00179 }; 00180 00181 #endif /*MMSTHREADSERVER_H_*/