/************************************************************************************** * Copyright (c) 2016, Tomoaki Yamaguchi * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v1.0 which accompany this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Tomoaki Yamaguchi - initial API and implementation and/or initial documentation **************************************************************************************/ #ifndef MQTTSNGWPROCESS_H_ #define MQTTSNGWPROCESS_H_ #include #include #include #include "MQTTSNGWDefines.h" #include "Threading.h" using namespace std; namespace MQTTSNGW { /*================================= * Parameters ==================================*/ #define MQTTSNGW_MAX_TASK 10 // number of Tasks #define PROCESS_LOG_BUFFER_SIZE 16384 // Ring buffer size for Logs #define MQTTSNGW_PARAM_MAX 128 // Max length of config records. /*================================= * Macros ==================================*/ #define WRITELOG theProcess->putLog #define CHK_SIGINT (theProcess->checkSignal() == SIGINT) #define UNUSED(x) ((void)(x)) /*================================= Class Process ==================================*/ class Process { public: Process(); virtual ~Process(); virtual void initialize(int argc, char** argv); virtual void run(void); void putLog(const char* format, ...); void resetRingBuffer(void); int getArgc(void); char** getArgv(void); int getParam(const char* parameter, char* value); const char* getLog(void); int checkSignal(void); const string* getConfigDirName(void); const string* getConfigFileName(void); private: int _argc; char** _argv; string _configDir; string _configFile; RingBuffer* _rb; Semaphore* _rbsem; Mutex _mt; int _log; char _rbdata[PROCESS_LOG_BUFFER_SIZE + 1]; }; /*===================================== Class MultiTaskProcess ====================================*/ class MultiTaskProcess: public Process { public: MultiTaskProcess(void); ~MultiTaskProcess(); void initialize(int argc, char** argv); int getParam(const char* parameter, char* value); void run(void); void waitStop(void); void threadStoped(void); void attach(Thread* thread); private: Thread* _threadList[MQTTSNGW_MAX_TASK]; Mutex _mutex; int _threadCount; int _stopCount; }; /*===================================== Class Exception =====================================*/ class Exception: public exception { public: Exception(const string& message); Exception(const int exNo, const string& message); Exception(const int exNo, const string& message, const char* file, const char* func, const int line); virtual ~Exception() throw (); const char* getFileName(); const char* getFunctionName(); const int getLineNo(); const int getExceptionNo(); virtual const char* what() const throw (); void writeMessage(); private: int _exNo; string _message; const char* _fileName; const char* _functionName; int _line; }; /*===================================== Class QueElement ====================================*/ template class QueElement { template friend class Que; public: QueElement(T* t) { _element = t; _next = 0; _prev = 0; } ~QueElement() { } private: T* _element; QueElement* _next; QueElement* _prev; }; /*===================================== Class Que ====================================*/ template class Que { public: Que() { _head = 0; _tail = 0; _cnt = 0; _maxSize = 0; } ~Que() { QueElement* elm = _head; while (elm) { QueElement* next = elm->_next; delete elm->_element; delete elm; elm = next; } } void pop(void) { if ( _head ) { QueElement* head = _head; if ( _head == _tail ) { _head = _tail = 0; } else { _head = head->_next; head->_prev = 0; } delete head; _cnt--; } } T* front(void) { { if ( _head ) { return _head->_element; } else { return 0; } } } int post(T* t) { if ( t && ( _maxSize == 0 || _cnt < _maxSize )) { QueElement* elm = new QueElement(t); if ( _head ) { if ( _tail == _head ) { elm->_prev = _tail; _tail = elm; _head->_next = elm; } else { _tail->_next = elm; elm->_prev = _tail; _tail = elm; } } else { _head = elm; _tail = elm; } _cnt++; return _cnt; } return 0; } int size(void) { return _cnt; } void setMaxSize(int maxSize) { _maxSize = maxSize; } private: int _cnt; int _maxSize; QueElement* _head; QueElement* _tail; }; /*===================================== Class Tree23 ====================================*/ #define TREE23_INSERT_ACTIVE (1) #define TREE23_DELETE_ACTIVE (2) #define TREE23_BI_NODE (3) #define TREE23_TRI_NODE (4) template class Tree23Elm{ template friend class Tree23; public: Tree23Elm() { _key = 0; _val = 0; } Tree23Elm(K* key, V* val) { _key = key; _val = val; } ~Tree23Elm() { } int compare(Tree23Elm* elm) { return _key->compare(elm->_key); } private: K* _key; V* _val; }; template class Tree23Node{ template friend class Tree23; public: Tree23Node(const int type) { _type = type; _telm0 = _telm1 = NULL; _left = _midle = _right = NULL; } Tree23Node(const int type, Tree23Node* midle) { _type = type; _telm0 = _telm1 = NULL; _left = _right = NULL; _midle = midle; } Tree23Node(const int type, Tree23Elm* telm) { _type = type; _telm0 = telm; _telm1 = NULL; _left = _midle = _right = NULL; } Tree23Node(const int type, Tree23Elm* telm, Tree23Node* left, Tree23Node* right) { _type = type; _telm0 = telm; _telm1 = NULL; _left = left; _midle = NULL; _right = right; } Tree23Node(const int type, Tree23Elm* telm0, Tree23Elm* telm1, Tree23Node* left, Tree23Node* midle, Tree23Node* right) { _type = type; _telm0 = telm0; _telm1 = telm1; _left = left; _midle = midle; _right = right; } ~Tree23Node() { } private: int _type; Tree23Elm* _telm0; Tree23Elm* _telm1; Tree23Node* _left; Tree23Node* _midle; Tree23Node* _right; }; template class Tree23{ public: Tree23() { _root = NULL; } ~Tree23() { if ( _root ) { delete _root; } } void add(K* key, V* val) { _root = add( _root, new Tree23Elm(key, val)); _root->_type = abs(_root->_type); } Tree23Node* add(Tree23Node* n, Tree23Elm* elm) { if ( n == 0 ) { return new Tree23Node(TREE23_INSERT_ACTIVE, elm); } int cmp0 = elm->compare(n->_telm0); int cmp1 = 0; switch ( n->_type ) { case 2: if ( cmp0 < 0 ) { n->_left = add(n->_left, elm); return addLeft2(n); } else if ( cmp0 == 0 ) { n->_telm0 = elm; return n; } else { n->_right = add(n->_right, elm); return addRight2(n); } break; case 3: cmp1 = elm->compare(n->_telm1); if ( cmp0 < 0 ) { n->_left = add(n->_left, elm); return addLeft3(n); } else if ( cmp0 == 0 ) { n->_telm0 = elm; return n; } else if ( cmp1 < 0 ) { n->_midle = add(n->_midle, elm); return addMidle3(n); } else if ( cmp1 == 0 ) { n->_telm1 = elm; return n; } else { n->_right = add(n->_right, elm); return addRight3(n); } break; default: break; } return 0; } void remove(K* k) { _root = remove(_root, k); if ( _root != NULL && _root->_type == TREE23_DELETE_ACTIVE ) { _root = _root->_midle; } } Tree23Node* remove(Tree23Node* node, K* k) { if ( node == NULL ) { return NULL; } int cmp0 = k->compare(node->_telm0->_key); int cmp1 = 0; switch ( node->_type ) { case 2: if ( cmp0 < 0 ) { node->_left = remove( node->_left, k); return removeLeft2(node); } else if ( cmp0 == 0 ) { if ( node->_left == NULL) { return new Tree23Node(TREE23_DELETE_ACTIVE); } Tree23Elm* maxLeft = new Tree23Elm(); node->_left = removeMax(node->_left, maxLeft); node->_telm0 = maxLeft; return removeLeft2(node); } else { node->_right = remove(node->_right, k); return removeRight2(node); } case 3: cmp1 = k->compare(node->_telm1->_key); if ( cmp0 < 0 ) { node->_left = remove(node->_left, k); return removeLeft3(node); } else if ( cmp0 == 0 ) { if ( node->_left == NULL ) { return new Tree23Node(TREE23_BI_NODE, node->_telm1); } Tree23Elm* maxLeft = new Tree23Elm(); node->_left = removeMax(node->_left, maxLeft); node->_telm0 = maxLeft; return removeLeft3(node); } else if ( cmp1 < 0 ) { node->_midle = remove(node->_midle, k); return removeMidle3(node); } else if ( cmp1 == 0 ) { if ( node->_midle == NULL ) { return new Tree23Node(TREE23_BI_NODE, node->_telm0); } Tree23Elm* maxMidle = new Tree23Elm(); node->_midle = removeMax(node->_midle, maxMidle); node->_telm1 = maxMidle; return removeMidle3(node); } else { node->_right = remove(node->_right, k); return removeRight3(node); } default: break; } return NULL; } bool find(K* key) { Tree23Node* node = _root; while (node != NULL) { int cmp0 = key->compare(node->_telm0->_key); int cmp1 = 0; switch (node->_type) { case 2: if ( cmp0 < 0 ) node = node->_left; else if ( cmp0 == 0 ) { return true; } else { node = node->_right; } break; case 3: cmp1 = key->compare(node->_telm1->_key); if ( cmp0 < 0 ) { node = node->_left; } else if ( cmp0 == 0 ) { return true; } else if ( cmp1 < 0 ) { node = node->_midle; } else if ( cmp1 == 0 ) { return true; } else { node = node->_right; } break; default: break; } } return false; } V* getVal(K* key) { Tree23Node* node = _root; while (node != NULL) { int cmp0 = key->compare(node->_telm0->_key); int cmp1 = 0; switch (node->_type) { case 2: if ( cmp0 < 0 ) { node = node->_left; } else if ( cmp0 == 0 ) { return node->_telm0->_val; } else { node = node->_right; } break; case 3: cmp1 = key->compare(node->_telm1->_key); if ( cmp0 < 0 ) { node = node->_left; } else if ( cmp0 == 0 ) { return node->_telm0->_val; } else if ( cmp1 < 0 ) { node = node->_midle; } else if ( cmp1 == 0 ) { return node->_telm1->_val; } else { node = node->_right; } break; default: break; } } return NULL; } private: Tree23Node* addLeft2(Tree23Node* node) { Tree23Node* n = node->_left; if ( n != NULL && n->_type == TREE23_INSERT_ACTIVE ) { return new Tree23Node(TREE23_TRI_NODE, n->_telm0, node->_telm0, n->_left, n->_right, node->_right); } return node; } Tree23Node* addLeft3(Tree23Node* node) { Tree23Node* n = node->_left; if ( n != NULL && n->_type == TREE23_INSERT_ACTIVE) { n->_type = TREE23_BI_NODE; Tree23Node* nn = new Tree23Node(TREE23_BI_NODE, node->_telm1, node->_midle, node->_right); return new Tree23Node(TREE23_INSERT_ACTIVE, node->_telm0, n, nn); } return node; } Tree23Node* addRight2(Tree23Node* node) { Tree23Node* n = node->_right; if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) { return new Tree23Node(TREE23_TRI_NODE, node->_telm0, n->_telm0, node->_left, n->_left, n->_right); } return node; } Tree23Node* addRight3(Tree23Node* node) { Tree23Node* n = node->_right; if (n != NULL && n->_type == TREE23_INSERT_ACTIVE) { n->_type = TREE23_BI_NODE; Tree23Node* nn = new Tree23Node(TREE23_BI_NODE, node->_telm0, node->_left, node->_midle); return new Tree23Node(TREE23_INSERT_ACTIVE, node->_telm1, nn, n); } return node; } Tree23Node* addMidle3(Tree23Node* node) { Tree23Node* n = node->_midle; if ( n != NULL && n->_type == TREE23_INSERT_ACTIVE ) { n->_left = new Tree23Node(TREE23_BI_NODE, node->_telm0, node->_left, n->_left); n->_right = new Tree23Node(TREE23_BI_NODE, node->_telm1, n->_right, node->_right); return n; } return node; } Tree23Node* removeMax(Tree23Node* node, Tree23Elm* elm) { if (node->_right == NULL) { switch (node->_type) { case 2: elm->_key = node->_telm0->_key; elm->_val = node->_telm0->_val; return new Tree23Node(TREE23_DELETE_ACTIVE); case 3: elm->_key = node->_telm1->_key; elm->_val = node->_telm1->_val; return new Tree23Node(TREE23_BI_NODE, node->_telm0); default: break; } } else { node->_right = removeMax(node->_right, elm); switch (node->_type) { case 2: return removeRight2(node); case 3: return removeRight3(node); default: break; } } return NULL; } Tree23Node* removeLeft2(Tree23Node* node) { Tree23Node* n = node->_left; if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) { Tree23Node* r = node->_right; Tree23Node* midle; Tree23Node* left; Tree23Node* right; switch ( r->_type ) { case 2: midle = new Tree23Node(TREE23_TRI_NODE, node->_telm0, r->_telm0, n->_midle, r->_left, r->_right); return new Tree23Node(TREE23_DELETE_ACTIVE, midle); case 3: left = new Tree23Node(TREE23_BI_NODE, node->_telm0, n->_midle, r->_left); right = new Tree23Node(TREE23_BI_NODE, r->_telm1, r->_midle, r->_right); return new Tree23Node(TREE23_BI_NODE, r->_telm0, left, right); default: break; } } return node; } Tree23Node* removeRight2(Tree23Node* node) { Tree23Node* n = node->_right; if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) { Tree23Node* l = node->_left; Tree23Node* midle; Tree23Node* left; Tree23Node* right; switch (l->_type) { case 2: midle = new Tree23Node(TREE23_TRI_NODE, l->_telm0, node->_telm0, l->_left, l->_right, n->_midle); return new Tree23Node(-1, midle); case 3: right = new Tree23Node(TREE23_BI_NODE, node->_telm0, l->_right, n->_midle); left = new Tree23Node(TREE23_BI_NODE, l->_telm0, l->_left, l->_midle); return new Tree23Node(TREE23_BI_NODE, l->_telm1, left, right); default: break; } } return node; } Tree23Node* removeLeft3(Tree23Node* node) { Tree23Node* n = node->_left; if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) { Tree23Node* m = node->_midle; Tree23Node* r = node->_right; Tree23Node* left; Tree23Node* midle; switch (m->_type) { case 2: left = new Tree23Node(TREE23_TRI_NODE, node->_telm0, m->_telm0, n->_midle, m->_left, m->_right); return new Tree23Node(TREE23_BI_NODE, node->_telm1, left, r); case 3: left = new Tree23Node(TREE23_BI_NODE, node->_telm0, n->_midle, m->_left); midle = new Tree23Node(TREE23_BI_NODE, m->_telm1, m->_midle, m->_right); return new Tree23Node(TREE23_TRI_NODE, m->_telm0, node->_telm1, left, midle, r); default: break; } } return node; } Tree23Node* removeMidle3(Tree23Node* node) { Tree23Node* n = node->_midle; if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) { Tree23Node* l = node->_left; Tree23Node* r = node->_right; Tree23Node* midle; Tree23Node* right; switch (r->_type) { case 2: right = new Tree23Node(TREE23_TRI_NODE, node->_telm1, r->_telm0, n->_midle, r->_left, r->_right); return new Tree23Node(TREE23_BI_NODE, node->_telm0, l, right); case 3: midle = new Tree23Node(TREE23_BI_NODE, node->_telm1, n->_midle, r->_left); right = new Tree23Node(TREE23_BI_NODE, r->_telm1, r->_midle, r->_right); return new Tree23Node(TREE23_TRI_NODE, node->_telm0, r->_telm0, l, midle, right); default: break; } } return node; } Tree23Node* removeRight3(Tree23Node* node) { Tree23Node* n = node->_right; if ( n != NULL && n->_type == TREE23_DELETE_ACTIVE ) { Tree23Node* l = node->_left; Tree23Node* m = node->_midle; Tree23Node* midle; Tree23Node* right; switch (m->_type) { case 2: right = new Tree23Node(TREE23_TRI_NODE, m->_telm0, node->_telm1, m->_left, m->_right, n->_midle); return new Tree23Node(TREE23_BI_NODE, node->_telm0, l, right); case 3: right = new Tree23Node(TREE23_BI_NODE, node->_telm1, m->_right, n->_midle); midle = new Tree23Node(TREE23_BI_NODE, m->_telm0, m->_left, m->_midle); return new Tree23Node(TREE23_TRI_NODE, node->_telm0, m->_telm1, l, midle, right); default: break; } } return node; } Tree23Node* _root; }; /*===================================== Class List =====================================*/ template class ListElm { template friend class List; public: ListElm() { _elm = 0; _prev = _next = 0; } ListElm(T* elm) { _elm = elm; _prev = _next = 0; } T* getContent(void) { return _elm; } ~ListElm(){} private: ListElm* getNext(void){return _next;} T* _elm; ListElm* _prev; ListElm* _next; }; template class List{ public: List() { _head = _tail = 0; _size = 0; } ~List() { clear(); } int add(T* t) { ListElm* elm = new ListElm(t); if ( elm == 0 ) { return 0; } if ( _head == 0 ) { _head = elm; _tail = elm; } else { elm->_prev = _tail; _tail->_next = elm; _tail = elm; } _size++; return 1; } void erase(ListElm* elm) { if ( _head == elm ) { _head = elm->_next; _size--; delete elm; } else if ( _tail == elm ) { _tail = elm->_prev; elm->_prev->_next = 0; _size--; delete elm; } else { elm->_prev->_next = elm->_next; elm->_next->_prev = elm->_prev; _size--; delete elm; } } void clear(void) { ListElm* p = _head; while ( p ) { ListElm* q = p->_next; delete p; p = q; } _head = 0; _tail = 0; _size = 0; } ListElm* getElm(void) { return _head; } ListElm* getNext(ListElm* elm) { return elm->getNext(); } int getSize(void) { return _size; } private: ListElm* _head; ListElm* _tail; int _size; }; extern Process* theProcess; extern MultiTaskProcess* theMultiTaskProcess; } #endif /* MQTTSNGWPROCESS_H_ */