├── .gitignore ├── CHANGES ├── LICENSE ├── LICENSE.GPL ├── Makefile.am ├── Makefile.in ├── README.md ├── aclocal.m4 ├── am.conf ├── ar-lib ├── autogen.sh ├── builder ├── Makefile.am ├── Makefile.in ├── README.md ├── builder_am.conf ├── conf │ ├── device_plugin.conf │ └── sample.conf ├── include │ ├── Makefile.am │ ├── Makefile.in │ ├── lower_layer_builder.h │ └── lower_layer_director.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ ├── builder.map │ ├── builder_action.c │ ├── builder_action.h │ ├── director.c │ ├── director.h │ └── lower_layer_director.c ├── sample_plugin │ ├── Makefile.am │ ├── Makefile.in │ ├── device_plugin_if.h │ ├── ossupport_device_plugin.c │ ├── ossupport_device_plugin.h │ ├── usb_device_plugin.c │ └── usb_device_plugin.h └── test │ ├── Makefile.am │ ├── Makefile.in │ └── main.c ├── chain_of_responsibility ├── CoR_am.conf ├── Makefile.am ├── Makefile.in ├── README.md ├── include │ ├── Makefile.am │ ├── Makefile.in │ └── chain_of_responsibility.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ ├── chain_element.c │ ├── chain_element.h │ ├── chain_of_responsibility.c │ └── chain_of_responsibility.map └── test │ ├── Makefile.am │ ├── Makefile.in │ └── main.c ├── combination_sample ├── Makefile.am ├── Makefile.in └── publisher_with_fd │ ├── Makefile.am │ ├── Makefile.in │ └── main.c ├── compile ├── config.guess ├── config.h.in ├── config.sub ├── configure ├── configure.ac ├── createVersionScript.sh ├── depcomp ├── design_pattern_util ├── Makefile.am ├── Makefile.in ├── include │ ├── Makefile.am │ ├── Makefile.in │ ├── dp_debug.h │ ├── dp_define.h │ ├── dp_list.h │ ├── dp_mutex.h │ └── dp_util.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ ├── dp_timelog.c │ └── dp_util.c └── sample │ ├── Makefile.am │ ├── Makefile.in │ ├── log.txt │ ├── main.c │ └── speedcheck.rb ├── flyweight ├── Makefile.am ├── Makefile.in ├── README.md ├── flyweight_am.conf ├── include │ ├── Makefile.am │ ├── Makefile.in │ └── flyweight.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ ├── flyweight.c │ └── flyweight.map └── test │ ├── Makefile.am │ ├── Makefile.in │ ├── main.c │ ├── test.h │ ├── test_methodsclass.c │ └── test_normalclass.c ├── install-sh ├── libtool ├── ltmain.sh ├── mement ├── Makefile.am ├── Makefile.in ├── include │ ├── Makefile.am │ ├── Makefile.in │ └── mement.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ └── mement.c ├── mement_am.conf └── test │ ├── Makefile.am │ ├── Makefile.in │ └── main.c ├── memorypool ├── Makefile.am ├── Makefile.in ├── include │ ├── Makefile.am │ ├── Makefile.in │ └── memorypool.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ ├── memorypool.c │ └── memorypool.map ├── memorypool_am.conf └── test │ ├── Makefile.am │ ├── Makefile.in │ └── main.c ├── missing ├── prototype ├── Makefile.am ├── Makefile.in ├── include │ ├── Makefile.am │ ├── Makefile.in │ └── prototype.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ ├── prototype.map │ ├── prototype_factory.c │ ├── prototype_factory.h │ └── prototype_manager.c ├── prototype_am.conf └── test │ ├── Makefile.am │ ├── Makefile.in │ └── main.c ├── publisher ├── Makefile.am ├── Makefile.in ├── README.md ├── include │ ├── Makefile.am │ ├── Makefile.in │ └── publisher.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ ├── publish_content.c │ ├── publish_content.h │ ├── publisher.c │ └── publisher.map ├── publisher_am.conf ├── sample │ ├── Makefile.am │ ├── Makefile.in │ ├── main.c │ ├── publish_msg.h │ ├── subscriber.c │ └── subscriber.h └── test │ ├── Makefile.am │ ├── Makefile.in │ └── main.c ├── state ├── Makefile.am ├── Makefile.in ├── README.md ├── include │ ├── Makefile.am │ ├── Makefile.in │ ├── state_machine.h │ └── state_manager.h ├── lib │ ├── Makefile.am │ ├── Makefile.in │ ├── state_machine.c │ ├── state_machine.map │ ├── state_manager.c │ └── state_manager.map ├── state_am.conf └── test │ ├── Makefile.am │ ├── Makefile.in │ ├── main.c │ ├── test_state_machine.c │ ├── test_state_machine.h │ ├── test_state_manager.c │ └── test_state_manager.h ├── test ├── README.md ├── coverage.sh ├── coverageResult.sh └── testAll.sh └── threadpool ├── Makefile.am ├── Makefile.in ├── README.md ├── event_if ├── Makefile.am ├── Makefile.in ├── event_if_epoll.c ├── event_if_libev.c ├── event_if_libevent.c └── event_if_select.c ├── include ├── Makefile.am ├── Makefile.in ├── event_threadpool.h ├── event_threadpool_data.h └── tpool_event_if.h ├── lib ├── Makefile.am ├── Makefile.in ├── event_thread.c ├── event_thread.h ├── event_tpool_manager.c └── threadpool.map ├── test ├── Makefile.am ├── Makefile.in ├── main.c ├── test_main.c └── test_main.h └── threadpool_am.conf /.gitignore: -------------------------------------------------------------------------------- 1 | #build object 2 | *.o 3 | *.lo 4 | *.la 5 | .deps 6 | .libs 7 | *.o 8 | 9 | #generated file by configure 10 | Makefile 11 | config.h 12 | config.log 13 | config.status 14 | config.h.in~ 15 | stamp-h1 16 | autom4te.cache 17 | 18 | #test/sample binary 19 | */test/test 20 | */sample/test 21 | publisher/sample/thread_sample 22 | combination_sample/publisher_with_fd/publish_with_fdevent 23 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | V.111 2 | Bug fix: 3 | - fix build error at clang(#49) 4 | - fix test code when limit of fd < 4096 (#51) 5 | 6 | V.110 7 | NEW: 8 | - Mement ; Add new 9 | 10 | Change Spec: 11 | - Builder: change interface of `lower_layer_director_construct` to get constructor parameter in callback. 12 | - Builder: change behavior of `lower_layer_director_construct`, switch sync or usync from input callback. NULL=>sync, return result at this API. 13 | - Builder: fix stack size of local thread, which call lower_layer_builder API 14 | - Common: Add extern C option in all header for C++ 15 | - Common: Move patterns which have only sample code to design_pattern_for_c_appendix 16 | 17 | Bug fix: 18 | - Builder: Fix to fail to load lib 19 | 20 | V1.00 21 | Support following: 22 | - Builder 23 | - Singleton (contained in Flyweight) 24 | - Flyweight 25 | - Chain of Responsibility 26 | - Observer(Publish-Subscribe) 27 | - State 28 | - Threadpool (with File disctriptor) 29 | - Memorypool 30 | - Prototype 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Hiroshi Tsuji 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.GPL: -------------------------------------------------------------------------------- 1 | All files in libev are 2 | Copyright (c)2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | Alternatively, the contents of this package may be used under the terms 29 | of the GNU General Public License ("GPL") version 2 or any later version, 30 | in which case the provisions of the GPL are applicable instead of the 31 | above. If you wish to allow the use of your version of this package only 32 | under the terms of the GPL and not to allow others to use your version of 33 | this file under the BSD license, indicate your decision by deleting the 34 | provisions above and replace them with the notice and other provisions 35 | required by the GPL in this and the other files of this package. If you do 36 | not delete the provisions above, a recipient may use your version of this 37 | file under either the BSD or the GPL. 38 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS=design_pattern_util 2 | if USE_FLYWEIGHT 3 | SUBDIRS+= flyweight 4 | endif 5 | 6 | if USE_BUILDER 7 | SUBDIRS+= builder 8 | endif 9 | 10 | if USE_PUBLISHER 11 | SUBDIRS+= publisher 12 | endif 13 | 14 | if USE_THREADPOOL 15 | SUBDIRS+= threadpool 16 | endif 17 | 18 | if USE_STATE 19 | SUBDIRS+= state 20 | endif 21 | 22 | if USE_COR 23 | SUBDIRS+= chain_of_responsibility 24 | endif 25 | 26 | if USE_MEMPOOL 27 | SUBDIRS+= memorypool 28 | endif 29 | 30 | if USE_PROTOTYPE 31 | SUBDIRS+= prototype 32 | endif 33 | 34 | if USE_MEMENT 35 | SUBDIRS+= mement 36 | endif 37 | 38 | if USE_SAMPLE 39 | SUBDIRS+= combination_sample 40 | endif 41 | -------------------------------------------------------------------------------- /am.conf: -------------------------------------------------------------------------------- 1 | AM_LDFLAGS= 2 | 3 | DPUTIL_DIR=$(top_srcdir)/design_pattern_util 4 | FLYWEIGHT_DIR=$(top_srcdir)/flyweight 5 | BUILDER_DIR=$(top_srcdir)/builder 6 | PUBLISHER_DIR=$(top_srcdir)/publisher 7 | CoR_DIR=$(top_srcdir)/chain_of_responsibility 8 | STATE_DIR=$(top_srcdir)/state 9 | THREADPOOL_DIR=$(top_srcdir)/threadpool 10 | MEMPOOL_DIR=$(top_srcdir)/memorypool 11 | PROTOTYPE_DIR=$(top_srcdir)/prototype 12 | MEMENT_DIR=$(top_srcdir)/mement 13 | 14 | AM_CPPFLAGS=-I$(DPUTIL_DIR)/include/ $(GCOV_OPT) 15 | INCLUDES_PATH=$(DPUTIL_DIR)/include/ 16 | -------------------------------------------------------------------------------- /ar-lib: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for Microsoft lib.exe 3 | 4 | me=ar-lib 5 | scriptversion=2012-03-01.08; # UTC 6 | 7 | # Copyright (C) 2010-2017 Free Software Foundation, Inc. 8 | # Written by Peter Rosin . 9 | # 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | # This file is maintained in Automake, please report 29 | # bugs to or send patches to 30 | # . 31 | 32 | 33 | # func_error message 34 | func_error () 35 | { 36 | echo "$me: $1" 1>&2 37 | exit 1 38 | } 39 | 40 | file_conv= 41 | 42 | # func_file_conv build_file 43 | # Convert a $build file to $host form and store it in $file 44 | # Currently only supports Windows hosts. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv in 65 | mingw) 66 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 67 | ;; 68 | cygwin) 69 | file=`cygpath -m "$file" || echo "$file"` 70 | ;; 71 | wine) 72 | file=`winepath -w "$file" || echo "$file"` 73 | ;; 74 | esac 75 | ;; 76 | esac 77 | } 78 | 79 | # func_at_file at_file operation archive 80 | # Iterate over all members in AT_FILE performing OPERATION on ARCHIVE 81 | # for each of them. 82 | # When interpreting the content of the @FILE, do NOT use func_file_conv, 83 | # since the user would need to supply preconverted file names to 84 | # binutils ar, at least for MinGW. 85 | func_at_file () 86 | { 87 | operation=$2 88 | archive=$3 89 | at_file_contents=`cat "$1"` 90 | eval set x "$at_file_contents" 91 | shift 92 | 93 | for member 94 | do 95 | $AR -NOLOGO $operation:"$member" "$archive" || exit $? 96 | done 97 | } 98 | 99 | case $1 in 100 | '') 101 | func_error "no command. Try '$0 --help' for more information." 102 | ;; 103 | -h | --h*) 104 | cat <success, other=>failed 7 | #int function (void * initial_parameter) 8 | #/after function name.comment, 9 | llbuilder_initial_name_1//If you write comment for interface, please add // after function name 10 | llbuilder_initial_name_2 11 | -------------------------------------------------------------------------------- /builder/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = lower_layer_builder.h lower_layer_director.h 2 | -------------------------------------------------------------------------------- /builder/include/lower_layer_builder.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lower_layer_builder.h 3 | * @brief This is API name definition for lower layer plugin library 4 | lower_layer_builder will load plugin defined this API. (this API will load by libbuilder.so as dynamic library) 5 | **/ 6 | #ifndef LOWER_LAYER_BUILDER_LIB_H_ 7 | #define LOWER_LAYER_BUILDER_LIB_H_ 8 | #include "dp_define.h" 9 | DP_H_BEGIN 10 | 11 | /*! result code : success */ 12 | #define LL_BUILDER_SUCCESS (0) 13 | /*! result code : error */ 14 | #define LL_BUILDER_FAILED (-1) 15 | 16 | /** 17 | * @brief new builder interface 18 | * @retval !=NULL this lower plugin interface class instance if lower library has it. 19 | * @retval NULL not implement interface 20 | */ 21 | void * lower_layer_builder_instance_new(void); 22 | /** 23 | * @brief name definition of plugin interface "new" 24 | */ 25 | #define LL_BUILDER_NEWNAME "lower_layer_builder_instance_new" 26 | 27 | /** 28 | * @brief free builder interface 29 | * @param[in] interfaceClass lower plugin interface class instance 30 | */ 31 | void lower_layer_builder_instance_free(void * interfaceClass); 32 | /** 33 | * @brief name definition of plugin interface "free" 34 | */ 35 | #define LL_BUILDER_FREENAME "lower_layer_builder_instance_free" 36 | 37 | DP_H_END 38 | #endif 39 | -------------------------------------------------------------------------------- /builder/include/lower_layer_director.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lower_layer_director.h 3 | * @brief This is API for director class action as design petten 4 | * In this case, Builder interface is included by conf file, and interface implement class is dynamic library. 5 | * Please see conf/sample.conf 6 | **/ 7 | 8 | #ifndef LOWER_LAYER_DIRECTOR_H_ 9 | #define LOWER_LAYER_DIRECTOR_H_ 10 | #include "lower_layer_builder.h" 11 | DP_H_BEGIN 12 | 13 | /*! @struct director_t 14 | * @brief director class member definition 15 | */ 16 | struct director_t; 17 | /** @brief Typedef class Director, member is defined in struct director_t */ 18 | typedef struct director_t *Director; 19 | 20 | /*! @struct lower_layer_director_t 21 | * @brief LowerLayerDirector class member definition 22 | */ 23 | struct lower_layer_director_t { 24 | void * lower_layer_interface;/*!< interface which has lower layer(builder). If no interface, it is NULL*/ 25 | Director director;/*!< director class instance */ 26 | }; 27 | 28 | /** @brief LowerLayerDirector class definition */ 29 | typedef struct lower_layer_director_t lower_layer_director_t, *LowerLayerDirector; 30 | 31 | /** 32 | * @brief director new 33 | * 34 | * @param[in] builder_lib_name library name implement builder interface 35 | * @param[in] builder_interface_conf conf file write interface definition 36 | * @retval !=NULL LowerLayerDirector class instance. 37 | * @retval NULL error 38 | */ 39 | LowerLayerDirector lower_layer_director_new(char * builder_lib_name, char * builder_interface_conf); 40 | 41 | /** 42 | * @brief director cconstruct 43 | * 44 | * @param[in] director LowerLayerDirector class instance returned at lower_layer_director_construct 45 | * @param[in] initial_parameter initialize parameter if you have 46 | * @param[in] initial_result initialize callback if you want to unsync call API, result is in here 47 | * @return LL_BUILDER_SUCCESS or LL_BUILDER_FAILED 48 | */ 49 | int lower_layer_director_construct(LowerLayerDirector director, void * initial_parameter, void (*initial_result)(void * initial_parameter, int result)); 50 | 51 | /** 52 | * @brief director denstruct 53 | * 54 | * @param[in] director LowerLayerDirector class instance returned at lower_layer_director_construct 55 | */ 56 | void lower_layer_director_free(LowerLayerDirector director); 57 | DP_H_END 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /builder/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/builder/builder_am.conf 3 | 4 | lib_LTLIBRARIES = liblower_layer_director.la 5 | 6 | liblower_layer_director_la_SOURCES = lower_layer_director.c builder_action.c director.c 7 | #for statik library 8 | liblower_layer_director_la_LDFLAGS=-shared $(top_srcdir)/design_pattern_util/lib/libdputil.la 9 | liblower_layer_director_la_LDFLAGS+=-Wl,--version-script,builder.map 10 | -------------------------------------------------------------------------------- /builder/lib/builder.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | lower_layer_builder_instance_new; 4 | lower_layer_builder_instance_free; 5 | layer; 6 | lower_layer_director_new; 7 | lower_layer_director_construct; 8 | lower_layer_director_free; 9 | local: *; 10 | }; 11 | -------------------------------------------------------------------------------- /builder/lib/builder_action.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file builder_action.c 3 | * @brief Implement of builder_action, running construct on other thread 4 | **/ 5 | #include 6 | #include 7 | #include 8 | #include "builder_action.h" 9 | #include "dp_debug.h" 10 | 11 | #define THREAD_STACKSIZE (256 * 1024)/*suitable stack size*/ 12 | 13 | /************* 14 | * public define 15 | *************/ 16 | 17 | /*! @struct BuilderAction 18 | * @brief action builder, to call builder by other thread, create class for it 19 | */ 20 | typedef builder_action_parameter_t *BuilderAction; 21 | 22 | /*! @name BuilderAction private method */ 23 | /* @{ */ 24 | /*! @brief run main */ 25 | static int builder_action_main(BuilderAction this); 26 | /*! @brief run action */ 27 | static void * builder_action_run(void * this); 28 | /* @} */ 29 | 30 | /************* 31 | * for BuilderAction method 32 | *************/ 33 | static int builder_action_main(BuilderAction this) { 34 | int i=0; 35 | int ret = LL_BUILDER_SUCCESS; 36 | //call builder methods 37 | for( i = 0; i < this->builder_method_cnt; i++) { 38 | if(this->builder_methods[i]) { 39 | DEBUG_ERRPRINT("methods[%d] call\n", i); 40 | ret = this->builder_methods[i](this->initial_parameter); 41 | if(ret == LL_BUILDER_FAILED) { 42 | break; 43 | } 44 | } 45 | } 46 | return ret; 47 | } 48 | 49 | static void * builder_action_run(void * arg) { 50 | BuilderAction this = (BuilderAction) arg; 51 | int i=0; 52 | int ret = builder_action_main(this); 53 | 54 | //call result callback 55 | if(this->initial_result) { 56 | this->initial_result(this->initial_parameter , ret); 57 | } 58 | free(this); 59 | pthread_exit(NULL); 60 | return NULL; 61 | } 62 | 63 | /*! @name BuilderAction public method */ 64 | /* @{ */ 65 | void builder_action_destruct(pthread_t tid) { 66 | if(0 9 | #include "lower_layer_builder.h" 10 | 11 | /*! @struct builder_action_parameter_t 12 | * @brief builder action parameter 13 | */ 14 | typedef struct builder_action_parameter_t { 15 | void * initial_parameter; 16 | void (*initial_result)(void * initial_parameter, int result); 17 | int builder_method_cnt; 18 | int (** builder_methods)(void * initial_parameter); 19 | } builder_action_parameter_t; 20 | 21 | /*! @name BuilderAction public method */ 22 | /* @{ */ 23 | /*! @brief construct action */ 24 | pthread_t builder_action_construct(builder_action_parameter_t * parameter); 25 | int builder_action_construct_sync(builder_action_parameter_t * parameter); 26 | /** @brief deconstruct action */ 27 | void builder_action_destruct(pthread_t tid); 28 | /* @} */ 29 | #endif 30 | -------------------------------------------------------------------------------- /builder/lib/director.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file director.c 3 | * @brief Implement of director API, defined in director.h 4 | **/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "builder_action.h" 11 | #include "director.h" 12 | #include "dp_debug.h" 13 | 14 | /************* 15 | * public define 16 | *************/ 17 | #define LLD_METHODSIZE_MAX (64) 18 | 19 | /*! @struct Director 20 | * @brief director class 21 | */ 22 | struct director_t { 23 | //public 24 | pthread_t tid; 25 | int is_sync; 26 | int builder_method_cnt; 27 | int (** builder_methods)(void * initial_parameter); 28 | //private 29 | void * dlhandle; 30 | void * (*builder_instance_new)(void); 31 | void (*builder_instance_free)(void *interface); 32 | }; 33 | 34 | /*! @name Director private method */ 35 | /* @{ */ 36 | static int director_open_library(Director this, char * builder_lib_name); 37 | static int director_load_methods(char * conffile, char ***methodname); 38 | static void director_free_methods(int methodcnt, char **methodname); 39 | static int director_add_methods(Director this, int methodcnt, char **methodname); 40 | static void director_load_interface_method(Director this); 41 | /* @} */ 42 | 43 | /************* 44 | * for Director private method 45 | *************/ 46 | /*! @name Director private method implement*/ 47 | /* @{ */ 48 | static int director_open_library(Director this, char * builder_lib_name) { 49 | //load library 50 | void * handle = dlopen(builder_lib_name, RTLD_NOW); 51 | if(!handle) { 52 | DEBUG_ERRPRINT("failed to open library %s\n", builder_lib_name); 53 | return LL_BUILDER_FAILED; 54 | } 55 | this->dlhandle = handle; 56 | return LL_BUILDER_SUCCESS; 57 | } 58 | 59 | static int director_load_methods(char * conffile, char ***methodname) { 60 | int ret_num=0; 61 | FILE *fp = fopen(conffile, "r"); 62 | if(!fp) { 63 | DEBUG_ERRPRINT("failed to open file %s\n", conffile); 64 | return LL_BUILDER_FAILED; 65 | } 66 | 67 | //count max line 68 | int line=0; 69 | char buffer[LLD_METHODSIZE_MAX]; 70 | while(fgets(buffer, sizeof(buffer), fp) != NULL) { 71 | line++; 72 | } 73 | //goto head 74 | fseek(fp, 0, SEEK_SET); 75 | 76 | //allocate 77 | *methodname = (char **) calloc(line, sizeof(char *)); 78 | if(!*methodname) { 79 | goto err; 80 | } 81 | 82 | //read conf 83 | while(fgets(buffer, sizeof(buffer), fp) != NULL) { 84 | //skip comment 85 | if(buffer[0]=='#') { 86 | DEBUG_ERRPRINT("continue comment\n"); 87 | continue; 88 | } 89 | 90 | //allocate memory 91 | (*methodname)[ret_num] = calloc(1, LLD_METHODSIZE_MAX); 92 | if(!methodname[ret_num]) { 93 | goto err; 94 | } 95 | 96 | //clear after comment 97 | char *after_comment = strstr(buffer, "/"); 98 | if(after_comment) { 99 | *after_comment = 0; 100 | } 101 | 102 | snprintf((*methodname)[ret_num++], LLD_METHODSIZE_MAX, "%s", buffer); 103 | } 104 | fclose(fp); 105 | return ret_num; 106 | err: 107 | fclose(fp); 108 | director_free_methods(ret_num, *methodname); 109 | return LL_BUILDER_FAILED; 110 | } 111 | 112 | static void director_free_methods(int methodcnt, char **methodname) { 113 | if(!methodname) { 114 | return; 115 | } 116 | 117 | int i=0; 118 | for(i = 0; i < methodcnt; i ++ ) { 119 | free(methodname[i]); 120 | } 121 | free(methodname); 122 | } 123 | 124 | static int director_add_methods(Director this, int methodcnt, char **methodname) { 125 | this->builder_methods = calloc(methodcnt, sizeof(void (*)(void *))); 126 | if(!this->builder_methods) { 127 | return LL_BUILDER_FAILED; 128 | } 129 | 130 | int i=0; 131 | for( i = 0; i < methodcnt; i ++ ) { 132 | //don't care NULL 133 | this->builder_methods[i] = dlsym(this->dlhandle, methodname[i]); 134 | if(!this->builder_methods) { 135 | DEBUG_ERRPRINT("library API %s is not implement, error detail =%s\n", methodname[i], dlerror()); 136 | } 137 | } 138 | this->builder_method_cnt = methodcnt; 139 | return LL_BUILDER_SUCCESS; 140 | } 141 | 142 | static void director_load_interface_method(Director this) { 143 | this->builder_instance_new = dlsym(this->dlhandle, LL_BUILDER_NEWNAME); 144 | if( this->builder_instance_new ) { 145 | this->builder_instance_free = dlsym(this->dlhandle, LL_BUILDER_FREENAME); 146 | } 147 | } 148 | 149 | /* @} */ 150 | 151 | /*! @name Director public method implement*/ 152 | /* @{ */ 153 | Director director_new(char * builder_lib_name, char * builder_interface_conf) { 154 | int ret = LL_BUILDER_FAILED; 155 | int methodcnt; 156 | char **methodnames=NULL; 157 | 158 | Director instance = (Director) calloc(1, sizeof(*instance)); 159 | if(!instance) { 160 | DEBUG_ERRPRINT("failed to calloc\n"); 161 | return NULL; 162 | } 163 | 164 | //load library 165 | ret = director_open_library(instance, builder_lib_name); 166 | if( ret == LL_BUILDER_FAILED ) { 167 | DEBUG_ERRPRINT("failed to open library\n"); 168 | goto err; 169 | } 170 | 171 | //get methods name from conf 172 | methodcnt = director_load_methods(builder_interface_conf, &methodnames); 173 | if( methodcnt == LL_BUILDER_FAILED ) { 174 | DEBUG_ERRPRINT("failed to load methods conf %s\n", builder_interface_conf); 175 | goto err; 176 | } 177 | 178 | //load library method in conf 179 | ret = director_add_methods(instance, methodcnt, methodnames); 180 | //free local memory 181 | director_free_methods(methodcnt, methodnames); 182 | if( ret == LL_BUILDER_FAILED ) { 183 | DEBUG_ERRPRINT("failed to load methods conf %s\n", builder_interface_conf); 184 | goto err; 185 | } 186 | 187 | //load common library 188 | director_load_interface_method(instance); 189 | return instance; 190 | 191 | err: 192 | director_free(instance); 193 | return NULL; 194 | } 195 | 196 | int director_construct(Director director, void * initial_parameter, void (*initial_result)(void * initial_parameter, int result)) { 197 | 198 | int ret = LL_BUILDER_SUCCESS; 199 | builder_action_parameter_t parameter; 200 | parameter.initial_parameter = initial_parameter; 201 | parameter.initial_result = initial_result; 202 | parameter.builder_method_cnt = director->builder_method_cnt; 203 | parameter.builder_methods = director->builder_methods; 204 | 205 | if(parameter.initial_result) { 206 | director->tid = builder_action_construct(¶meter); 207 | } else { 208 | director->is_sync = 1; 209 | ret = builder_action_construct_sync(¶meter); 210 | } 211 | return ret; 212 | } 213 | 214 | void director_destruct(Director director) { 215 | //to care constructing now 216 | if(!director->is_sync) { 217 | builder_action_destruct(director->tid); 218 | } 219 | } 220 | 221 | void * director_interface_class_new(Director this) { 222 | if(!this || !this->builder_instance_new) { 223 | DEBUG_ERRPRINT("No interface\n"); 224 | return NULL; 225 | } 226 | 227 | return this->builder_instance_new(); 228 | } 229 | 230 | void director_interface_class_free(Director this, void * instance) { 231 | if(!instance || !this->builder_instance_free) { 232 | DEBUG_ERRPRINT("No interface\n"); 233 | return; 234 | } 235 | 236 | this->builder_instance_free(instance); 237 | } 238 | 239 | void director_free(Director this) { 240 | if(!this) { 241 | return; 242 | } 243 | 244 | //free instance 245 | free(this->builder_methods); 246 | 247 | //close library 248 | if(this->dlhandle) { 249 | if(dlclose(this->dlhandle)) { 250 | DEBUG_ERRPRINT("failed to unload library\n"); 251 | } 252 | } 253 | 254 | free(this); 255 | } 256 | /* @} */ 257 | -------------------------------------------------------------------------------- /builder/lib/director.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file director.h 3 | * @brief This is API definition of Director class 4 | **/ 5 | #ifndef DIRECTOR_H_ 6 | #define DIRECTOR_H_ 7 | #include "lower_layer_director.h" 8 | 9 | /*! @name DirectorClass public method */ 10 | /* @{ */ 11 | /*! @brief director new */ 12 | Director director_new(char * builder_lib_name, char * builder_interface_conf); 13 | /*! @brief director construct */ 14 | int director_construct(Director director, void * initial_parameter, void (*initial_result)(void * initial_parameter, int result)); 15 | /*! @brief director destruct */ 16 | void director_destruct(Director director); 17 | /*! @brief interface class new */ 18 | void * director_interface_class_new(Director this); 19 | /*! @brief interface class free */ 20 | void director_interface_class_free(Director this, void * instance); 21 | /*! @brief director free */ 22 | void director_free(Director this); 23 | /* }@ */ 24 | #endif 25 | -------------------------------------------------------------------------------- /builder/lib/lower_layer_director.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lower_layer_director.c 3 | * @brief Implement of lower_layer_director (related to builder design petten) library API, defined in flyweight.h 4 | **/ 5 | #include 6 | #include 7 | #include 8 | #include "director.h" 9 | #include "lower_layer_builder.h" 10 | #include "dp_debug.h" 11 | 12 | /************* 13 | * public interface API implement 14 | *************/ 15 | LowerLayerDirector lower_layer_director_new(char * builder_lib_name, char * builder_interface_conf) { 16 | LowerLayerDirector instance = calloc(1, sizeof(*instance)); 17 | if(!instance) { 18 | return NULL; 19 | } 20 | 21 | instance->director = director_new(builder_lib_name, builder_interface_conf); 22 | if(!instance->director) { 23 | DEBUG_ERRPRINT("failed to new director\n"); 24 | goto err; 25 | } 26 | 27 | instance->lower_layer_interface = director_interface_class_new(instance->director); 28 | return instance; 29 | err: 30 | lower_layer_director_free(instance); 31 | return NULL; 32 | } 33 | 34 | int lower_layer_director_construct(LowerLayerDirector this, void * initial_parameter, void (*initial_result)(void * initial_parameter, int result)) { 35 | return director_construct(this->director, initial_parameter, initial_result); 36 | } 37 | 38 | void lower_layer_director_free(LowerLayerDirector this) { 39 | if(!this) { 40 | return; 41 | } 42 | 43 | Director director = this->director; 44 | 45 | if(director) { 46 | //destruct 47 | director_destruct(director); 48 | 49 | //interface free 50 | director_interface_class_free(director, this->lower_layer_interface); 51 | 52 | //director free 53 | director_free(director); 54 | } 55 | free(this); 56 | } 57 | -------------------------------------------------------------------------------- /builder/sample_plugin/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/builder/builder_am.conf 3 | 4 | noinst_LTLIBRARIES = libossupport_device_plugin.la libusb_device_plugin.la 5 | # 6 | #lib_LTLIBRARIES = libbuilder.la 7 | 8 | libossupport_device_plugin_la_SOURCES = ossupport_device_plugin.c 9 | libossupport_device_plugin_la_LDFLAGS=-module -shared -export-dynamic -rpath $(libdir) 10 | 11 | libusb_device_plugin_la_SOURCES = usb_device_plugin.c 12 | libusb_device_plugin_la_LDFLAGS=-module -shared -export-dynamic -rpath $(libdir) 13 | -------------------------------------------------------------------------------- /builder/sample_plugin/device_plugin_if.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICE_PLUGIN_IF_ 2 | #define DEVICE_PLUGIN_IF_ 3 | 4 | /*! @Class 5 | * @brief device plugin interface, all plugin use it 6 | */ 7 | struct device_plugin_interface; 8 | typedef struct device_plugin_interface device_plugin_interface_t, *DevicePluginInterface; 9 | 10 | struct device_plugin_interface { 11 | void (*connect)(DevicePluginInterface this); 12 | void (*disconnect)(DevicePluginInterface this); 13 | }; 14 | 15 | //define LowerLayerInterface by DevicePluginInterface 16 | 17 | #define DEVICE_PLUGIN_INTERFACE \ 18 | void (*connect)(DevicePluginInterface this);\ 19 | void (*disconnect)(DevicePluginInterface this); 20 | #endif 21 | -------------------------------------------------------------------------------- /builder/sample_plugin/ossupport_device_plugin.c: -------------------------------------------------------------------------------- 1 | #include "ossupport_device_plugin.h" 2 | #include "lower_layer_builder.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define DEBUG_PRINT(...) printf("[ethernet] ");printf(__VA_ARGS__); 8 | 9 | typedef struct osssupport_dp_interface { 10 | DEVICE_PLUGIN_INTERFACE 11 | char gateway[64]; 12 | int retry_time; 13 | int outsize; 14 | } osssupport_device_plugin_interface_t, *OSSSupportDPInterface; 15 | 16 | static void ossupport_device_connect(DevicePluginInterface handle) { 17 | OSSSupportDPInterface this = (OSSSupportDPInterface) handle; 18 | 19 | DEBUG_PRINT("set gateway %s!!\n", this->gateway); 20 | DEBUG_PRINT("check connection to WAN!\n"); 21 | int i=0; 22 | for(i = 0; i < this->retry_time; i++ ) { 23 | if( this->outsize ) { 24 | DEBUG_PRINT("Success to connect!\n"); 25 | return; 26 | } else { 27 | DEBUG_PRINT("Failed to connect, try [%d/%d]\n", i+1 , this->retry_time); 28 | sleep(1); 29 | } 30 | } 31 | 32 | DEBUG_PRINT("Failed to connect, retry time %d\n", i ); 33 | return; 34 | } 35 | 36 | static void ossupport_device_disconnect(DevicePluginInterface handle) { 37 | OSSSupportDPInterface this = (OSSSupportDPInterface) handle; 38 | DEBUG_PRINT("remove gateway %s!!\n", this->gateway); 39 | } 40 | 41 | //initialize device, as set IP, ... 42 | int llbuilder_initial_device(void * arg) { 43 | ossupport_device_s *device = (ossupport_device_s *)arg; 44 | sprintf(device->device_name, "eth0"); 45 | DEBUG_PRINT("ifup %s!!\n", device->device_name); 46 | sprintf(device->ipaddress, "192.168.56.100"); 47 | DEBUG_PRINT("set ip address %s!!\n", device->ipaddress); 48 | return 0; 49 | } 50 | 51 | //don't need load device, not implement! 52 | 53 | void * lower_layer_builder_instance_new(void) { 54 | OSSSupportDPInterface instance = calloc(1, sizeof(*instance)); 55 | if(!instance) { 56 | return NULL; 57 | } 58 | 59 | instance->connect = ossupport_device_connect; 60 | instance->disconnect = ossupport_device_disconnect; 61 | sprintf(instance->gateway, "192.168.56.1"); 62 | 63 | instance->retry_time = 3; 64 | instance->outsize = time(NULL)%2; 65 | return instance; 66 | } 67 | 68 | void lower_layer_builder_instance_free(void * interfaceClass) { 69 | free(interfaceClass); 70 | } 71 | -------------------------------------------------------------------------------- /builder/sample_plugin/ossupport_device_plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef OSSUPPORT_DEVICE_PLUGIN_ 2 | #define OSSUPPORT_DEVICE_PLUGIN_ 3 | //interface definition is here 4 | #include "device_plugin_if.h" 5 | 6 | /*! @struct 7 | * @brief ossupport_device, have to use ssid and key 8 | */ 9 | typedef struct ossupport_device_ { 10 | char device_name[64]; 11 | char ipaddress[64]; 12 | } ossupport_device_s; 13 | #endif 14 | -------------------------------------------------------------------------------- /builder/sample_plugin/usb_device_plugin.c: -------------------------------------------------------------------------------- 1 | #include "usb_device_plugin.h" 2 | #include "lower_layer_builder.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define DEBUG_PRINT(...) printf("[wifi] ");printf(__VA_ARGS__); 9 | 10 | typedef struct usb_dp_interface { 11 | DEVICE_PLUGIN_INTERFACE 12 | char gateway[64]; 13 | } usb_device_plugin_interface_t, *USBDPInterface; 14 | 15 | USBDPInterface usb_dp_interface_g=NULL; 16 | 17 | static void usd_device_connect(DevicePluginInterface handle) { 18 | USBDPInterface this = (USBDPInterface) handle; 19 | 20 | DEBUG_PRINT("check connection to gateway!!"); 21 | DEBUG_PRINT("Success to connect!, gateway IP:[%s]\n", this->gateway); 22 | } 23 | 24 | static void usd_device_disconnect(DevicePluginInterface handle) { 25 | DEBUG_PRINT("disconnect!!"); 26 | } 27 | 28 | int llbuilder_load_driver(void * arg) { 29 | wifi_device_s *device = (wifi_device_s *)arg; 30 | DEBUG_PRINT("load device driver related to %s device!!\n", device->device_name); 31 | 32 | sleep(1); 33 | 34 | DEBUG_PRINT("Success to load device driver, we can use %s device!!\n", device->device_name); 35 | return 0; 36 | } 37 | 38 | int llbuilder_initial_device(void * arg) { 39 | wifi_device_s *device = (wifi_device_s *)arg; 40 | DEBUG_PRINT("Scanning access point!!\n"); 41 | int i=0; 42 | for(i = 0; i < 10; i ++) { 43 | printf("."); 44 | usleep(100); 45 | } 46 | 47 | sprintf(device->ssid, "sampleSSID"); 48 | DEBUG_PRINT("Find access point!! ssid[%s]\n", device->ssid); 49 | 50 | sprintf(device->device_name, "wlan0"); 51 | DEBUG_PRINT("ifup %s!!\n", device->device_name); 52 | sprintf(device->ipaddress, "192.168.100.100"); 53 | DEBUG_PRINT("get ip address %s from Access point!!\n", device->ipaddress); 54 | 55 | sprintf(usb_dp_interface_g->gateway, "192.168.100.1"); 56 | return 0; 57 | } 58 | 59 | void * lower_layer_builder_instance_new(void) { 60 | usb_dp_interface_g = calloc(1, sizeof(*usb_dp_interface_g)); 61 | usb_dp_interface_g->connect=usd_device_connect; 62 | usb_dp_interface_g->disconnect=usd_device_disconnect; 63 | return usb_dp_interface_g; 64 | } 65 | 66 | void lower_layer_builder_instance_free(void * interfaceClass) { 67 | free(interfaceClass); 68 | } 69 | -------------------------------------------------------------------------------- /builder/sample_plugin/usb_device_plugin.h: -------------------------------------------------------------------------------- 1 | #ifndef USB_WIFI_DEVICE_PLUGIN_ 2 | #define USB_WIFI_DEVICE_PLUGIN_ 3 | //interface definition is here 4 | #include "device_plugin_if.h" 5 | 6 | /*! @struct 7 | * @brief wifie_device, have to use ssid and key 8 | */ 9 | typedef struct wifi_device_ { 10 | char device_name[64]; 11 | char ipaddress[64]; 12 | char ssid[64]; 13 | } wifi_device_s; 14 | #endif 15 | -------------------------------------------------------------------------------- /builder/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/builder/builder_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CFLAGS = -g -O0 7 | test_SOURCES = main.c 8 | -------------------------------------------------------------------------------- /builder/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "lower_layer_director.h" 5 | #include "ossupport_device_plugin.h" 6 | #include "usb_device_plugin.h" 7 | 8 | #define CONFNAME "../conf/device_plugin.conf" 9 | #define USBPLUGIN_NAME "../sample_plugin/.libs/libusb_device_plugin.so" 10 | #define OSSSUPPORT_PLUGIN_NAME "../sample_plugin/.libs/libossupport_device_plugin.so" 11 | 12 | static int result_g; 13 | static void initial_result(void * initial_parameter, int result) { 14 | printf("<%s> result=%d\n", __FUNCTION__, result); 15 | result_g = result; 16 | } 17 | 18 | int main(int argc, char *argv[]) { 19 | printf("If not set parameter=> try to load %s\n", USBPLUGIN_NAME); 20 | printf("Otherwise=> try to load %s\n", OSSSUPPORT_PLUGIN_NAME); 21 | 22 | char *libname[]={USBPLUGIN_NAME, OSSSUPPORT_PLUGIN_NAME}; 23 | 24 | int i; 25 | for(i=0;ilower_layer_interface; 48 | interface->connect(interface); 49 | printf("Disconnect!!\n"); 50 | interface->disconnect(interface); 51 | 52 | printf("Exit\n"); 53 | lower_layer_director_free(director); 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /chain_of_responsibility/CoR_am.conf: -------------------------------------------------------------------------------- 1 | #common header deifinition 2 | include $(top_srcdir)/am.conf 3 | 4 | AM_CPPFLAGS+=-I$(FLYWEIGHT_DIR)/include -I$(CoR_DIR)/include 5 | INCLUDES_PATH+=$(FLYWEIGHT_DIR)/include -I$(CoR_DIR)/include 6 | 7 | AM_LDFLAGS+=$(CoR_DIR)/lib/libchainofresp.la 8 | -------------------------------------------------------------------------------- /chain_of_responsibility/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib include test 2 | -------------------------------------------------------------------------------- /chain_of_responsibility/README.md: -------------------------------------------------------------------------------- 1 | # ChainOfResponsibility 2 | The library for Linux C language to use ChainOfResponsibility pattern. 3 | 4 | # How to use 5 | After build all, please link libchainofresp.so library. 6 | API header is in chain_of_responsibility.h 7 | 8 | Please see wiki "https://github.com/developer-kikikaikai/design_pattern_for_c/wiki/Chain-of-Responsibility" for more detai. 9 | -------------------------------------------------------------------------------- /chain_of_responsibility/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = chain_of_responsibility.h 2 | -------------------------------------------------------------------------------- /chain_of_responsibility/include/chain_of_responsibility.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file chain_of_responsibility.h 3 | * @brief This is API for Chain of Responsibility design pettern class 4 | **/ 5 | #ifndef CHAIN_OF_RESPONSIBILITY_H_ 6 | #define CHAIN_OF_RESPONSIBILITY_H_ 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | 10 | /*! 11 | * @brief chain_api result type 12 | */ 13 | typedef enum { 14 | CoR_GONEXT,/*!< go to next */ 15 | CoR_RETURN,/*!< exit to call chain_api*/ 16 | } cor_result_e; 17 | 18 | /*! @struct chain_of_resp_t 19 | * ChainElementPart class instance definition, which is a part of chain. This member is defined in chain_element.c. 20 | */ 21 | struct chain_element_part; 22 | /** ChainElementPart class definition */ 23 | typedef struct chain_element_part * ChainElementPart; 24 | 25 | /** 26 | * @brief chain func 27 | * 28 | * @param[in] arg input parameter pointer, related to function 29 | * @param[in] ctx context information registered at cor_add_function 30 | * @retval CoR_GONEXT -> call next chain_api 31 | * @retval CoR_RETURN -> exit to call chain_api 32 | */ 33 | typedef cor_result_e (*chain_func)(void *arg, void *ctx); 34 | 35 | /** 36 | * @brief set thredsafe 37 | * 38 | * @param [in] is_threadsafe 1 if you want to use threadsafe. 39 | * @return none 40 | */ 41 | void cor_set_threadsafe(int is_threadsafe); 42 | 43 | /** 44 | * @brief add to chain api 45 | * 46 | * @param[in] id key id related to chain api 47 | * @param[in] func chain func 48 | * @param[in] ctx user defined context information 49 | * @retval !=NULL -> Success to add, if you want to remove element, please keep it. 50 | * @retval NULL -> Faled to add 51 | */ 52 | ChainElementPart cor_add_function(const int id, chain_func func, void *ctx); 53 | 54 | /** 55 | * @brief call chain api 56 | * 57 | * @param[in] id key id related to chain api 58 | * @param[in] arg input parameter pointer, related to function 59 | * @return none. If you want to get result, please define input parameter to know result 60 | */ 61 | void cor_call(const int id, void *arg); 62 | 63 | /** 64 | * @brief remove to chain api 65 | * 66 | * @param[in] id key id related to chain api 67 | * @param[in] func chain api func 68 | * @return none 69 | * @note This function remove all functions which is same address. So if you set same function by cor_add_function, all of them will remove. 70 | * @note This function "NOT" free ctx 71 | */ 72 | void cor_remove_function(const int id, chain_func func); 73 | 74 | /** 75 | * @brief remove to chain api 76 | * 77 | * @param[in] id key id related to chain api 78 | * @param[in] element chain element returned at cor_add_function 79 | * @return none 80 | * @note This function only remove element. So if you want to register same functions, and remove only one element, please use it. 81 | * @note This function "NOT" free ctx 82 | */ 83 | void cor_remove_chain_element_part(const int id, ChainElementPart element); 84 | 85 | /** 86 | * @brief clear all list 87 | * 88 | * @return none 89 | */ 90 | void cor_clear(void); 91 | DP_H_END 92 | #endif 93 | -------------------------------------------------------------------------------- /chain_of_responsibility/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/chain_of_responsibility/CoR_am.conf 3 | 4 | lib_LTLIBRARIES = libchainofresp.la 5 | 6 | libchainofresp_la_SOURCES = chain_element.c chain_of_responsibility.c 7 | #for statik library 8 | libchainofresp_la_LDFLAGS=-shared $(DPUTIL_DIR)/lib/libdputil.la $(FLYWEIGHT_DIR)/lib/libflyweight.la -Xlinker -rpath -Xlinker $(libdir) 9 | libchainofresp_la_LDFLAGS+=-Wl,--version-script,chain_of_responsibility.map 10 | -------------------------------------------------------------------------------- /chain_of_responsibility/lib/chain_element.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file chain_element.c 3 | * @brief Implement of ChainElement class 4 | **/ 5 | 6 | #include "dp_util.h" 7 | #include "chain_element.h" 8 | 9 | /*! @name ChainElementPart class */ 10 | /* @{ */ 11 | 12 | /*! @struct ChainElementPart 13 | * @brief chain function element part class instance definition 14 | */ 15 | typedef struct chain_element_part * ChainElementPart; 16 | struct chain_element_part { 17 | ChainElementPart next; 18 | ChainElementPart prev; 19 | chain_element_data_t data; 20 | }; 21 | 22 | /*! @brief new ChainElementPart */ 23 | static ChainElementPart chain_element_part_new(chain_element_data_t * element_data); 24 | /*! @brief free ChainElementPart */ 25 | static void chain_element_part_free(ChainElementPart this); 26 | /* @} */ 27 | 28 | /*! @struct chain_element 29 | * @brief ChainElement class instance definition 30 | */ 31 | struct chain_element_t { 32 | ChainElementPart head;/*! list of ChainElementPart*/ 33 | ChainElementPart tail; 34 | pthread_mutex_t *lock;/*! lock */ 35 | }; 36 | 37 | #define CHAIN_ELEMENT_LOCK(instance) DPUTIL_LOCK(instance->lock) 38 | #define CHAIN_ELEMENT_UNLOCK DPUTIL_UNLOCK 39 | 40 | /************* 41 | * for ChainElementPart class API definition 42 | *************/ 43 | static ChainElementPart chain_element_part_new(chain_element_data_t * element_data) { 44 | ChainElementPart element = calloc(1, sizeof(*element)); 45 | if(!element) { 46 | return NULL; 47 | } 48 | 49 | memcpy(&element->data, element_data, sizeof(element->data)); 50 | return element; 51 | } 52 | 53 | static void chain_element_part_free(ChainElementPart this) { 54 | free(this); 55 | } 56 | 57 | ChainElement chain_element_new(int is_threadsafe) { 58 | ChainElement element = calloc(1, sizeof(*element) + (is_threadsafe * sizeof(pthread_mutex_t))); 59 | if(!element) { 60 | return NULL; 61 | } 62 | 63 | if(is_threadsafe) { 64 | element->lock = (pthread_mutex_t *)(element + 1); 65 | pthread_mutex_init(element->lock, NULL); 66 | } 67 | return element; 68 | } 69 | 70 | /************* 71 | * public API definition 72 | *************/ 73 | int chain_element_add_function(ChainElement this, chain_element_req_t * elemnt_data) { 74 | int ret = COR_FAILED; 75 | CHAIN_ELEMENT_LOCK(this) 76 | ChainElementPart part=chain_element_part_new(&elemnt_data->element_data); 77 | if(part) { 78 | dputil_list_push((DPUtilList)this, (DPUtilListData)part); 79 | elemnt_data->result_element_part = part; 80 | ret = COR_SUCCESS; 81 | } 82 | CHAIN_ELEMENT_UNLOCK 83 | return ret; 84 | } 85 | 86 | void chain_element_remove_function(ChainElement this, chain_func func) { 87 | CHAIN_ELEMENT_LOCK(this) 88 | ChainElementPart part = this->head; 89 | while(part) { 90 | if(part->data.func == func) { 91 | //free ChainElementPart 92 | ChainElementPart free_part = part; 93 | part=part->next; 94 | dputil_list_pull((DPUtilList)this, (DPUtilListData)free_part); 95 | chain_element_part_free(free_part); 96 | } else { 97 | part=part->next; 98 | } 99 | } 100 | CHAIN_ELEMENT_UNLOCK 101 | } 102 | 103 | void chain_element_remove_element_part(ChainElement this, ChainElementPart element) { 104 | CHAIN_ELEMENT_LOCK(this) 105 | dputil_list_pull((DPUtilList)this, (DPUtilListData)element); 106 | chain_element_part_free(element); 107 | CHAIN_ELEMENT_UNLOCK 108 | } 109 | 110 | void chain_element_call(ChainElement this, void *arg) { 111 | CHAIN_ELEMENT_LOCK(this) 112 | ChainElementPart part = this->head; 113 | while(part) { 114 | if((part->data.func) && (part->data.func(arg, part->data.ctx) == CoR_RETURN)) { 115 | /*exit*/ 116 | break; 117 | } 118 | part=part->next; 119 | } 120 | CHAIN_ELEMENT_UNLOCK 121 | } 122 | 123 | void chain_element_delete(ChainElement this) { 124 | CHAIN_ELEMENT_LOCK(this) 125 | ChainElementPart part; 126 | do { 127 | part = (ChainElementPart) dputil_list_pop((DPUtilList) this); 128 | chain_element_part_free(part); 129 | } while(part); 130 | CHAIN_ELEMENT_UNLOCK 131 | free(this); 132 | } 133 | -------------------------------------------------------------------------------- /chain_of_responsibility/lib/chain_element.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file chain_element.h 3 | * @brief This is API for element of chain 4 | **/ 5 | #ifndef CHAIN_ELEMENT_H_ 6 | #define CHAIN_ELEMENT_H_ 7 | #include "chain_of_responsibility.h" 8 | 9 | /* @{ */ 10 | #define COR_SUCCESS (0) 11 | #define COR_FAILED (-1) 12 | /* @} */ 13 | 14 | /*! @struct chain_element 15 | * @brief ChainElement class instance definition, detail is in chain_element.c 16 | */ 17 | struct chain_element_t;/*! extend DPUtilListData defined in design_pattern_util/include/dp_list.h */ 18 | typedef struct chain_element_t chain_element_t, *ChainElement; 19 | 20 | struct chain_element_data_t { 21 | chain_func func; 22 | void *ctx; 23 | }; 24 | typedef struct chain_element_data_t chain_element_data_t; 25 | 26 | struct chain_element_req_t { 27 | chain_element_data_t element_data; 28 | ChainElementPart result_element_part; 29 | }; 30 | typedef struct chain_element_req_t chain_element_req_t; 31 | 32 | typedef struct chain_element_data_t chain_element_data_t; 33 | ChainElement chain_element_new(int is_threadsafe); 34 | int chain_element_add_function(ChainElement this, chain_element_req_t * elemnt_data); 35 | void chain_element_remove_function(ChainElement this, chain_func func); 36 | void chain_element_remove_element_part(ChainElement this, ChainElementPart element); 37 | void chain_element_call(ChainElement this, void *arg); 38 | void chain_element_delete(ChainElement this); 39 | #endif 40 | -------------------------------------------------------------------------------- /chain_of_responsibility/lib/chain_of_responsibility.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file chain_of_responsibility.c 3 | * @brief Implement of Chain of Responsibility design petten library API 4 | **/ 5 | #include "chain_of_responsibility.h" 6 | #include "flyweight.h" 7 | #include "chain_element.h" 8 | #include "dp_util.h" 9 | 10 | /*! @name ChainOfResponsibility class */ 11 | /* @{ */ 12 | /*! @struct ChainOfResponsibility 13 | * @brief ChainOfResponsibility class instance definition 14 | */ 15 | typedef struct chain_of_resp_t * ChainOfResponsibility; 16 | struct chain_of_resp_t { 17 | int id; 18 | ChainElement element; 19 | }; 20 | 21 | /*! new API */ 22 | static void chain_of_resp_new(void *this, size_t size, void *input_parameter); 23 | /*! @brief equall operand, check name */ 24 | static int chain_of_resp_equall_operand(void *this, size_t size, void *input_parameter); 25 | /*! @brief setter, add function to ChainElement */ 26 | static int chain_of_resp_setter(void *this, size_t size, void *input_parameter); 27 | /*! @brief free member resource */ 28 | static void chain_of_resp_free(void *this); 29 | /* @} */ 30 | 31 | /*! @struct chain_of_resp_mng_t 32 | * @brief management parameter of this class API, to use flyweight 33 | */ 34 | struct chain_of_resp_mng_t { 35 | flyweight_methods_t method; 36 | FlyweightFactory handle; 37 | int is_threadsafe; 38 | } cor_mng_g = { 39 | .method ={ 40 | .constructor=chain_of_resp_new, 41 | .equall_operand=chain_of_resp_equall_operand, 42 | .setter=chain_of_resp_setter, 43 | .destructor=chain_of_resp_free, 44 | }, 45 | .handle = NULL, 46 | .is_threadsafe = 0, 47 | }; 48 | 49 | /************* 50 | * ChainOfResponsibility method definition 51 | *************/ 52 | /*! new API */ 53 | /*input is name*/ 54 | static void chain_of_resp_new(void *this, size_t size, void *input_parameter) { 55 | ChainOfResponsibility instance = (ChainOfResponsibility)this; 56 | int * id = (int *)input_parameter; 57 | instance->id = *id; 58 | instance->element = chain_element_new(cor_mng_g.is_threadsafe); 59 | } 60 | 61 | /*! equall operand, check name */ 62 | static int chain_of_resp_equall_operand(void *this, size_t size, void *input_parameter) { 63 | ChainOfResponsibility instance = (ChainOfResponsibility)this; 64 | int * id = (int *)input_parameter; 65 | 66 | //check name is same 67 | return instance->id == *id; 68 | } 69 | 70 | /*! setter, add function to ChainElement */ 71 | static int chain_of_resp_setter(void *this, size_t size, void *input_parameter) { 72 | ChainOfResponsibility instance = (ChainOfResponsibility)this; 73 | chain_element_req_t * data = input_parameter; 74 | return chain_element_add_function(instance->element, data); 75 | } 76 | 77 | /*! free member resource */ 78 | static void chain_of_resp_free(void *this) { 79 | ChainOfResponsibility instance = (ChainOfResponsibility)this; 80 | chain_element_delete(instance->element); 81 | } 82 | 83 | /************* 84 | * public interface API implement 85 | *************/ 86 | void cor_set_threadsafe(int is_threadsafe) { 87 | cor_mng_g.is_threadsafe = is_threadsafe; 88 | } 89 | 90 | ChainElementPart cor_add_function(const int id, chain_func func, void *ctx) { 91 | if(!func) { 92 | return NULL; 93 | } 94 | 95 | if(!cor_mng_g.handle) { 96 | /* get flyweight handle with thread safe */ 97 | cor_mng_g.handle = flyweight_factory_new(sizeof(struct chain_of_resp_t), cor_mng_g.is_threadsafe, &cor_mng_g.method); 98 | if(!cor_mng_g.handle) { 99 | return NULL; 100 | } 101 | } 102 | 103 | chain_element_req_t data={{func, ctx}, NULL}; 104 | int ret = flyweight_set(cor_mng_g.handle, (void *)&id, &data, NULL); 105 | if( ret == COR_FAILED ) { 106 | return NULL; 107 | } else { 108 | return data.result_element_part; 109 | } 110 | } 111 | 112 | void cor_call(const int id, void *arg) { 113 | if(!cor_mng_g.handle) { 114 | return; 115 | } 116 | ChainOfResponsibility cor_instance = flyweight_get(cor_mng_g.handle, (void *)&id); 117 | if(cor_instance) { 118 | chain_element_call(cor_instance->element, arg); 119 | } 120 | } 121 | 122 | void cor_remove_function(const int id, chain_func func) { 123 | if(!cor_mng_g.handle || !func) { 124 | return; 125 | } 126 | 127 | ChainOfResponsibility cor_instance = flyweight_get(cor_mng_g.handle, (void *)&id); 128 | if(cor_instance) { 129 | chain_element_remove_function(cor_instance->element, func); 130 | } 131 | } 132 | 133 | void cor_remove_chain_element_part(const int id, ChainElementPart element) { 134 | if(!cor_mng_g.handle || !element) { 135 | return; 136 | } 137 | 138 | ChainOfResponsibility cor_instance = flyweight_get(cor_mng_g.handle, (void *)&id); 139 | if(cor_instance) { 140 | chain_element_remove_element_part(cor_instance->element, element); 141 | } 142 | } 143 | 144 | void cor_clear(void) { 145 | flyweight_factory_free(cor_mng_g.handle); 146 | cor_mng_g.handle=NULL; 147 | } 148 | -------------------------------------------------------------------------------- /chain_of_responsibility/lib/chain_of_responsibility.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | cor_set_threadsafe; 4 | cor_add_function; 5 | cor_call; 6 | cor_remove_function; 7 | cor_remove_chain_element_part; 8 | cor_clear; 9 | local: *; 10 | }; 11 | -------------------------------------------------------------------------------- /chain_of_responsibility/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/chain_of_responsibility/CoR_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CXXFLAGS = -g -O0 7 | test_CFLAGS = -g -O0 8 | test_SOURCES = main.c 9 | -------------------------------------------------------------------------------- /chain_of_responsibility/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "chain_of_responsibility.h" 5 | 6 | #define ERRLOG(...) printf("####<%s:%d>", __FUNCTION__, __LINE__);printf(__VA_ARGS__); 7 | 8 | enum { 9 | ID_TEST1, 10 | ID_TEST2, 11 | ID_TEST3, 12 | ID_TEST4, 13 | MAX 14 | }; 15 | 16 | int ctx_g; 17 | 18 | static int all_cnt(int *values) { 19 | int i=0; 20 | int ret = 0; 21 | for(i=0;i 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | static void event_publish(int socketfd, int eventflag, void * event_arg) { 10 | char buf[256]={0}; 11 | if(eventflag|EV_TPOOL_READ) 12 | read(socketfd, buf, sizeof(buf)); 13 | publisher_publish(1, socketfd, buf); 14 | } 15 | 16 | static void add_event_publisher(EventTPoolManager tpool) { 17 | event_subscriber_t stdout_subscriber ={STDOUT_FILENO, EV_TPOOL_READ, event_publish}; 18 | event_tpool_add(tpool, &stdout_subscriber, NULL); 19 | } 20 | 21 | void publisher_notify(int publish_type, void * detail, void *ctx) { 22 | fprintf(stderr, "enter publisher_notify\n"); 23 | char * str = (char *)detail; 24 | char * str_ctx = (char *)ctx; 25 | printf("input:%s(context:%s)\n", str, str_ctx); 26 | } 27 | 28 | int main(int argc, char *argv[]) { 29 | int maxfd=1, ret = 0;; 30 | EventTPoolManager tpool = event_tpool_manager_new(1,0,NULL); 31 | add_event_publisher(tpool); 32 | publisher_new(1); 33 | 34 | publisher_subscribe(1, STDOUT_FILENO, publisher_notify, "for stdout");//for stdout 35 | while(1) { 36 | ret = select(maxfd+1, NULL, NULL, NULL, NULL); 37 | if(ret<0) { 38 | printf("exit\n"); 39 | break; 40 | } 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* "Define path of default plugin" */ 4 | #undef EVENT_IF_PLUGIN_PATH 5 | 6 | /* "Define Threadpool MAX FD SIZE (this value * 64)" */ 7 | #undef EV_TPOLL_MAXFDS 8 | 9 | /* "Define Threadpool MAX FD SIZE (this value * 64)" */ 10 | #undef EV_TPOLL_MAXFDS_SELECT 11 | 12 | /* Define to 1 if you have the `clock_gettime' function. */ 13 | #undef HAVE_CLOCK_GETTIME 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_DLFCN_H 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_EVENT_EVENV2_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_EV_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_INTTYPES_H 26 | 27 | /* Define to 1 if you have the `dl' library (-ldl). */ 28 | #undef HAVE_LIBDL 29 | 30 | /* Define to 1 if you have the `event' library (-levent). */ 31 | #undef HAVE_LIBEVENT 32 | 33 | /* Define to 1 if you have the `pthread' library (-lpthread). */ 34 | #undef HAVE_LIBPTHREAD 35 | 36 | /* Define to 1 if you have the `rt' library (-lrt). */ 37 | #undef HAVE_LIBRT 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #undef HAVE_MEMORY_H 41 | 42 | /* Define to 1 if you have the `memset' function. */ 43 | #undef HAVE_MEMSET 44 | 45 | /* Define to 1 if you have the `select' function. */ 46 | #undef HAVE_SELECT 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #undef HAVE_STDDEF_H 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #undef HAVE_STDINT_H 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #undef HAVE_STDLIB_H 56 | 57 | /* Define to 1 if you have the `strerror' function. */ 58 | #undef HAVE_STRERROR 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #undef HAVE_STRINGS_H 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #undef HAVE_STRING_H 65 | 66 | /* Define to 1 if you have the `strstr' function. */ 67 | #undef HAVE_STRSTR 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_SYS_SOCKET_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_SYS_STAT_H 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_SYS_TYPES_H 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_UNISTD_H 80 | 81 | /* Define to the sub-directory where libtool stores uninstalled libraries. */ 82 | #undef LT_OBJDIR 83 | 84 | /* Name of package */ 85 | #undef PACKAGE 86 | 87 | /* Define to the address where bug reports for this package should be sent. */ 88 | #undef PACKAGE_BUGREPORT 89 | 90 | /* Define to the full name of this package. */ 91 | #undef PACKAGE_NAME 92 | 93 | /* Define to the full name and version of this package. */ 94 | #undef PACKAGE_STRING 95 | 96 | /* Define to the one symbol short name of this package. */ 97 | #undef PACKAGE_TARNAME 98 | 99 | /* Define to the home page for this package. */ 100 | #undef PACKAGE_URL 101 | 102 | /* Define to the version of this package. */ 103 | #undef PACKAGE_VERSION 104 | 105 | /* Define to 1 if you have the ANSI C header files. */ 106 | #undef STDC_HEADERS 107 | 108 | /* when use libev */ 109 | #undef USE_LIBEV 110 | 111 | /* Version number of package */ 112 | #undef VERSION 113 | 114 | /* Define to `__inline__' or `__inline' if that's what the C compiler 115 | calls it, or to nothing if 'inline' is not supported under any name. */ 116 | #ifndef __cplusplus 117 | #undef inline 118 | #endif 119 | 120 | /* Define to `unsigned int' if does not define. */ 121 | #undef size_t 122 | -------------------------------------------------------------------------------- /createVersionScript.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | output_conf_map() { 4 | #{ 5 | # global: 6 | # function_name; 7 | # ... 8 | # local: *; 9 | #} 10 | 11 | #only get function list from header file 12 | HEADER_FUNC_LIST=`grep "[a-zA-Z](" -r $1 | grep -v "@brief" | grep -v "#define" | awk -F"(" '{print $1}' | awk -F " " '{print $NF}'` 13 | #template 14 | echo "{" 15 | echo " global:" 16 | 17 | #show all function 18 | for data in $HEADER_FUNC_LIST 19 | do 20 | echo " $data;" 21 | done 22 | 23 | #template end 24 | echo " local: *;" 25 | echo "};" 26 | } 27 | 28 | INCLUDE_LIST=`find . -name include` 29 | for inc_dir in $INCLUDE_LIST 30 | do 31 | prevdir=`echo $inc_dir | awk -F"/" '{i=NF-1; print $i}'` 32 | outfile=${prevdir}.map 33 | echo $inc_dir 34 | output_conf_map $inc_dir > ./${prevdir}/lib/$outfile 35 | done 36 | 37 | -------------------------------------------------------------------------------- /design_pattern_util/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib include sample 2 | -------------------------------------------------------------------------------- /design_pattern_util/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = dp_define.h dp_debug.h dp_list.h dp_mutex.h dp_util.h 2 | -------------------------------------------------------------------------------- /design_pattern_util/include/dp_debug.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dp_debug.h 3 | * @brief For using debug log 4 | **/ 5 | #ifndef DP_UTIL_DEBUG_H_ 6 | #define DP_UTIL_DEBUG_H_ 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | /************* 16 | * define debug 17 | *************/ 18 | /** 19 | * @brief This is API to store log with timestamp, to measure speed spec. 20 | **/ 21 | struct dp_timelog_t; 22 | typedef struct dp_timelog_t dp_timelog_t, *DPTimeLog; 23 | 24 | /** 25 | * @brief Init store log 26 | * 27 | * @param[in] delimiter delimiter string if you want, default:" " 28 | * @param[in] maxloglen Max length of logs 29 | * @param[in] maxstoresize Storaged log size. If 0, always show log 30 | * @param[in] is_threadsafe threadsafe or not 31 | * @retval !NULL handle pointer to use other method 32 | * @retval NULL error 33 | */ 34 | DPTimeLog dp_timelog_init(const char *delimiter, size_t maxloglen, unsigned long maxstoresize, int is_threadsafe); 35 | 36 | /** 37 | * @brief Store log 38 | * 39 | * @param[in] handle handle returned from timelog_init 40 | * @param[in] format log format as printf 41 | * @retval 0<=val success 42 | * @retval other failed (same as prinf) 43 | */ 44 | int dp_timelog_print(DPTimeLog handle, const char *format, ...); 45 | 46 | /** 47 | * @brief Exit stored log, and show stored log 48 | * 49 | * @param[in] handle handle returned from timelog_init 50 | * @return none 51 | */ 52 | void dp_timelog_exit(DPTimeLog handle); 53 | 54 | /************* 55 | * define debug macro 56 | *************/ 57 | #define DEBUG_PRINT(...) 58 | 59 | #define DBGFLAG/*if you want to disable all debug information, please comment out it*/ 60 | //#define DBGFLAG_ALL/*if you want to enaable all debug(at threadpool)information, please enable itr*/ 61 | 62 | #ifdef DBGFLAG 63 | #include 64 | /*! global timelog handle to show debug log*/ 65 | extern DPTimeLog timelog_g; 66 | /*! If you want to show deail log, please set DPDEBUG_INIT or DPDEBUG_INIT_THREADSAFE at start, and set DPDEBUG_EXIT at end*/ 67 | #define DPDEBUG_INIT timelog_g=dp_timelog_init(",", 2048, 8192, 0); dp_timelog_print(timelog_g,"init\n"); 68 | /*! If you want to show deail log, please set DPDEBUG_INIT or DPDEBUG_INIT_THREADSAFE at start, and set DPDEBUG_EXIT at end*/ 69 | #define DPDEBUG_INIT_THREADSAFE timelog_g=dp_timelog_init(",", 2048, 1, 1); dp_timelog_print(timelog_g,"init\n"); 70 | #include 71 | #define DEBUG_ERRPRINT(...) DEBUG_ERRPRINT_(__VA_ARGS__, "") 72 | #define DEBUG_ERRPRINT_(fmt, ...) \ 73 | dp_timelog_print(timelog_g, "[%s(%s:%d)thread:%x]: "fmt"%s", __FUNCTION__,__FILE__,__LINE__,(unsigned int)pthread_self(), __VA_ARGS__) 74 | /*! If you want to show deail log, please set DPDEBUG_INIT or DPDEBUG_INIT_THREADSAFE at start, and set DPDEBUG_EXIT at end*/ 75 | #define DPDEBUG_EXIT dp_timelog_print(timelog_g,"exit\n");dp_timelog_exit(timelog_g);timelog_g=NULL; 76 | 77 | /*define DEBUG_PRINT*/ 78 | #ifdef DBGFLAG_ALL 79 | #undef DEBUG_PRINT 80 | #define DEBUG_PRINT(...) DEBUG_ERRPRINT_(__VA_ARGS__, "") 81 | #endif 82 | 83 | #else/*DBGFLAG*/ 84 | 85 | #define DPDEBUG_INIT 86 | #define DPDEBUG_INIT_THREDSAFE 87 | #define DEBUG_ERRPRINT(...) 88 | #define DPDEBUG_EXIT 89 | 90 | #endif/*DBGFLAG*/ 91 | 92 | DP_H_END 93 | #endif/*DP_UTIL_DEBUG_H_*/ 94 | -------------------------------------------------------------------------------- /design_pattern_util/include/dp_define.h: -------------------------------------------------------------------------------- 1 | #ifndef DP_H_BEGIN 2 | #ifdef __cplusplus 3 | #define DP_H_BEGIN extern "C" { 4 | #define DP_H_END } 5 | #else /*! __cplusplus */ 6 | #define DP_H_BEGIN 7 | #define DP_H_END 8 | #endif /*! __cplusplus */ 9 | #endif /*!defined(DP_H_BEGIN)*/ 10 | -------------------------------------------------------------------------------- /design_pattern_util/include/dp_list.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dp_list.h 3 | * @brief Utility list API for design pattern 4 | **/ 5 | #ifndef DPUTIL_LIST_H_ 6 | #define DPUTIL_LIST_H_ 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | 10 | /*! @name List Structure */ 11 | /* @{ */ 12 | /** @brief Typedef class DPUtilListData, member is defined in struct dputil_list_data_t*/ 13 | typedef struct dputil_list_data_t *DPUtilListData; 14 | /**! @struct dputil_list_data_t 15 | * @brief This structure will override to use, when you use it, please define own next/prev pointer at the top 16 | */ 17 | struct dputil_list_data_t { 18 | DPUtilListData next; 19 | DPUtilListData prev; 20 | }; 21 | /**! @struct DPUtilList 22 | * @brief This structure will override to use, when you use it, please define own head/tail pointer at the top 23 | */ 24 | typedef struct dputil_list_t *DPUtilList; 25 | struct dputil_list_t { 26 | DPUtilListData head; 27 | DPUtilListData tail; 28 | }; 29 | /* @} */ 30 | 31 | /*! @name List API */ 32 | /* @{ */ 33 | /*! list push */ 34 | void dputil_list_push(DPUtilList this, DPUtilListData data); 35 | /*! list insert to point */ 36 | void dputil_list_insert(DPUtilList this, DPUtilListData prev, DPUtilListData data); 37 | /*! list pull */ 38 | void dputil_list_pull(DPUtilList this, DPUtilListData data); 39 | /*! list pop */ 40 | DPUtilListData dputil_list_pop(DPUtilList this); 41 | /* @} */ 42 | 43 | DP_H_END 44 | #endif 45 | -------------------------------------------------------------------------------- /design_pattern_util/include/dp_mutex.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dp_mutex.h 3 | * @brief Utility mutex API for design pattern 4 | **/ 5 | #ifndef DPUTIL_MUTEX_H_ 6 | #define DPUTIL_MUTEX_H_ 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | /*! @name Lock/Unlock API */ 10 | #include 11 | /* @{ */ 12 | /*! lock */ 13 | void dputil_lock(void *handle); 14 | /*! unlock */ 15 | void dputil_unlock(void *handle); 16 | /*! lock macro, to care pthread_cancel */ 17 | #define DPUTIL_LOCK(lock) \ 18 | dputil_lock(lock);\ 19 | pthread_cleanup_push(dputil_unlock, lock); 20 | /*! unlock macro, to care pthread_cancel */ 21 | #define DPUTIL_UNLOCK pthread_cleanup_pop(1); 22 | /* @} */ 23 | DP_H_END 24 | #endif 25 | -------------------------------------------------------------------------------- /design_pattern_util/include/dp_util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dp_util.h 3 | * @brief Utility headers 4 | **/ 5 | #ifndef DPUTIL_H_ 6 | #define DPUTIL_H_ 7 | 8 | #include "dp_list.h" 9 | #include "dp_mutex.h" 10 | #include "dp_debug.h" 11 | #endif 12 | -------------------------------------------------------------------------------- /design_pattern_util/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | AM_CPPFLAGS=-I$(top_srcdir)/design_pattern_util/include/ -I$(top_srcdir)/design_pattern_util/include/ 3 | INCLUDES_PATH=$(top_srcdir)/design_pattern_util/include/ $(top_srcdir)/design_pattern_util/include/ 4 | 5 | lib_LTLIBRARIES = libdputil.la 6 | # 7 | libdputil_la_SOURCES = dp_util.c dp_timelog.c 8 | libdputil_la_LDFLAGS=-shared 9 | -------------------------------------------------------------------------------- /design_pattern_util/lib/dp_timelog.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Implement of dp_timelog API, defined in dp_debug.h 3 | **/ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "dp_debug.h" 12 | #include "dp_mutex.h" 13 | 14 | DPTimeLog timelog_g; 15 | 16 | /************* 17 | * public define 18 | *************/ 19 | /*! @name Error definition */ 20 | /* @{ */ 21 | #define DPTLOG_FAILED (-1) /*! error */ 22 | #define DPTLOG_SUCCESS (0) /*! success */ 23 | /* @} */ 24 | 25 | /*! @brief default delimiter definition */ 26 | #define DPTLOG_DELIMITER_DEFAULT (char *)" " 27 | 28 | /*! @struct dp_timelog_data_t 29 | * @brief log data with timestamp, defined like class 30 | */ 31 | typedef struct dp_timelog_data_t{ 32 | //private member 33 | struct timespec time;/*! timestamp */ 34 | char * buf;/*! tmp buffer for using store log */ 35 | } dp_timelog_data_t; 36 | 37 | /*! @name log class API for dp_timelog_data_t */ 38 | /* @{ */ 39 | static inline void dp_timelog_data_store(DPTimeLog mng); 40 | /* @} */ 41 | 42 | /*! @struct dp_timelog_t 43 | * @brief storaged log data management structure 44 | */ 45 | struct dp_timelog_t{ 46 | //private member 47 | const char *delimiter; /*! delimiter */ 48 | pthread_mutex_t *lock; 49 | 50 | unsigned long current_num; /*! numnber of current stored log */ 51 | unsigned long maxstoresize; /*! max size of log_list */ 52 | dp_timelog_data_t * log_list; /*! log list */ 53 | size_t maxloglen; 54 | char * tmpbuf;/*! tmp buffer for using store log */ 55 | }; 56 | 57 | #define DPTLOG_LOCK(mng) DPUTIL_LOCK(mng->lock) 58 | #define DPTLOG_UNLOCK DPUTIL_UNLOCK; 59 | 60 | static void dp_timelog_show(DPTimeLog mng); 61 | 62 | /************* 63 | * implement 64 | *************/ 65 | /**for dp_timelog_data_t**/ 66 | static inline void dp_timelog_data_store(DPTimeLog mng) { 67 | //set time 68 | dp_timelog_data_t * data = &mng->log_list[mng->current_num++]; 69 | clock_gettime(CLOCK_REALTIME, &data->time); 70 | memcpy(data->buf, mng->tmpbuf, mng->maxloglen); 71 | } 72 | 73 | /*interface*/ 74 | static void dp_timelog_show(DPTimeLog mng) { 75 | unsigned long i=0; 76 | for(i = 0; i < mng->current_num; i ++) { 77 | //show 1 data 78 | fprintf(stderr, "%u.%09lu%s%s", (unsigned int)mng->log_list[i].time.tv_sec, mng->log_list[i].time.tv_nsec, mng->delimiter, mng->log_list[i].buf); 79 | } 80 | } 81 | 82 | /************* 83 | * public interface API implement 84 | *************/ 85 | DPTimeLog dp_timelog_init(const char *delimiter, size_t maxloglen, unsigned long maxstoresize, int is_threadsafe) { 86 | DPTimeLog mng=NULL; 87 | size_t size = sizeof(*mng); 88 | void * current_p=NULL; 89 | /*add buffer data size*/ 90 | 91 | /*add dp_timelog_data_t size*/ 92 | size += sizeof(dp_timelog_data_t) * maxstoresize; 93 | 94 | /*add buffer size + tmp buffer size*/ 95 | size += (maxloglen + 1) * (maxstoresize + 1); 96 | 97 | mng=malloc(size); 98 | if(!mng) { 99 | DEBUG_ERRPRINT("calloc mng error:%s\n", strerror(errno)); 100 | return NULL; 101 | } 102 | memset(mng, 0, size); 103 | 104 | current_p = (mng+1); 105 | 106 | /*set delimiter*/ 107 | if(delimiter) { 108 | mng->delimiter = delimiter; 109 | } else { 110 | mng->delimiter = DPTLOG_DELIMITER_DEFAULT; 111 | } 112 | 113 | /*set lock*/ 114 | if(is_threadsafe) { 115 | mng->lock = malloc(sizeof(pthread_mutex_t)); 116 | pthread_mutex_init(mng->lock, NULL); 117 | } 118 | 119 | mng->maxstoresize = maxstoresize; 120 | 121 | /*set loglist*/ 122 | unsigned long i; 123 | mng->log_list = (dp_timelog_data_t *)current_p; 124 | current_p = mng->log_list + maxstoresize; 125 | 126 | /*set buffer in log_list*/ 127 | for( i = 0; i < maxstoresize; i++ ) { 128 | mng->log_list[i].buf = current_p; 129 | current_p = mng->log_list[i].buf + maxloglen; 130 | } 131 | 132 | /*set tmp buffer*/ 133 | mng->maxloglen = maxloglen; 134 | mng->tmpbuf = current_p; 135 | 136 | return mng; 137 | } 138 | 139 | int dp_timelog_print(DPTimeLog mng, const char *format, ...) { 140 | //fail safe 141 | if(!mng || !format) { 142 | return DPTLOG_FAILED; 143 | } 144 | 145 | DPTLOG_LOCK(mng) 146 | memset(mng->tmpbuf, 0, mng->maxloglen); 147 | va_list arg; 148 | va_start(arg, format); 149 | vsnprintf(mng->tmpbuf, mng->maxloglen, format, arg); 150 | va_end(arg); 151 | dp_timelog_data_store(mng); 152 | 153 | if(mng->maxstoresize <= mng->current_num) { 154 | dp_timelog_show(mng); 155 | mng->current_num=0; 156 | } 157 | DPTLOG_UNLOCK 158 | 159 | return DPTLOG_SUCCESS; 160 | } 161 | 162 | void dp_timelog_exit(DPTimeLog mng) { 163 | //fail safe 164 | if(!mng) { 165 | return ; 166 | } 167 | 168 | pthread_mutex_t *lock=NULL; 169 | DPTLOG_LOCK(mng) 170 | //show log 171 | dp_timelog_show(mng); 172 | lock=mng->lock; 173 | free(mng); 174 | DPTLOG_UNLOCK 175 | free(lock); 176 | } 177 | 178 | -------------------------------------------------------------------------------- /design_pattern_util/lib/dp_util.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dp_util.c 3 | * @brief design pattern libraries utility API 4 | **/ 5 | #include "dp_util.h" 6 | /*! lock */ 7 | void dputil_lock(void *handle) { 8 | if(!handle) { 9 | return; 10 | } 11 | pthread_mutex_lock((pthread_mutex_t *)handle); 12 | } 13 | /*! unlock */ 14 | void dputil_unlock(void *handle) { 15 | if(!handle) { 16 | return; 17 | } 18 | pthread_mutex_unlock((pthread_mutex_t *)handle); 19 | } 20 | 21 | void dputil_list_push(DPUtilList this, DPUtilListData data) { 22 | /* add to tail */ 23 | data->prev = this->tail; 24 | //slide tail 25 | if(this->tail) { 26 | this->tail->next = data; 27 | } 28 | this->tail = data; 29 | 30 | /* if head is null, set to head */ 31 | if(!this->head) { 32 | this->head = data; 33 | } 34 | } 35 | 36 | void dputil_list_insert(DPUtilList this, DPUtilListData prev, DPUtilListData data) { 37 | 38 | /*add to tail*/ 39 | if(!prev) { 40 | dputil_list_push(this, data); 41 | return; 42 | } 43 | 44 | //there is a prev. 45 | data->next = prev->next; 46 | data->prev = prev; 47 | 48 | //only to care prev has next or not 49 | if(prev->next) { 50 | prev->next->prev = data; 51 | } else { 52 | //there is no next=> prev is tail 53 | this->tail = data; 54 | } 55 | 56 | prev->next = data; 57 | } 58 | 59 | void dputil_list_pull(DPUtilList this, DPUtilListData data) { 60 | if(!data) { 61 | return; 62 | } 63 | 64 | /* update content */ 65 | if(this->head == data) { 66 | this->head = data->next; 67 | } else { 68 | /* else case, account is not head. So there is a prev. */ 69 | data->prev->next = data->next; 70 | } 71 | 72 | if(this->tail == data) { 73 | this->tail = data->prev; 74 | } else { 75 | /* else case, account is not tail. So there is a next. */ 76 | data->next->prev = data->prev; 77 | } 78 | } 79 | 80 | DPUtilListData dputil_list_pop(DPUtilList this) { 81 | DPUtilListData data = this->head; 82 | dputil_list_pull(this, data); 83 | return data; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /design_pattern_util/sample/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CFLAGS = -g -O0 7 | test_SOURCES = main.c 8 | test_LDFLAGS = $(AM_LDFLAGS) $(top_srcdir)/design_pattern_util/lib/libdputil.la 9 | -------------------------------------------------------------------------------- /design_pattern_util/sample/log.txt: -------------------------------------------------------------------------------- 1 | 1530135733.448325907,init 2 | 1530135733.448329512,[event_thread_msg_send_add(event_thread.c:188)thread:92390740]: add, subscriber->143! 3 | 1530135733.448333091,[event_thread_msg_send(event_thread.c:161)thread:92390740]: (thread:92390740)wait signal from event thread , 0x559a23401158 4 | 1530135733.457713924,[event_subscriber_data_new(event_thread.c:235)thread:9066e700]: add subscriber->143! 5 | 1530135733.457720419,[event_if_add(event_if_select.c:103)thread:9066e700]: event_add [143] 6 | 1530135733.457721107,[event_if_add(event_if_select.c:121)thread:9066e700]: maxfd [143] 7 | 1530135733.457723057,[event_tpool_thread_call_msgs(event_thread.c:408)thread:9066e700]: cond signal from event thread to 0x559a23401158 8 | 1530135733.457730005,[event_tpool_thread_call_msgs(event_thread.c:410)thread:9066e700]: cond signal from event thread to 0x559a23401158 end 9 | 1530135733.457732965,[event_thread_msg_send(event_thread.c:166)thread:92390740]: (thread:92390740)wait signal from event thread 0x559a23401158 end, ret=0 10 | 1530135733.457733572,exit 11 | 1530135968.593211181,init 12 | 1530135968.593215298,[event_thread_msg_send_add(event_thread.c:188)thread:92390740]: add, subscriber->143! 13 | 1530135968.593218071,[event_thread_msg_send(event_thread.c:161)thread:92390740]: (thread:92390740)wait signal from event thread , 0x559a23401158 14 | 1530135968.593222458,[event_subscriber_data_new(event_thread.c:235)thread:9066e700]: add subscriber->143! 15 | 1530135968.593224110,[event_if_add(event_if_select.c:103)thread:9066e700]: event_add [143] 16 | 1530135968.593227687,[event_if_add(event_if_select.c:121)thread:9066e700]: maxfd [143] 17 | 1530135968.593228376,[event_tpool_thread_call_msgs(event_thread.c:408)thread:9066e700]: cond signal from event thread to 0x559a23401158 18 | 1530135968.593238260,[event_tpool_thread_call_msgs(event_thread.c:410)thread:9066e700]: cond signal from event thread to 0x559a23401158 end 19 | 1530135968.593277283,[event_thread_msg_send(event_thread.c:166)thread:92390740]: (thread:92390740)wait signal from event thread 0x559a23401158 end, ret=0 20 | 1530135968.593279778,exit 21 | 1530135970.006231403,init 22 | 1530135970.006234898,[event_thread_msg_send_add(event_thread.c:188)thread:92390740]: add, subscriber->143! 23 | 1530135970.006239538,[event_thread_msg_send(event_thread.c:161)thread:92390740]: (thread:92390740)wait signal from event thread , 0x559a23401158 24 | 1530135970.009657953,[event_subscriber_data_new(event_thread.c:235)thread:9066e700]: add subscriber->143! 25 | 1530135970.009659491,[event_if_add(event_if_select.c:103)thread:9066e700]: event_add [143] 26 | 1530135970.009660403,[event_if_add(event_if_select.c:121)thread:9066e700]: maxfd [143] 27 | 1530135970.009661113,[event_tpool_thread_call_msgs(event_thread.c:408)thread:9066e700]: cond signal from event thread to 0x559a23401158 28 | 1530135970.009668914,[event_tpool_thread_call_msgs(event_thread.c:410)thread:9066e700]: cond signal from event thread to 0x559a23401158 end 29 | 1530135970.009698413,[event_thread_msg_send(event_thread.c:166)thread:92390740]: (thread:92390740)wait signal from event thread 0x559a23401158 end, ret=0 30 | 1530135970.009699453,exit 31 | 1530135970.906835728,init 32 | 1530135970.906838687,[event_thread_msg_send_add(event_thread.c:188)thread:92390740]: add, subscriber->143! 33 | 1530135970.906842613,[event_thread_msg_send(event_thread.c:161)thread:92390740]: (thread:92390740)wait signal from event thread , 0x559a23401158 34 | 1530135970.917648918,[event_subscriber_data_new(event_thread.c:235)thread:9066e700]: add subscriber->143! 35 | 1530135970.917650703,[event_if_add(event_if_select.c:103)thread:9066e700]: event_add [143] 36 | 1530135970.917651362,[event_if_add(event_if_select.c:121)thread:9066e700]: maxfd [143] 37 | 1530135970.917652052,[event_tpool_thread_call_msgs(event_thread.c:408)thread:9066e700]: cond signal from event thread to 0x559a23401158 38 | 1530135970.917659261,[event_tpool_thread_call_msgs(event_thread.c:410)thread:9066e700]: cond signal from event thread to 0x559a23401158 end 39 | 1530135970.917688367,[event_thread_msg_send(event_thread.c:166)thread:92390740]: (thread:92390740)wait signal from event thread 0x559a23401158 end, ret=0 40 | 1530135970.917689349,exit 41 | -------------------------------------------------------------------------------- /design_pattern_util/sample/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include "dp_debug.h" 9 | 10 | static pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; 11 | static int mutex_data=0; 12 | 13 | static int sockpair[2]; 14 | static int write_data=0; 15 | 16 | static int normal_data=0; 17 | static DPTimeLog handle; 18 | 19 | static void * mutex_thread(void *arg) { 20 | int *num = (int *) arg; 21 | int i=0; 22 | dp_timelog_print(handle, "start, value=%d\n", mutex_data); 23 | for(i=0; i< *num; i++) { 24 | pthread_mutex_lock(&mutex); 25 | mutex_data++; 26 | pthread_mutex_unlock(&mutex); 27 | } 28 | dp_timelog_print(handle, "end, value=%d\n", mutex_data); 29 | pthread_exit(NULL); 30 | return NULL; 31 | } 32 | static void * nomutex_thread(void *arg) { 33 | int *num = (int *) arg; 34 | int i=0; 35 | dp_timelog_print(handle, "start, value=%d\n", normal_data); 36 | for(i=0; i< *num; i++) { 37 | normal_data++; 38 | } 39 | dp_timelog_print(handle, "end, value=%d\n", normal_data); 40 | pthread_exit(NULL); 41 | return NULL; 42 | } 43 | 44 | static void * read_thread(void *arg) { 45 | int *num = (int *) arg; 46 | int i=0; 47 | pthread_t tid=0; 48 | dp_timelog_print(handle, "start, value=%d\n", write_data); 49 | for(i=0; i< *num; i++) { 50 | read(sockpair[1], &tid, sizeof(tid)); 51 | write_data++; 52 | } 53 | dp_timelog_print(handle, "end, value=%d\n", write_data); 54 | pthread_exit(NULL); 55 | return NULL; 56 | } 57 | 58 | static void initialize() { 59 | socketpair(AF_UNIX, SOCK_DGRAM, 0, sockpair); 60 | } 61 | 62 | static void read_testdata_mutex(int * fsize) { 63 | pthread_t tid=0; 64 | pthread_create(&tid, NULL, mutex_thread, fsize); 65 | pthread_join(tid, NULL); 66 | } 67 | 68 | static void read_testdata_socket(int * fsize) { 69 | pthread_t tid=0; 70 | pthread_create(&tid, NULL, read_thread, fsize); 71 | int i=0; 72 | for(i=0; i< *fsize; i++) { 73 | write(sockpair[0], &tid, sizeof(tid)); 74 | } 75 | pthread_join(tid, NULL); 76 | } 77 | 78 | static void read_testdata_normal(int * fsize) { 79 | pthread_t tid=0; 80 | pthread_create(&tid, NULL, nomutex_thread, fsize); 81 | pthread_join(tid, NULL); 82 | dp_timelog_print(handle, "end, value=%d\n", normal_data); 83 | } 84 | 85 | int main(int argc, char *argv[]) { 86 | if(argc < 2) return 0; 87 | int fsize=atoi(argv[1]); 88 | 89 | /*write id, len*/ 90 | initialize(); 91 | 92 | handle = dp_timelog_init(",", 100, 1000, 0); 93 | if(!handle) return 0; 94 | 95 | dp_timelog_print(handle, "Mutex\n"); 96 | read_testdata_mutex(&fsize); 97 | dp_timelog_print(handle, "Socket\n"); 98 | read_testdata_socket(&fsize); 99 | dp_timelog_print(handle, "No lock\n"); 100 | read_testdata_normal(&fsize); 101 | 102 | //exit 103 | dp_timelog_exit(handle); 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /design_pattern_util/sample/speedcheck.rb: -------------------------------------------------------------------------------- 1 | #!//usr/bin/ruby 2 | require 'bigdecimal' 3 | require 'bigdecimal/util' 4 | require 'json' 5 | 6 | oldresult=0.0 7 | newresult=0.0 8 | 9 | puts("|Time|Log|") 10 | puts("|:---|:---|") 11 | log="" 12 | File.open("log.txt", "r") {|f| 13 | log=f.read() 14 | } 15 | log.each_line{|line| 16 | time_and_word=line.chomp.split(",") 17 | newresult = time_and_word[0].to_f 18 | if newresult != 0 then 19 | diff = newresult - oldresult 20 | puts("|#{diff}|#{time_and_word[1,time_and_word.length() - 1].to_s}|") 21 | oldresult = newresult 22 | else 23 | puts("|||") 24 | end 25 | } 26 | -------------------------------------------------------------------------------- /flyweight/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib include test 2 | -------------------------------------------------------------------------------- /flyweight/README.md: -------------------------------------------------------------------------------- 1 | # flyweight 2 | The library for Linux C language to use flyweight pattern. 3 | 4 | # How to use 5 | After build all, please link libflyweight.so library. 6 | API header is in flyweight.h 7 | 8 | Please see wiki "https://github.com/developer-kikikaikai/design_pattern_for_c/wiki/Flyweight" for more detai. 9 | -------------------------------------------------------------------------------- /flyweight/flyweight_am.conf: -------------------------------------------------------------------------------- 1 | #common header deifinition 2 | include $(top_srcdir)/am.conf 3 | 4 | AM_CPPFLAGS+=-I$(FLYWEIGHT_DIR)/include 5 | INCLUDES_PATH+=$(FLYWEIGHT_DIR)/include 6 | 7 | AM_LDFLAGS+=$(FLYWEIGHT_DIR)/lib/libflyweight.la 8 | -------------------------------------------------------------------------------- /flyweight/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = flyweight.h 2 | -------------------------------------------------------------------------------- /flyweight/include/flyweight.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file flyweight.h 3 | * @brief This is API as Flyweight design petten 4 | **/ 5 | #ifndef FLYWEIGHT_H_ 6 | #define FLYWEIGHT_H_ 7 | 8 | #include 9 | #include "dp_define.h" 10 | DP_H_BEGIN 11 | 12 | /*! @struct flyweight_methods_t 13 | * @brief Flyweight methods interface definition, to set flyweight_factory_new. This interface is used for generating instance into FlyweightFactory. 14 | */ 15 | struct flyweight_methods_t { 16 | /** 17 | * @brief constructor of class 18 | * @param[in] this class instance 19 | * @param[in] size size of this instance 20 | * @param[in] input_parameter input parameter related to flyweight_get 21 | * @note default: memcpy size 22 | */ 23 | void (*constructor)(void *this, size_t size, void *input_parameter); 24 | /** 25 | * @brief operand == 26 | * @param[in] this class instance 27 | * @param[in] size size of this instance 28 | * @param[in] input_parameter input parameter related to flyweight_get 29 | * @return defined value 30 | * @note if you set function which return always 1, this class is same as Singleton. 31 | * @note if you set function which return always 0, this class always allocate new instance 32 | * @note default: memcmp size 33 | */ 34 | int (*equall_operand)(void *this, size_t size, void *input_parameter); 35 | /** 36 | * @brief setter 37 | * @param[in] this class instance 38 | * @param[in] size size of this instance 39 | * @param[in] input_parameter 40 | * @note default: memcpy size 41 | */ 42 | int (*setter)(void *this, size_t size, void *input_parameter); 43 | /** 44 | * @brief destructor 45 | * @param[in] this class instance 46 | * @note allocated memory will free into library, please free members in class 47 | * @note default: none 48 | */ 49 | void (*destructor)(void *this); 50 | }; 51 | 52 | /** @brief FlyweightMethodsInterface class definition, member is defined in flyweight_methods_t, */ 53 | typedef struct flyweight_methods_t flyweight_methods_t, * FlyweightMethodsIF; 54 | 55 | /*! @struct flyweight_factory_t 56 | * @brief FlyweightFactory member definition, defined in flyweight.c 57 | */ 58 | struct flyweight_factory_t; 59 | 60 | /** @brief FlyweightFactory definition*/ 61 | typedef struct flyweight_factory_t * FlyweightFactory; 62 | 63 | /** 64 | * @brief define class for flyweight 65 | * @param[in] class_size size of instance which defined in user side. 66 | * @param[in] is_threadsafe if !=0, ensure threadsafe to create new class instace, please set !=0 if you want to use this API on multi thread 67 | * @param[in] methods for generating class instance 68 | * If NULL, use defautlt. If not NULL, override methods. override NULL, this method is no effect. 69 | * destructor is called at free 70 | * @retval !=NULL this class handle 71 | * @retval NULL error 72 | */ 73 | FlyweightFactory flyweight_factory_new(size_t class_size, int is_threadsafe, FlyweightMethodsIF methods); 74 | 75 | /** 76 | * @brief getter 77 | * @param[in] this FlyweightFactory instance returned at flyweight_factory_new, first time to call get, allocate class, memset 0 and call constructor 78 | * @param[in] constructor_parameter constructor parameter 79 | * @retval !NULL class instance 80 | * @retval NULL id is invalid 81 | */ 82 | void * flyweight_get(FlyweightFactory this, void * constructor_parameter); 83 | 84 | /** 85 | * @brief setter 86 | * @param[in] this FlyweightFactory instance returned at flyweight_factory_new, 87 | * @param[in] constructor_parameter constructor parameter 88 | * @param[in] data set data pointer 89 | * @param[in] setter setter if you want to change setter ( if NULL, use setter related to flyweight_register_class input) 90 | */ 91 | int flyweight_set(FlyweightFactory this, void * constructor_parameter, void * data, int (*setter)(void *this, size_t size, void *input_parameter)); 92 | 93 | /** 94 | * @brief clear class handle 95 | * @param [in] this FlyweightFactory instance returned at flyweight_factory_new, 96 | * @return none 97 | */ 98 | void flyweight_factory_free(FlyweightFactory this); 99 | 100 | DP_H_END 101 | #endif/*FLYWEIGHT_*/ 102 | -------------------------------------------------------------------------------- /flyweight/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/flyweight/flyweight_am.conf 3 | 4 | lib_LTLIBRARIES = libflyweight.la 5 | 6 | libflyweight_la_SOURCES = flyweight.c 7 | #for statik library 8 | libflyweight_la_LDFLAGS=-shared $(DPUTIL_DIR)/lib/libdputil.la 9 | libflyweight_la_LDFLAGS+=-Wl,--version-script,flyweight.map 10 | -------------------------------------------------------------------------------- /flyweight/lib/flyweight.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | flyweight_factory_new; 4 | flyweight_get; 5 | flyweight_set; 6 | flyweight_factory_free; 7 | local: *; 8 | }; 9 | -------------------------------------------------------------------------------- /flyweight/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/flyweight/flyweight_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CXXFLAGS = -g -O0 7 | test_CFLAGS = -g -O0 8 | test_SOURCES = test_normalclass.c test_methodsclass.c main.c 9 | -------------------------------------------------------------------------------- /flyweight/test/main.c: -------------------------------------------------------------------------------- 1 | #include "flyweight.h" 2 | #include "test.h" 3 | int main(int argc, char *argv[]) { 4 | int totalcnt=0; 5 | int cnt=0; 6 | cnt = test_normalclass(0); 7 | if(cnt == 0) { 8 | ERRLOG("test normal class unthreadsafe error\n") 9 | } 10 | totalcnt+=cnt; 11 | 12 | cnt = test_methodsclass(0); 13 | if(cnt == 0) { 14 | ERRLOG("test method class unthreadsafe error\n") 15 | } 16 | totalcnt+=cnt; 17 | 18 | cnt = test_normalclass(1); 19 | if(cnt == 0) { 20 | ERRLOG("test normal class threadsafe error\n") 21 | } 22 | totalcnt+=cnt; 23 | 24 | cnt = test_methodsclass(1); 25 | if(cnt == 0) { 26 | ERRLOG("test normal class threadsafe error\n") 27 | } 28 | totalcnt+=cnt; 29 | printf("Finish all test %d\n", totalcnt); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /flyweight/test/test.h: -------------------------------------------------------------------------------- 1 | #include 2 | int test_normalclass(int);//test normal class 3 | int test_methodsclass(int);//test class, set methods 4 | 5 | #define ERRLOG(...) printf("####<%s:%s:%d> error", __FILE__, __FUNCTION__, __LINE__);\ 6 | printf(__VA_ARGS__);printf("\n");\ 7 | return 0; 8 | -------------------------------------------------------------------------------- /flyweight/test/test_methodsclass.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "flyweight.h" 4 | #include "test.h" 5 | 6 | #define NAMELEN 64 7 | 8 | //get name by id 9 | #define MEMBER \ 10 | int id;\ 11 | char *name; 12 | 13 | struct testclass1 { 14 | char * (*getname)(struct testclass1 *data); 15 | MEMBER 16 | }; 17 | 18 | struct testclass1_input { 19 | MEMBER 20 | }; 21 | 22 | #define COPY_MEMBER(src, dst) \ 23 | (dst)->id=(src)->id;\ 24 | sprintf((dst)->name, (src)->name); 25 | 26 | //to check keep function 27 | static char * getname_inplement(struct testclass1 *data) { 28 | return data->name; 29 | } 30 | 31 | //create 2 Flyweight class, to check member and to check ID. 32 | static void constructor_member(void *this, size_t size, void *input_parameter) { 33 | struct testclass1 * class_instance = (struct testclass1 *)this; 34 | struct testclass1_input *input = (struct testclass1_input*)input_parameter; 35 | //only copy member 36 | class_instance->name = malloc(NAMELEN); 37 | 38 | class_instance->id = input->id; 39 | sprintf(class_instance->name, "%s", input->name); 40 | class_instance->getname=getname_inplement; 41 | } 42 | 43 | static void destructor_member(void *this) { 44 | struct testclass1 * class_instance = (struct testclass1 *)this; 45 | free(class_instance->name); 46 | } 47 | 48 | //for only id Flyweight class 49 | static int equall_operand_onlyid(void *this, size_t size, void *input_parameter) { 50 | struct testclass1 * class_instance = (struct testclass1 *)this; 51 | struct testclass1_input *input = (struct testclass1_input*)input_parameter; 52 | return (class_instance->id == input->id); 53 | } 54 | 55 | static int set_for_operand_onlyid(void *this, size_t size, void *input_parameter) { 56 | struct testclass1 * class_instance = (struct testclass1 *)this; 57 | struct testclass1_input *input = (struct testclass1_input*)input_parameter; 58 | char * name = (char *)input_parameter; 59 | sprintf(class_instance->name, "%s", name); 60 | return 1; 61 | } 62 | 63 | static flyweight_methods_t onlyid_method={ 64 | .constructor=constructor_member, 65 | .equall_operand=equall_operand_onlyid, 66 | .setter=set_for_operand_onlyid, 67 | .destructor=destructor_member, 68 | }; 69 | 70 | //for only operand member 71 | static int equall_operand_member(void *this, size_t size, void *input_parameter) { 72 | struct testclass1 * class_instance = (struct testclass1 *)this; 73 | struct testclass1_input *input = (struct testclass1_input*)input_parameter; 74 | return (class_instance->id == input->id) && (strcmp(class_instance->name, input->name)==0); 75 | } 76 | 77 | static flyweight_methods_t member_method={ 78 | .constructor=constructor_member, 79 | .equall_operand=equall_operand_member, 80 | .setter=NULL, 81 | .destructor=destructor_member, 82 | }; 83 | 84 | //override API for member_method 85 | static char * getname_implement_withset(struct testclass1 *data) { 86 | static char name[20]; 87 | sprintf(name, "Mr. %s", data->name); 88 | return name; 89 | } 90 | static int setter_override(void *this, size_t size, void *input_parameter) { 91 | struct testclass1 * class_instance = (struct testclass1 *)this; 92 | class_instance->getname = getname_implement_withset; 93 | return 0; 94 | } 95 | 96 | #define TESTDATA_LEN 5 97 | int test_methodsclass(int is_threadsafe) { 98 | int testcnt=0; 99 | struct testclass1_input setting[TESTDATA_LEN] = { 100 | {0,"ootani"}, 101 | {1,"ootani"}, 102 | {2,"sakai"}, 103 | {1,"ootani"}, 104 | {2,"kato"}, 105 | }; 106 | 107 | //test1, check operator is check member 108 | { 109 | FlyweightFactory handle = flyweight_factory_new(sizeof(struct testclass1), is_threadsafe, &member_method); 110 | if(!handle) { 111 | ERRLOG("failed to create handle"); 112 | } 113 | 114 | void *instances[TESTDATA_LEN]; 115 | int i=0; 116 | for(i=0;igetname != getname_inplement) { 122 | ERRLOG("Not initialize interface method") 123 | } 124 | struct testclass1 * instance = (struct testclass1 *)instances[i]; 125 | printf("%d name:%s\n", i, instance->getname(instance)); 126 | } 127 | 128 | //check instance, only same id => different, only same name => different, same all => OK 129 | if(instances[0] == instances[1] || instances[1] == instances[2] ||instances[1] != instances[3]) { 130 | ERRLOG("Instance usage failed") 131 | } 132 | flyweight_factory_free(handle); 133 | testcnt++; 134 | } 135 | 136 | //test2, check operator is check only ID 137 | { 138 | FlyweightFactory handle = flyweight_factory_new(sizeof(struct testclass1), is_threadsafe, &onlyid_method); 139 | if(!handle) { 140 | ERRLOG("failed to create handle"); 141 | } 142 | 143 | void *instances[TESTDATA_LEN]; 144 | int i=0; 145 | for(i=0;igetname != getname_inplement) { 151 | ERRLOG("Not initialize interface method") 152 | } 153 | struct testclass1 * instance = (struct testclass1 *)instances[i]; 154 | printf("%d name:%s\n", i, instance->getname(instance)); 155 | } 156 | 157 | //check instance, only same id => OK 158 | if(instances[0] == instances[1] || instances[1] != instances[3] ||instances[2] != instances[4]) { 159 | ERRLOG("Instance usage failed") 160 | } 161 | 162 | //setter use 163 | flyweight_set(handle, &setting[0], "update name", NULL); 164 | void *instance=flyweight_get(handle, &setting[0]); 165 | if(instance != instances[0]) { 166 | ERRLOG("Instance usage failed") 167 | } 168 | 169 | struct testclass1 * testclass1_instance = (struct testclass1 *)instance; 170 | printf("Update, %s\n", testclass1_instance->name); 171 | if(strcmp(testclass1_instance->name, "update name") != 0) { 172 | ERRLOG("Failed to set") 173 | } 174 | 175 | //setter set 176 | flyweight_set(handle, &setting[0], "update name", setter_override); 177 | instance=flyweight_get(handle, &setting[0]); 178 | if(instance != instances[0]) { 179 | ERRLOG("Instance usage failed") 180 | } 181 | 182 | testclass1_instance = (struct testclass1 *)instance; 183 | char *updatename = testclass1_instance->getname(testclass1_instance); 184 | printf("Update, %s\n", updatename); 185 | if(strcmp(updatename, "update name") == 0) { 186 | ERRLOG("Failed to set") 187 | } 188 | if(strcmp(updatename, "Mr. update name") != 0) { 189 | ERRLOG("Failed to set") 190 | } 191 | flyweight_factory_free(handle); 192 | testcnt++; 193 | } 194 | 195 | return testcnt; 196 | } 197 | -------------------------------------------------------------------------------- /flyweight/test/test_normalclass.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "flyweight.h" 4 | #include "test.h" 5 | 6 | struct testclass1 { 7 | int data; 8 | }; 9 | 10 | int test_normalclass(int is_threadsafe) { 11 | int testcnt=0; 12 | struct testclass1 data1={.data=0}; 13 | struct testclass1 data2_different1={.data=1}; 14 | 15 | //test1, create handle 16 | FlyweightFactory handle = flyweight_factory_new(sizeof(struct testclass1), is_threadsafe, NULL); 17 | if(!handle) { 18 | ERRLOG("failed to create handle"); 19 | } 20 | testcnt++; 21 | 22 | //test2, get instance 23 | { 24 | void * data1_instance = flyweight_get(handle, &data1); 25 | if(!data1_instance || (memcmp(&data1, data1_instance, sizeof(struct testclass1)) != 0) ) { 26 | ERRLOG("failed to create instance"); 27 | } 28 | void * data1_instance_twice = flyweight_get(handle, &data1); 29 | if(data1_instance != data1_instance_twice) { 30 | ERRLOG("failed to reuse same data"); 31 | } 32 | testcnt++; 33 | } 34 | 35 | { 36 | void * data2_instance = flyweight_get(handle, &data2_different1); 37 | if(!data2_instance || (memcmp(&data2_different1, data2_instance, sizeof(struct testclass1)) != 0 )) { 38 | ERRLOG("failed to create instance"); 39 | } 40 | void * data1_instance = flyweight_get(handle, &data1); 41 | if(data1_instance == data2_instance) { 42 | ERRLOG("failed to separate data"); 43 | } 44 | testcnt++; 45 | } 46 | 47 | { 48 | //set API 49 | struct testclass1 data1_cpy=data1; 50 | void * data1_instance = flyweight_get(handle, &data1); 51 | if(!data1_instance) { 52 | ERRLOG("failed to get instance"); 53 | } 54 | void * data1_instance_cpy = flyweight_get(handle, &data1_cpy); 55 | if(data1_instance != data1_instance_cpy) { 56 | ERRLOG("failed to reuse instance"); 57 | } 58 | //change instance data to 2 59 | data1_cpy.data=2; 60 | flyweight_set(handle, &data1, &data1_cpy, NULL); 61 | 62 | data1_instance_cpy = flyweight_get(handle, &data1_cpy); 63 | if(data1_instance != data1_instance_cpy || (memcmp(&data1_cpy, data1_instance_cpy,sizeof(struct testclass1)) != 0) ) { 64 | ERRLOG("failed to set value"); 65 | } 66 | data1_instance = flyweight_get(handle, &data1); 67 | if(!data1_instance || data1_instance == data1_instance_cpy || (memcmp(&data1, data1_instance,sizeof(struct testclass1)) != 0) ) { 68 | ERRLOG("failed to get new value"); 69 | } 70 | testcnt++; 71 | } 72 | 73 | { 74 | if(flyweight_factory_new(0,0,NULL) != NULL) { 75 | ERRLOG("fail safe check error"); 76 | } 77 | if(flyweight_get(NULL,NULL) != NULL) { 78 | ERRLOG("fail safe check error"); 79 | } 80 | if(flyweight_get(handle,NULL) == NULL) { 81 | ERRLOG("fail safe accept NULL constructor"); 82 | } 83 | if(flyweight_set(NULL,NULL, NULL, NULL) != -1) { 84 | ERRLOG("fail safe check error"); 85 | } 86 | if(flyweight_set(handle,NULL, NULL, NULL) != -1) { 87 | ERRLOG("fail safe check error"); 88 | } 89 | testcnt++; 90 | } 91 | //exit 92 | 93 | flyweight_factory_free(NULL); 94 | flyweight_factory_free(handle); 95 | return testcnt; 96 | } 97 | -------------------------------------------------------------------------------- /mement/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib include test 2 | -------------------------------------------------------------------------------- /mement/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = mement.h 2 | -------------------------------------------------------------------------------- /mement/include/mement.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mement.h 3 | * @brief This is API for Prototype design pattern 4 | **/ 5 | #ifndef MEMENT_H 6 | #define MEMENT_H 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | 10 | /*! @struct mement_manager_t 11 | * MementRegister class member definition, defined in mement_manager.c 12 | */ 13 | struct mement_register_t; 14 | /*! MementRegister class definition, member is defined in mement_manager_t */ 15 | typedef struct mement_register_t *MementRegister; 16 | 17 | /*! @struct mement_method_t 18 | * MementMethod methods interface definition, to set mement_register. 19 | */ 20 | struct mement_method_t { 21 | 22 | /** 23 | * constructor 24 | * @param[out] instance new instance 25 | * @param[in] base base data pointer 26 | * @param[in] base_length base data length 27 | * @return new cloned pointer 28 | * @note default: memcopy, this is sharrow copy 29 | */ 30 | void (*constructor) (void *instance, void * base, size_t base_length); 31 | 32 | /** 33 | * copy api of a base data, to do deep copy 34 | * @param[out] broken_instance broken instance pointer 35 | * @param[in] base base data pointer 36 | * @param[in] base_length base data length 37 | * @return new cloned pointer 38 | * @note default: memcopy, this is sharrow copy 39 | */ 40 | void (*copy) (void *broken_instance, void * base, size_t base_length); 41 | 42 | /** 43 | * free api of a clone data, to do deep copy 44 | * @param[in] cloned_data cloned data by using clone function pointer in this mement_factory_method_t structure 45 | * @param[in] base_length base data length 46 | * @return none 47 | * @note default: none, free base data with MementRegister instance 48 | */ 49 | void (*free) (void * base, size_t base_length); 50 | }; 51 | 52 | typedef struct mement_method_t mement_method_t; 53 | 54 | /** 55 | * Create MementRegister class 56 | * 57 | * @param[in] base base data. 58 | * @param[in] base_length base data length 59 | * @param[in] method method ( if NULL or member is NULL, use default. It's better to use own method) 60 | * @retval !NULL MementRegister instance 61 | * @retval NULL error 62 | */ 63 | MementRegister mement_register(void * base, size_t base_length, mement_method_t * method); 64 | /** 65 | * Unregister MementRegister class 66 | * 67 | * @param[in] this MementRegister instance returned at mement_manager_new, 68 | * @return none 69 | */ 70 | void mement_unregister(MementRegister this); 71 | /** 72 | * Rememter mement information into broken_instance 73 | * 74 | * @param[in] this MementRegister instance returned at mement_register. 75 | * @param[out] broken_instance broken instance data. 76 | * @param[in] is_unregister_mement unregister mement or not. if !=0, unregister this data same as calling mement_unregister 77 | * @return none 78 | */ 79 | void mement_remember(MementRegister this, void * broken_instance, int is_unregister_mement); 80 | DP_H_END 81 | #endif 82 | -------------------------------------------------------------------------------- /mement/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/mement/mement_am.conf 3 | 4 | lib_LTLIBRARIES = libmement.la 5 | 6 | libmement_la_SOURCES = mement.c 7 | #for static library 8 | libmement_la_LDFLAGS=-shared 9 | -------------------------------------------------------------------------------- /mement/lib/mement.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mement.c 3 | * @brief Implement of mement API, defined in mement.h. 4 | **/ 5 | #include 6 | #include 7 | #include "mement.h" 8 | 9 | /*! mement_factory_instance, PrototypeFactory class instance definition*/ 10 | struct mement_register_t { 11 | void * base; 12 | size_t base_len; 13 | mement_method_t method; 14 | }; 15 | 16 | /*@name mement_factory_instance private API definition*/ 17 | /* @{ */ 18 | /*! free */ 19 | static void mement_default_constructor(void *instance, void * base, size_t base_length); 20 | /*! copy */ 21 | static void mement_default_copy(void *broken_instance, void * base, size_t base_length); 22 | /*! free */ 23 | static void mement_default_free(void * base, size_t base_length); 24 | /* @} */ 25 | 26 | /*! define to set default*/ 27 | #define MEMENTDEFAULT_METHOD(key) mement_default_ ## key 28 | /*! define to set method*/ 29 | #define MEMENTSET_METHOD(this, method, key) \ 30 | if(method && method->key) instance->method.key = method->key;\ 31 | else instance->method.key = MEMENTDEFAULT_METHOD(key) 32 | 33 | /*@name mement_factory_instance private API definition*/ 34 | /* @{ */ 35 | static void mement_default_constructor(void *instance, void * base, size_t base_length) { 36 | /*shallow copy*/ 37 | memcpy(instance, base, base_length); 38 | } 39 | 40 | static void mement_default_copy(void *broken_instance, void * base, size_t base_length) { 41 | /*shallow copy*/ 42 | memcpy(broken_instance, base, base_length); 43 | } 44 | 45 | static void mement_default_free(void * base, size_t base_length) { 46 | (void)base; 47 | } 48 | 49 | /* @} */ 50 | /*@name mement_factory_instance public API definition*/ 51 | /* @{ */ 52 | /*! new */ 53 | MementRegister mement_register(void * base, size_t base_length, mement_method_t * method) { 54 | if(!base || base_length==0) return NULL; 55 | 56 | MementRegister instance = malloc(sizeof(*instance) + base_length); 57 | if(!instance) { 58 | return NULL; 59 | } 60 | memset(instance, 0, sizeof(*instance) + base_length); 61 | 62 | instance->base = (instance + 1); 63 | instance->base_len = base_length; 64 | 65 | MEMENTSET_METHOD(instance, method, constructor); 66 | MEMENTSET_METHOD(instance, method, copy); 67 | MEMENTSET_METHOD(instance, method, free); 68 | 69 | instance->method.constructor(instance->base, base, base_length); 70 | return instance; 71 | } 72 | 73 | /*! free */ 74 | void mement_unregister(MementRegister this) { 75 | if(!this) return; 76 | 77 | this->method.free(this->base, this->base_len); 78 | free(this); 79 | } 80 | 81 | /*! remembe*/ 82 | void mement_remember(MementRegister this, void * broken_instance, int is_unregister_mement) { 83 | if(!this || !broken_instance) return; 84 | 85 | this->method.copy(broken_instance, this->base, this->base_len); 86 | 87 | /*unregister check*/ 88 | if(is_unregister_mement) mement_unregister(this); 89 | } 90 | /* @} */ 91 | -------------------------------------------------------------------------------- /mement/mement_am.conf: -------------------------------------------------------------------------------- 1 | #common header deifinition 2 | include $(top_srcdir)/am.conf 3 | 4 | AM_CPPFLAGS+=-I$(MEMENT_DIR)/include 5 | INCLUDES_PATH+=$(MEMENT_DIR)/include 6 | 7 | AM_LDFLAGS+=$(MEMENT_DIR)/lib/libmement.la 8 | -------------------------------------------------------------------------------- /mement/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/mement/mement_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CXXFLAGS = -g -O0 7 | test_CFLAGS = -g -O0 8 | test_SOURCES = main.c 9 | -------------------------------------------------------------------------------- /mement/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "mement.h" 7 | 8 | #define ERRORCASE \ 9 | printf( "###(%d)failed\n", __LINE__);\ 10 | return -1; 11 | 12 | static int test_mement_fail_safe() { 13 | void * data = NULL; 14 | /*is it dead?*/ 15 | mement_unregister(NULL); 16 | mement_remember(NULL, &data, 0); 17 | mement_remember((MementRegister)&data, NULL, 0); 18 | 19 | /*register parameter check*/ 20 | if(mement_register(NULL, sizeof(&data), NULL)) { 21 | ERRORCASE 22 | } 23 | 24 | if(mement_register(&data, 0, NULL)) { 25 | ERRORCASE 26 | } 27 | 28 | return 0; 29 | } 30 | 31 | static void tmp_api(void *ptr, size_t len) { 32 | (void)ptr; 33 | (void)len; 34 | } 35 | 36 | static int test_mement_default_cb() { 37 | int data = 10; 38 | 39 | MementRegister mement = mement_register(&data, sizeof(data), NULL); 40 | if(!mement) { 41 | ERRORCASE 42 | } 43 | 44 | data = 5; 45 | mement_remember(mement, &data, 0); 46 | if(data != 10) { 47 | ERRORCASE; 48 | } 49 | 50 | mement_unregister(mement); 51 | 52 | int data_static = 5; 53 | mement_method_t method={NULL, NULL, tmp_api}; 54 | mement = mement_register(&data_static, sizeof(data_static), &method); 55 | if(!mement) { 56 | ERRORCASE 57 | } 58 | 59 | data = 10; 60 | mement_remember(mement, &data, 0); 61 | if(data != 5) { 62 | ERRORCASE; 63 | } 64 | mement_unregister(mement); 65 | return 0; 66 | } 67 | 68 | #define TYPE_STRING (0) 69 | #define TYPE_INT (1) 70 | typedef struct test_msgdata{ 71 | int type; 72 | union { 73 | char * string; 74 | int * value; 75 | } data; 76 | }test_msgdata; 77 | 78 | static void test_msgdata_constructor(void *instance, void * base, size_t base_length) { 79 | test_msgdata * msgdata = (test_msgdata *) base; 80 | test_msgdata * msgdata_instance = (test_msgdata *) instance; 81 | 82 | msgdata_instance->type = msgdata->type; 83 | /*deep copy data*/ 84 | if(msgdata_instance->type == TYPE_STRING) { 85 | msgdata_instance->data.string = calloc(1, strlen(msgdata->data.string) + 1); 86 | sprintf(msgdata_instance->data.string, "%s", msgdata->data.string); 87 | } else { 88 | msgdata_instance->data.value = calloc(1, sizeof(int)); 89 | *msgdata_instance->data.value = *msgdata->data.value; 90 | } 91 | } 92 | 93 | static void test_msgdata_free(void * data, size_t data_length) { 94 | assert(data_length == sizeof(test_msgdata)); 95 | 96 | test_msgdata * msgdata = (test_msgdata *) data; 97 | if(msgdata->type == TYPE_STRING) { 98 | free(msgdata->data.string); 99 | } else { 100 | free(msgdata->data.value); 101 | } 102 | } 103 | 104 | static void test_msgdata_copy(void *broken_data, void * base, size_t base_length) { 105 | test_msgdata * msgdata = (test_msgdata *) base; 106 | test_msgdata * broken_msg = (test_msgdata *)broken_data; 107 | 108 | test_msgdata_free(broken_msg, base_length); 109 | test_msgdata_constructor(broken_msg, msgdata, base_length); 110 | } 111 | 112 | 113 | static void test_msgdata_int_init(test_msgdata *msgdata, int value) { 114 | msgdata->type = TYPE_INT; 115 | msgdata->data.value = calloc(1, sizeof(int)); 116 | *msgdata->data.value = value; 117 | } 118 | 119 | static void test_msgdata_string_init(test_msgdata *msgdata, const char* string) { 120 | msgdata->type = TYPE_STRING; 121 | msgdata->data.string = calloc(1, strlen(string) + 1); 122 | sprintf(msgdata->data.string, "%s", string); 123 | } 124 | 125 | #define MSG_OK "no problem msg!!" 126 | #define MSG_NG "missing msg!!" 127 | 128 | static int test_mement_normally(void) { 129 | 130 | /**deep copy test **/ 131 | test_msgdata basedata_int, basedata_string; 132 | test_msgdata_int_init(&basedata_int, 10); 133 | mement_method_t deep_method ={test_msgdata_constructor, test_msgdata_copy, test_msgdata_free}; 134 | MementRegister mement = mement_register(&basedata_int, sizeof(test_msgdata), &deep_method); 135 | if(!mement) { 136 | ERRORCASE 137 | } 138 | 139 | /*same type*/ 140 | *basedata_int.data.value = 20; 141 | 142 | mement_remember(mement, &basedata_int, 0); 143 | if(basedata_int.type != TYPE_INT || *basedata_int.data.value != 10) { 144 | ERRORCASE 145 | } 146 | 147 | /*different type*/ 148 | free(basedata_int.data.value); 149 | test_msgdata_string_init(&basedata_int, MSG_NG); 150 | 151 | mement_remember(mement, &basedata_int, 0); 152 | if(basedata_int.type != TYPE_INT || *basedata_int.data.value != 10) { 153 | ERRORCASE 154 | } 155 | mement_unregister(mement); 156 | free(basedata_int.data.value); 157 | 158 | /*check string type*/ 159 | test_msgdata_string_init(&basedata_string, MSG_OK); 160 | mement = mement_register(&basedata_string, sizeof(test_msgdata), &deep_method); 161 | if(!mement) { 162 | ERRORCASE 163 | } 164 | 165 | strcpy(basedata_string.data.string, MSG_NG); 166 | mement_remember(mement, &basedata_string, 0); 167 | if(basedata_string.type != TYPE_STRING || strcmp(basedata_string.data.string, MSG_OK) != 0 ) { 168 | ERRORCASE 169 | } 170 | 171 | /*different type*/ 172 | free(basedata_string.data.string); 173 | test_msgdata_int_init(&basedata_string, 10); 174 | mement_remember(mement, &basedata_string, 1); 175 | if(basedata_string.type != TYPE_STRING || strcmp(basedata_string.data.string, MSG_OK) != 0 ) { 176 | ERRORCASE 177 | } 178 | free(basedata_string.data.string); 179 | 180 | return 0; 181 | } 182 | 183 | int main(int argc, char *argv[]) { 184 | if(test_mement_fail_safe()) { 185 | ERRORCASE 186 | } 187 | 188 | if(test_mement_default_cb()) { 189 | ERRORCASE 190 | } 191 | 192 | if(test_mement_normally()) { 193 | ERRORCASE 194 | } 195 | 196 | printf("Success all test!!\n"); 197 | return 0; 198 | } 199 | -------------------------------------------------------------------------------- /memorypool/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib include test 2 | -------------------------------------------------------------------------------- /memorypool/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = memorypool.h 2 | -------------------------------------------------------------------------------- /memorypool/include/memorypool.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file memorypool.h 3 | * This is API for memory pool 4 | **/ 5 | #ifndef MEMORYPOOL_H 6 | #define MEMORYPOOL_H 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | /*! @struct memorypool_t 10 | * @brief MemoryPool class member definition, detail is defined in C file. 11 | */ 12 | struct memorypool_t; 13 | /*! MemoryPool class definition, to use API */ 14 | typedef struct memorypool_t * MemoryPool; 15 | 16 | /** 17 | * create MemoryPool class 18 | * 19 | * @param[in] max_size max of allocated memory size, to allocate fast, this value will update 2^n in library. 20 | * @param[in] max_cnt number of allocated memory 21 | * @param[in] is_multithread threadsafe flag. If you want to use it on multi thread, please set 1. 22 | * @param[in] constructor if you want to initialize memory first. 23 | * @param[in] constructor_parameter constructor parameter if you want to initialize memory first. 24 | * @retval !=NULL this class handle 25 | * @retval NULL error 26 | */ 27 | MemoryPool mpool_create(size_t max_size, size_t max_cnt, int is_multithread, void (*constructor)(void * this, void *constructor_parameter), void *constructor_parameter); 28 | /** 29 | * free MemoryPool class 30 | * 31 | * @param[in] this MemoryPool instance returned at mpool_malloc_new, 32 | * @param[in] destructor if you want to finialize memory 33 | * @return none 34 | */ 35 | void mpool_delete(MemoryPool this, void (*destructor)(void *)); 36 | 37 | /** 38 | * get memory from pool 39 | * 40 | * @param[in] this MemoryPool instance returned at mpool_malloc_new, 41 | * @retval !=NULL allocated pointer 42 | * @retval NULL max_size of allocated memory 43 | * @note If already get all allocated pointer, return NULL 44 | */ 45 | void * mpool_get(MemoryPool this); 46 | /** 47 | * get used memory 48 | * 49 | * @param[in] this MemoryPool instance return, 50 | * @param[in] ptr used pointer 51 | * @retval !=NULL get next 52 | * @retval NULL this pointer is end 53 | */ 54 | void * mpool_get_next_usedmem(MemoryPool this, void * ptr); 55 | 56 | /*! define for used loop */ 57 | #define FOR_ALL_USEDMEM(this,ptr) for(ptr=mpool_get_next_usedmem(this, NULL); ptr!=NULL; ptr = mpool_get_next_usedmem(this, ptr )) 58 | 59 | /** 60 | * get used cnt 61 | * 62 | * @param[in] this MemoryPool instance return, 63 | * @return used count 64 | */ 65 | size_t mpool_get_usedcnt(MemoryPool this); 66 | /** 67 | * release memory to pool 68 | * 69 | * @param[in] this MemoryPool instance returned at mpool_malloc_new, 70 | * @param[in] ptr allocated pointer which get from mpool_malloc 71 | * @return none 72 | * @note not initialize memory 73 | */ 74 | void mpool_release(MemoryPool this, void * ptr); 75 | DP_H_END 76 | #endif 77 | -------------------------------------------------------------------------------- /memorypool/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/memorypool/memorypool_am.conf 3 | 4 | lib_LTLIBRARIES = libmemorypool.la 5 | 6 | libmemorypool_la_SOURCES = memorypool.c 7 | libmemorypool_la_LDFLAGS=-shared 8 | libmemorypool_la_LDFLAGS+=-Wl,--version-script,memorypool.map 9 | -------------------------------------------------------------------------------- /memorypool/lib/memorypool.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | mpool_create; 4 | mpool_delete; 5 | mpool_get; 6 | mpool_get_next_usedmem; 7 | mpool_get_usedcnt; 8 | mpool_release; 9 | local: *; 10 | }; 11 | -------------------------------------------------------------------------------- /memorypool/memorypool_am.conf: -------------------------------------------------------------------------------- 1 | #common header deifinition 2 | include $(top_srcdir)/am.conf 3 | 4 | AM_CPPFLAGS+=-I$(MEMPOOL_DIR)/include 5 | INCLUDES_PATH+=-I$(MEMPOOL_DIR)/include 6 | 7 | AM_LDFLAGS+=$(MEMPOOL_DIR)/lib/libmemorypool.la 8 | -------------------------------------------------------------------------------- /memorypool/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/memorypool/memorypool_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CFLAGS = -g -O0 7 | test_SOURCES = main.c 8 | test_LDFLAGS = $(AM_LDFLAGS) $(MEMPOOL_DIR)/lib/libmemorypool.la 9 | -------------------------------------------------------------------------------- /prototype/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib include test 2 | -------------------------------------------------------------------------------- /prototype/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = prototype.h 2 | -------------------------------------------------------------------------------- /prototype/include/prototype.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file prototype.h 3 | * @brief This is API for Prototype design pattern 4 | **/ 5 | #ifndef PROTOTYPE_H 6 | #define PROTOTYPE_H 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | 10 | /*! @struct prototype_manager_t 11 | * PrototypeManager class member definition, defined in prototype_manager.c 12 | */ 13 | struct prototype_manager_t; 14 | /*! PrototypeManager class definition, member is defined in prototype_manager_t */ 15 | typedef struct prototype_manager_t *PrototypeManager; 16 | 17 | /*! @struct prototype_factory_t 18 | * PrototypeFactory methods interface definition, to set prototype_register. 19 | */ 20 | struct prototype_factory_t; 21 | /*! PrototypeFactory class definition, member is defined in prototype_factory_t */ 22 | typedef struct prototype_factory_t *PrototypeFactory; 23 | 24 | #define PROTOTYPE_SUCCESS (0) 25 | #define PROTOTYPE_FAILED (-1) 26 | 27 | /*! @struct prototype_factory_method_t 28 | * PrototypeFactory methods interface definition, to set prototype_register. 29 | */ 30 | struct prototype_factory_method_t { 31 | /** 32 | * clone api of a base data, to do deep copy 33 | * @param[in] base base data pointer 34 | * @param[in] base_length base data length 35 | * @return new cloned pointer 36 | * @note default: memcopy, this is sharrow copy 37 | */ 38 | void * (*clone) (void * base, size_t base_length); 39 | /** 40 | * free api of a clone data, to do deep copy 41 | * @param[in] cloned_data cloned data by using clone function pointer in this prototype_factory_method_t structure 42 | * @param[in] base_length base data length 43 | * @return none 44 | * @note default: free 45 | */ 46 | void (*free) (void * cloned_data); 47 | /** 48 | * free api of a base data, please free deep data 49 | * @param[in] base_data base data registered by prototype_register 50 | * @return none 51 | * @note default: free 52 | */ 53 | void (*free_base) (void * base_data); 54 | }; 55 | 56 | typedef struct prototype_factory_method_t prototype_factory_method_t; 57 | 58 | /** 59 | * Create PrototypeManager class 60 | * 61 | * @param[in] is_threadsafe if !=0, ensure threadsafe to create new class instace 62 | * @retval !=NULL this class handle 63 | * @retval NULL error 64 | */ 65 | PrototypeManager prototype_manager_new(int is_threadsafe); 66 | /** 67 | * free class handle 68 | * @param [in] this PrototypeManager instance returned at prototype_manager_new, 69 | * @return none 70 | */ 71 | void prototype_manager_free(PrototypeManager this); 72 | 73 | /** 74 | * Register PrototypeFactory class 75 | * 76 | * @param[in] this PrototypeManager instance returned at prototype_manager_new, 77 | * @param[in] base base data. 78 | * @param[in] base_length base data length 79 | * @param[in] factory_method factory method ( if NULL or member is NULL, use default. It's better to use free_basedata) 80 | * @retval !NULL PrototypeFactory instance 81 | * @retval NULL error 82 | * @note Please keep instance of base. This will free into prototype_unregister API by using free_basedata 83 | * 84 | */ 85 | PrototypeFactory prototype_register(PrototypeManager this, void * base, size_t base_length, prototype_factory_method_t * factory_method); 86 | 87 | /** 88 | * Unregister PrototypeFactory class 89 | * 90 | * @param[in] this PrototypeManager instance returned at prototype_manager_new, 91 | * @param[in] factory PrototypeFactory instance returned at prototype_register, 92 | * @return none 93 | */ 94 | void prototype_unregister(PrototypeManager this, PrototypeFactory factory); 95 | /** 96 | * Clone base pointer by using PrototypeFactory class 97 | * 98 | * @param[in] this PrototypeFactory instance returned at prototype_register. 99 | * @return cloned data or NULL 100 | */ 101 | void * prototype_clone(PrototypeFactory this); 102 | /** 103 | * Free cloned pointer 104 | * 105 | * @param[in] this PrototypeFactory instance returned at prototype_register. 106 | * @param[in] cloned_data free data returned at prototype_clone. 107 | * @return none 108 | */ 109 | void prototype_free(PrototypeFactory this, void * cloned_data); 110 | DP_H_END 111 | #endif 112 | -------------------------------------------------------------------------------- /prototype/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/prototype/prototype_am.conf 3 | 4 | lib_LTLIBRARIES = libprototype.la 5 | 6 | libprototype_la_SOURCES = prototype_factory.c prototype_manager.c 7 | #for static library 8 | libprototype_la_LDFLAGS=-shared $(DPUTIL_DIR)/lib/libdputil.la 9 | libprototype_la_LDFLAGS+=-Wl,--version-script,prototype.map 10 | -------------------------------------------------------------------------------- /prototype/lib/prototype.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | prototype_manager_new; 4 | prototype_manager_free; 5 | prototype_register; 6 | prototype_unregister; 7 | prototype_clone; 8 | prototype_free; 9 | local: *; 10 | }; 11 | -------------------------------------------------------------------------------- /prototype/lib/prototype_factory.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file prototype_factory.c 3 | * @brief Implement of prototype_factory API, defined in prototype_factory.h. 4 | **/ 5 | #include 6 | #include "dp_util.h" 7 | #include "prototype_factory.h" 8 | 9 | /*! prototype_factory_instance, PrototypeFactory class instance definition*/ 10 | struct prototype_factory_instance_t { 11 | void * base; 12 | size_t base_len; 13 | prototype_factory_method_t factory_method; 14 | }; 15 | 16 | /*@name prototype_factory_instance private API definition*/ 17 | /* @{ */ 18 | /*! clone */ 19 | static void * prototype_default_clone(void * base, size_t base_length); 20 | /*! free */ 21 | static void prototype_default_free(void * clone_base); 22 | /*! free base */ 23 | static void prototype_default_free_base(void * base); 24 | /* @} */ 25 | 26 | /*! define to set default*/ 27 | #define PROT_FACT_DEFAULT_METHOD(key) prototype_default_ ## key 28 | /*! define to set method*/ 29 | #define PROT_FACT_SET_METHOD(this, factory_method, key) \ 30 | if(factory_method && factory_method->key) instance->factory_method.key = factory_method->key;\ 31 | else instance->factory_method.key = PROT_FACT_DEFAULT_METHOD(key) 32 | 33 | /*@name prototype_factory_instance private API definition*/ 34 | /* @{ */ 35 | static void * prototype_default_clone(void * base, size_t base_length) { 36 | void * clone_data = malloc(base_length); 37 | if(!clone_data) return NULL; 38 | 39 | /*shallow copy*/ 40 | memcpy(clone_data, base, base_length); 41 | return clone_data; 42 | } 43 | 44 | static void prototype_default_free(void * clone_base) { 45 | free(clone_base); 46 | } 47 | 48 | static void prototype_default_free_base(void * base) { 49 | free(base); 50 | } 51 | /* @} */ 52 | /*@name prototype_factory_instance public API definition*/ 53 | /* @{ */ 54 | /*! new */ 55 | PrototypeFactoryInstance prototype_factory_instance_new(void * base, size_t base_length, prototype_factory_method_t * factory_method) { 56 | PrototypeFactoryInstance instance = calloc(1, sizeof(*instance)); 57 | if(!instance) { 58 | return NULL; 59 | } 60 | 61 | instance->base = base; 62 | instance->base_len = base_length; 63 | 64 | PROT_FACT_SET_METHOD(instance, factory_method, clone); 65 | PROT_FACT_SET_METHOD(instance, factory_method, free); 66 | PROT_FACT_SET_METHOD(instance, factory_method, free_base); 67 | return instance; 68 | } 69 | 70 | /*! free */ 71 | void prototype_factory_instance_free(PrototypeFactoryInstance this) { 72 | this->factory_method.free_base(this->base); 73 | free(this); 74 | } 75 | 76 | /*! clone data */ 77 | void * prototype_factory_instance_clone_data(PrototypeFactoryInstance this) { 78 | return this->factory_method.clone(this->base, this->base_len); 79 | } 80 | 81 | /*! free data */ 82 | void prototype_factory_instance_free_data(PrototypeFactoryInstance this, void *data) { 83 | this->factory_method.free(data); 84 | } 85 | /* @} */ 86 | -------------------------------------------------------------------------------- /prototype/lib/prototype_factory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file prototype_factory.h 3 | * @brief This is API for PrototypeFactoryInstance class 4 | **/ 5 | #ifndef PROTOTYPE_FACTORY_H 6 | #define PROTOTYPE_FACTORY_H 7 | #include "prototype.h" 8 | 9 | /*! prototype_factory_instance, PrototypeFactory class instance definition*/ 10 | struct prototype_factory_instance_t; 11 | typedef struct prototype_factory_instance_t prototype_factory_instance_t, *PrototypeFactoryInstance; 12 | 13 | /*@name prototype_factory_instance API definition*/ 14 | /* @{ */ 15 | /*! new */ 16 | PrototypeFactoryInstance prototype_factory_instance_new(void * base, size_t base_length, prototype_factory_method_t * factory_method); 17 | /*! free */ 18 | void prototype_factory_instance_free(PrototypeFactoryInstance this); 19 | /*! clone data */ 20 | void * prototype_factory_instance_clone_data(PrototypeFactoryInstance this); 21 | /*! free data */ 22 | void prototype_factory_instance_free_data(PrototypeFactoryInstance this, void * data); 23 | /* @} */ 24 | #endif 25 | -------------------------------------------------------------------------------- /prototype/lib/prototype_manager.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file prototype_manager.c 3 | * @brief Implement of Prototype library API, defined in prototype.h. 4 | **/ 5 | #include 6 | #include "dp_util.h" 7 | #include "prototype_factory.h" 8 | 9 | /************* 10 | * public define 11 | *************/ 12 | struct prototype_factory_t { 13 | PrototypeFactory next; 14 | PrototypeFactory prev; 15 | pthread_mutex_t *lock; 16 | PrototypeFactoryInstance instance; 17 | }; 18 | 19 | /*! @struct prototype_manager_t 20 | * @brief information of StateMachine, to use as list 21 | */ 22 | struct prototype_manager_t { 23 | PrototypeFactory head; 24 | PrototypeFactory tail; 25 | pthread_mutex_t *lock; 26 | }; 27 | 28 | #define prototype_push(this, data) dputil_list_push((DPUtilList)this, (DPUtilListData)data); 29 | #define prototype_pull(this, data) dputil_list_pull((DPUtilList)this, (DPUtilListData)data); 30 | #define prototype_pop(this) (PrototypeFactory)dputil_list_pop((DPUtilList)this); 31 | 32 | #define PROTOTYPE_LOCK(this) DPUTIL_LOCK(this->lock); 33 | #define PROTOTYPE_UNLOCK DPUTIL_UNLOCK 34 | 35 | PrototypeManager prototype_manager_new(int is_threadsafe) { 36 | PrototypeManager instance = calloc(1, sizeof(*instance)); 37 | if(!instance) { 38 | DEBUG_ERRPRINT("Failed to create instance\n"); 39 | return NULL; 40 | } 41 | 42 | if(is_threadsafe) { 43 | instance->lock = malloc(sizeof(*(instance->lock))); 44 | if(!instance->lock) { 45 | DEBUG_ERRPRINT("Fai|led to create lock instance\n"); 46 | free(instance); 47 | return NULL; 48 | } 49 | pthread_mutex_init(instance->lock, NULL); 50 | } 51 | 52 | return instance; 53 | } 54 | 55 | void prototype_manager_free(PrototypeManager this) { 56 | pthread_mutex_t *lock=NULL; 57 | if(!this) { 58 | return; 59 | } 60 | 61 | PROTOTYPE_LOCK(this) 62 | lock=this->lock; 63 | PrototypeFactory factory = prototype_pop(this); 64 | while(factory) { 65 | prototype_factory_instance_free(factory->instance); 66 | free(factory); 67 | factory = prototype_pop(this); 68 | } 69 | free(this); 70 | PROTOTYPE_UNLOCK 71 | free(lock); 72 | } 73 | 74 | PrototypeFactory prototype_register(PrototypeManager this, void * base, size_t base_length, prototype_factory_method_t * factory_method) { 75 | PrototypeFactory factory = NULL; 76 | if(!this || !base || base_length==0) { 77 | return NULL; 78 | } 79 | 80 | PROTOTYPE_LOCK(this) 81 | factory = calloc(1, sizeof(*factory)); 82 | if(!factory) { 83 | DEBUG_ERRPRINT("Fai|led to create PrototypeFactory\n"); 84 | goto end; 85 | } 86 | 87 | factory->instance = prototype_factory_instance_new(base, base_length, factory_method); 88 | if(!factory->instance) { 89 | DEBUG_ERRPRINT("Fai|led to create PrototypeFactory instance\n"); 90 | free(factory); 91 | factory=NULL; 92 | goto end; 93 | } 94 | 95 | factory->lock=this->lock; 96 | prototype_push(this, factory); 97 | end: 98 | PROTOTYPE_UNLOCK 99 | return factory; 100 | } 101 | 102 | void prototype_unregister(PrototypeManager this, PrototypeFactory factory) { 103 | if(!this || !factory) { 104 | return; 105 | } 106 | 107 | PROTOTYPE_LOCK(this) 108 | prototype_pull(this, factory); 109 | PROTOTYPE_UNLOCK 110 | prototype_factory_instance_free(factory->instance); 111 | free(factory); 112 | } 113 | 114 | void * prototype_clone(PrototypeFactory this) { 115 | if(!this) { 116 | return NULL; 117 | } 118 | 119 | void * data; 120 | PROTOTYPE_LOCK(this) 121 | data = prototype_factory_instance_clone_data(this->instance); 122 | PROTOTYPE_UNLOCK 123 | return data; 124 | } 125 | 126 | void prototype_free(PrototypeFactory this, void * cloned_data) { 127 | if(!this || !cloned_data) { 128 | return; 129 | } 130 | 131 | PROTOTYPE_LOCK(this) 132 | prototype_factory_instance_free_data(this->instance, cloned_data); 133 | PROTOTYPE_UNLOCK 134 | } 135 | -------------------------------------------------------------------------------- /prototype/prototype_am.conf: -------------------------------------------------------------------------------- 1 | #common header deifinition 2 | include $(top_srcdir)/am.conf 3 | 4 | AM_CPPFLAGS+=-I$(PROTOTYPE_DIR)/include 5 | INCLUDES_PATH+=$(PROTOTYPE_DIR)/include 6 | 7 | AM_LDFLAGS+=$(PROTOTYPE_DIR)/lib/libprototype.la 8 | -------------------------------------------------------------------------------- /prototype/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/prototype/prototype_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CXXFLAGS = -g -O0 7 | test_CFLAGS = -g -O0 8 | test_SOURCES = main.c 9 | -------------------------------------------------------------------------------- /publisher/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib include test sample 2 | -------------------------------------------------------------------------------- /publisher/README.md: -------------------------------------------------------------------------------- 1 | # Observer(Publish Subscribe) 2 | The library for Linux C language to use Observer(Publish Subscribe) pattern. 3 | 4 | # How to use 5 | After build all, please link libpublisher.so library. 6 | API header is in publisher.h 7 | 8 | Please see wiki "https://github.com/developer-kikikaikai/design_pattern_for_c/wiki/Observer(Publish-Subscribe)" for more detai. 9 | -------------------------------------------------------------------------------- /publisher/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = publisher.h 2 | -------------------------------------------------------------------------------- /publisher/include/publisher.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file publisher.h 3 | * @brief This is API as Observer(Publish-Subscribe) design petten 4 | **/ 5 | #ifndef PUBLISHER_H_ 6 | #define PUBLISHER_H_ 7 | 8 | #include "dp_define.h" 9 | DP_H_BEGIN 10 | 11 | #include 12 | 13 | #define PUBLISHER_SUCCESS (0) 14 | #define PUBLISHER_FAILED (-1) 15 | 16 | /*! @struct subscriber_account_t 17 | * @brief SubscriberAccount class member definition, to get by publisher_subscribe. This is defined in publisher.c. 18 | */ 19 | struct subscriber_account_t; 20 | 21 | /** @brief SubscriberAccount class definition */ 22 | typedef struct subscriber_account_t subscriber_account_t, *SubscriberAccount; 23 | 24 | /** 25 | * @brief new Publisher content, user can get notify to subscribe. 26 | * @param[in] contents_num max size of publish content 27 | * @retval PUBLISHER_SUCCESS success to create PublisherContents, you can select content by 1, 2, 3, ... ,contents_num 28 | * @retval PUBLISHER_FAILED Failed to create instance/already created 29 | */ 30 | int publisher_new(size_t contents_num); 31 | 32 | /** 33 | * @brief free All publisher content 34 | * @return none 35 | */ 36 | void publisher_free(void); 37 | 38 | /** 39 | * @brief subscribe 40 | * @param[in] content_id id of publish content you want to receive 41 | * @param[in] publish_type type of pushlish related to publish. this ID use bitwise operation "OR". So if you want to receive notification from some publish type, please use "OR". So, if you set 0, send notify to all 42 | * @param[in] notify notification interface. If subscriber set this IF and type, publisher notify when publish. 43 | * @param[in] ctx user definition ctx information 44 | * @retval !=NULL SubscriberAccount account of this subscribe, if you want to manage unscribe/subscribe many time, please keep this accout information 45 | * @retval NULL failed to subscribe 46 | */ 47 | SubscriberAccount publisher_subscribe(int content_id, int publish_type, void (*notify)(int publish_type, void * detail, void * ctx), void * ctx ); 48 | 49 | /** 50 | * @brief subscribe only oneshot 51 | * @param[in] content_id id of publish content you want to receive 52 | * @param[in] publish_type type of pushlish related to publish. this ID use bitwise operation "OR". So if you want to receive notification from some publish type, please use "OR". So, if you set 0, send notify to all 53 | * @param[in] notify notification interface. If subscriber set this IF and type, publisher notify when publish. 54 | * @param[in] ctx user definition ctx information 55 | * @return none 56 | * @note ctx is not free in this library 57 | */ 58 | void publisher_subscribe_oneshot(int content_id, int publish_type, void (*notify)(int publish_type, void * detail, void * ctx), void * ctx ); 59 | /** 60 | * @brief unsubscribe, if you want to stop subscribe, please call it 61 | * @param[in] content_id id of publish content 62 | * @param[in] account account returned at publisher_subscribe 63 | * @return none 64 | */ 65 | void publisher_unsubscribe(int content_id, SubscriberAccount account); 66 | 67 | /** 68 | * @brief publish, Publisher call subscriber's notify if type is same 69 | * @param[in] content_id id 70 | * @param[in] publish_type publish type 71 | * @param[in] detail detail data of publish 72 | * @return none 73 | */ 74 | void publisher_publish(int content_id, int publish_type, void * detail); 75 | DP_H_END 76 | #endif 77 | -------------------------------------------------------------------------------- /publisher/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/publisher/publisher_am.conf 3 | 4 | lib_LTLIBRARIES = libpublisher.la 5 | 6 | libpublisher_la_SOURCES = publisher.c publish_content.c 7 | #for statik library 8 | libpublisher_la_LDFLAGS=-shared $(DPUTIL_DIR)/lib/libdputil.la 9 | libpublisher_la_LDFLAGS+=-Wl,--version-script,publisher.map 10 | -------------------------------------------------------------------------------- /publisher/lib/publish_content.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file publish_content.c 3 | * @brief Implement of Flyweight design petten library API, related to PublishContent class 4 | **/ 5 | #include "publish_content.h" 6 | #include 7 | #include 8 | #include "dp_util.h" 9 | struct subscriber_account_t { 10 | SubscriberAccount next; 11 | SubscriberAccount prev; 12 | int is_oneshot; 13 | int publish_type; 14 | void (*notify)(int publish_type, void * detail, void * ctx); 15 | void * ctx; 16 | }; 17 | 18 | struct publish_content_t { 19 | SubscriberAccount head; 20 | SubscriberAccount tail; 21 | pthread_mutex_t lock; 22 | }; 23 | 24 | 25 | /*! @name PublishContent private method */ 26 | /* @{ */ 27 | /*! push subscriber */ 28 | static inline void publish_content_push_subscriber(PublishContent this, SubscriberAccount account) { 29 | dputil_list_push((DPUtilList)this, (DPUtilListData)account); 30 | } 31 | /*! pull subscriber */ 32 | static inline void publish_content_pull_subscriber(PublishContent this, SubscriberAccount account) { 33 | dputil_list_pull((DPUtilList)this, (DPUtilListData)account); 34 | free(account); 35 | } 36 | /*! pop subscriber */ 37 | static inline SubscriberAccount publish_content_pop_subscriber(PublishContent this) { 38 | SubscriberAccount account = (SubscriberAccount)dputil_list_pop((DPUtilList)this); 39 | free(account); 40 | return account; 41 | } 42 | #define PUBLISH_CONTENT_LOCK(content) DPUTIL_LOCK(&(content->lock)) 43 | #define PUBLISH_CONTENT_UNLOCK DPUTIL_UNLOCK 44 | /* @} */ 45 | 46 | /************* 47 | * public interface API implement 48 | *************/ 49 | PublishContent publish_content_new(void) { 50 | PublishContent content = (PublishContent)calloc(1, sizeof(publish_content_t)); 51 | pthread_mutex_init(&content->lock, NULL); 52 | return content; 53 | } 54 | 55 | SubscriberAccount publish_content_subscribe(PublishContent this, int publish_type, void (*notify)(int publish_type, void * detail, void * ctx), void * ctx) { 56 | SubscriberAccount account=NULL; 57 | 58 | PUBLISH_CONTENT_LOCK(this) 59 | account = (SubscriberAccount)calloc(1, sizeof(publish_content_t)); 60 | if(account) { 61 | account->publish_type = publish_type; 62 | account->notify = notify; 63 | account->ctx = ctx; 64 | publish_content_push_subscriber(this, account); 65 | } 66 | PUBLISH_CONTENT_UNLOCK 67 | return account; 68 | } 69 | 70 | void publish_content_subscribe_oneshot(PublishContent this, int publish_type, void (*notify)(int publish_type, void * detail, void * ctx), void * ctx) { 71 | 72 | PUBLISH_CONTENT_LOCK(this) 73 | SubscriberAccount account = (SubscriberAccount)calloc(1, sizeof(publish_content_t)); 74 | if(account) { 75 | account->is_oneshot = 1; 76 | account->publish_type = publish_type; 77 | account->notify = notify; 78 | account->ctx = ctx; 79 | publish_content_push_subscriber(this, account); 80 | } 81 | PUBLISH_CONTENT_UNLOCK 82 | } 83 | 84 | void publish_content_unsubscribe(PublishContent this, SubscriberAccount account) { 85 | PUBLISH_CONTENT_LOCK(this) 86 | publish_content_pull_subscriber(this, account); 87 | PUBLISH_CONTENT_UNLOCK 88 | 89 | } 90 | 91 | void publish_content_publish(PublishContent this, int publish_type, void * detail) { 92 | PUBLISH_CONTENT_LOCK(this) 93 | SubscriberAccount account, account_next; 94 | account = this->head; 95 | while(account) { 96 | /* check type */ 97 | if((account->publish_type & publish_type) != publish_type) { 98 | account=account->next; 99 | continue; 100 | } 101 | 102 | /* notify message, notify is not null because publisher check it */ 103 | account->notify(publish_type, detail, account->ctx); 104 | if(account->is_oneshot) { 105 | account_next = account->next; 106 | publish_content_pull_subscriber(this, account); 107 | account=account_next; 108 | } else { 109 | account=account->next; 110 | } 111 | } 112 | 113 | PUBLISH_CONTENT_UNLOCK 114 | } 115 | 116 | void publish_content_free(PublishContent this ) { 117 | PUBLISH_CONTENT_LOCK(this) 118 | SubscriberAccount account; 119 | 120 | /* free all account */ 121 | account=this->head; 122 | while(account) { 123 | /* unsubscribe head */ 124 | account = publish_content_pop_subscriber(this); 125 | } 126 | 127 | PUBLISH_CONTENT_UNLOCK 128 | /* free this after unlick*/ 129 | free(this); 130 | } 131 | -------------------------------------------------------------------------------- /publisher/lib/publish_content.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file publish_content.h 3 | * @brief This is API for PublishContent class which managed in Publisher 4 | **/ 5 | #ifndef PUBLISH_CONTENT_H_ 6 | #define PUBLISH_CONTENT_H_ 7 | 8 | #include "publisher.h" 9 | 10 | /*! @struct publish_content 11 | * @brief PublishContent class instance definition, detail is in publish_content.c 12 | */ 13 | struct publish_content_t; 14 | typedef struct publish_content_t publish_content_t, *PublishContent; 15 | 16 | /* 17 | * @brief new 18 | * @param[in] none 19 | * @return !=NULL : PublishContent resource 20 | * @retval NULL : failed to subscribe 21 | */ 22 | PublishContent publish_content_new(void); 23 | 24 | /* 25 | * @brief subscribe. 26 | * @param[in] publish_type type of pushlish related to publish. this ID use bitwise operation "OR". So if you want to receive notification from some publish type, please use "OR". 27 | * @param[in] notify notification interface. If subscriber set this IF and type, publisher notify when publish. 28 | * @param[in] ctx user definition ctx information 29 | * @retval !=NULL : SubscriberAccount account of this subscribe, if you want to manage unscribe/subscribe many time, please keep this accout information 30 | * @retval NULL : failed to subscribe 31 | */ 32 | SubscriberAccount publish_content_subscribe(PublishContent this, int publish_type, void (*notify)(int publish_type, void * detail, void * ctx), void * ctx); 33 | 34 | /* 35 | * @brief subscribe oneshot 36 | * @param[in] publish_type type of pushlish related to publish. this ID use bitwise operation "OR". So if you want to receive notification from some publish type, please use "OR". 37 | * @param[in] notify notification interface. If subscriber set this IF and type, publisher notify when publish. 38 | * @param[in] ctx user definition ctx information 39 | * @return none 40 | */ 41 | void publish_content_subscribe_oneshot(PublishContent this, int publish_type, void (*notify)(int publish_type, void * detail, void * ctx), void * ctx); 42 | 43 | /* 44 | * @brief unsubscribe. If you want to stop subscribe, please call it 45 | * @param[in] PublishContent 46 | * @param[in] account account returned at publisher_subscribe 47 | * @return none 48 | */ 49 | void publish_content_unsubscribe(PublishContent this, SubscriberAccount account); 50 | 51 | /* 52 | * @brief publish. Publisher call subscriber's notify if type is same 53 | * @param[in] PublishContent 54 | * @param[in] publish_type publish type 55 | * @param[in] detail detail data of publish 56 | * @return none 57 | */ 58 | void publish_content_publish(PublishContent content, int publish_type, void * detail); 59 | 60 | /* 61 | * @brief free 62 | * @param[in] PublishContent 63 | * @return none 64 | */ 65 | void publish_content_free(PublishContent content); 66 | #endif 67 | -------------------------------------------------------------------------------- /publisher/lib/publisher.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file publisher.c 3 | * @brief Implement of Flyweight design petten library API, related to Publisher class 4 | **/ 5 | #include 6 | #include 7 | #include "publish_content.h" 8 | #include "dp_util.h" 9 | 10 | /*! @struct publisher_mng_t 11 | * @brief publisher class instance 12 | */ 13 | struct publisher_mng_t { 14 | int content_cnt;/*! content cnt, to use fail safe (care list size)*/ 15 | PublishContent * contents;/*! list of PublishContent data, allocate content_cnt size*/ 16 | } publisher_g; 17 | 18 | /* @brief definition convert from ID to INDEX macro */ 19 | #define PC_INDEX_FROM_ID(content_id) ((content_id)-1) 20 | 21 | /************* 22 | * private interface API implement 23 | *************/ 24 | /** 25 | * @brief get content from id 26 | * @param [in] content_id 27 | * @return PublishContent instance 28 | */ 29 | static PublishContent publisher_get_content(int content_id) { 30 | if ((0 2 | #include 3 | #include 4 | #include 5 | 6 | #include "publisher.h" 7 | #include "publish_msg.h" 8 | #include "subscriber.h" 9 | 10 | static int running_g=1; 11 | static void stop_running(void) { 12 | running_g=0; 13 | } 14 | static int is_running() { 15 | return (running_g==1); 16 | } 17 | void sighandler(int signum) { 18 | printf("call sighandler, id=%d\n", signum); 19 | stop_running(); 20 | printf("exit process! please enter some key!!\n"); 21 | } 22 | 23 | int main(int argc, char *argv[]) { 24 | struct { 25 | int type; 26 | char *defail; 27 | } msgtype[] = { 28 | {PUB_MSG_PUBLISH_NEW_BOOK, "Release new book!"}, 29 | {PUB_MSG_PUBLISH_DISCOUNT_BOOK, "Discount book!"}, 30 | {PUB_MSG_PUBLISH_STOP_PRODUCTION, "Stop production this book..."}, 31 | }; 32 | 33 | //signal setting 34 | signal(SIGHUP, sighandler); 35 | signal(SIGINT, sighandler); 36 | signal(SIGTERM, sighandler); 37 | 38 | publisher_new(1); 39 | 40 | printf("Start subscribe!\n"); 41 | subscriber_init(); 42 | 43 | int ret=0; 44 | int i=0; 45 | int type; 46 | publish_msg_detail_t msg_defail; 47 | while(is_running()) { 48 | memset(&msg_defail, 0, sizeof(msg_defail)); 49 | printf("Please enter witter name\n"); 50 | ret = scanf("%s", msg_defail.writername); 51 | if(ret != 1 || !is_running()) continue; 52 | 53 | printf("Please enter msg type:\n"); 54 | for(i = 0;i < sizeof(msgtype)/sizeof(msgtype[0]); i ++) { 55 | printf("type:%d (%s)\n", msgtype[i].type, msgtype[i].defail); 56 | } 57 | 58 | ret = scanf("%d", &type); 59 | if(ret != 1 || !is_running()) continue; 60 | 61 | printf("OK, notify to subscriber!\n"); 62 | publisher_publish(PUBLISH_ID, type, &msg_defail); 63 | } 64 | 65 | subscriber_exit(); 66 | publisher_free(); 67 | } 68 | -------------------------------------------------------------------------------- /publisher/sample/publish_msg.h: -------------------------------------------------------------------------------- 1 | #ifndef PUBLISH_MSG_ 2 | #define PUBLISH_MSG_ 3 | 4 | #define PUBLISH_ID (1) 5 | #define PUB_MSG_PUBLISH_NEW_BOOK (0x01<<0) 6 | #define PUB_MSG_PUBLISH_DISCOUNT_BOOK (0x01<<1) 7 | #define PUB_MSG_PUBLISH_STOP_PRODUCTION (0x01<<2) 8 | 9 | typedef struct publish_msg_detail { 10 | char writername[32]; 11 | } publish_msg_detail_t; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /publisher/sample/subscriber.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "publisher.h" 9 | #include "publish_msg.h" 10 | 11 | #define SUBSCRIBER_LOG(...) printf("[subscriber]");printf(__VA_ARGS__); 12 | 13 | #define WRITER_NUM (5) 14 | struct subscribe_account { 15 | int type; 16 | publish_msg_detail_t writer; 17 | } writer_list_g[WRITER_NUM]; 18 | 19 | static SubscriberAccount account; 20 | static pthread_t tid; 21 | static int sockpair[2]; 22 | #define READ_SOCK sockpair[0] 23 | #define WRITE_SOCK sockpair[1] 24 | 25 | typedef struct subscriber_msg { 26 | int type; 27 | publish_msg_detail_t detail; 28 | } subscriber_msg_t; 29 | 30 | static int running_g=1; 31 | static void stop_running(void) { 32 | running_g=0; 33 | } 34 | static int is_running() { 35 | return (running_g==1); 36 | } 37 | 38 | static struct subscribe_account * search_writter(subscriber_msg_t *msg) { 39 | int i=0; 40 | for(i = 0; i < WRITER_NUM; i ++) { 41 | if( (msg->type&writer_list_g[i].type) && (memcmp(&writer_list_g[i].writer, &msg->detail, sizeof(msg->detail)) == 0)) { 42 | return &writer_list_g[i]; 43 | } 44 | } 45 | 46 | return NULL; 47 | } 48 | 49 | static void subscriber_msg_action(subscriber_msg_t *msg) { 50 | struct subscribe_account *writter = search_writter(msg); 51 | if(!writter) { 52 | return; 53 | } 54 | 55 | switch(msg->type) { 56 | case PUB_MSG_PUBLISH_NEW_BOOK: 57 | SUBSCRIBER_LOG("Wow, %s's new book release!! I will buy it!\n", msg->detail.writername); 58 | break; 59 | case PUB_MSG_PUBLISH_DISCOUNT_BOOK: 60 | SUBSCRIBER_LOG("Wow, %s's book is discount!! I may be able to buy it!\n", msg->detail.writername); 61 | break; 62 | case PUB_MSG_PUBLISH_STOP_PRODUCTION: 63 | SUBSCRIBER_LOG("Oh..., %s's book production is stopped, ...\n", msg->detail.writername); 64 | publisher_unsubscribe(PUBLISH_ID, account); 65 | account=NULL; 66 | stop_running(); 67 | break; 68 | default: 69 | break; 70 | } 71 | } 72 | 73 | static void * subscriber_main(void *arg) { 74 | 75 | subscriber_msg_t msg; 76 | 77 | fd_set readfds; 78 | FD_ZERO(&readfds); 79 | FD_SET(READ_SOCK, &readfds); 80 | while(is_running()) { 81 | FD_ZERO(&readfds); 82 | FD_SET(READ_SOCK, &readfds); 83 | SUBSCRIBER_LOG("Wait msg...\n"); 84 | if(select(READ_SOCK+1, &readfds, NULL, NULL, NULL) <0 ) { 85 | SUBSCRIBER_LOG("failed to select, %s\n", strerror(errno)); 86 | continue; 87 | } 88 | if (FD_ISSET(READ_SOCK, &readfds)) { 89 | memset(&msg, 0, sizeof(msg)); 90 | int ret = read(READ_SOCK, &msg, sizeof(msg)); 91 | if(ret < 0) { 92 | SUBSCRIBER_LOG("failed to select, %s\n", strerror(errno)); 93 | } 94 | subscriber_msg_action(&msg); 95 | } 96 | } 97 | 98 | close(READ_SOCK); 99 | pthread_exit(NULL); 100 | } 101 | 102 | static void create_socket() { 103 | if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockpair)) { 104 | SUBSCRIBER_LOG("Failed to create socket pair!\n"); 105 | return; 106 | } 107 | 108 | } 109 | void notification(int publish_type, void * defail, void *ctx) { 110 | publish_msg_detail_t *msgdetail = (publish_msg_detail_t *) defail; 111 | subscriber_msg_t msg; 112 | memset(&msg, 0, sizeof(msg)); 113 | msg.type = publish_type; 114 | memcpy(&msg.detail, msgdetail, sizeof(msg.detail)); 115 | int ret = write(WRITE_SOCK, &msg, sizeof(msg)); 116 | if(ret < 0) { 117 | SUBSCRIBER_LOG("...failed to send, errno=%s\n", strerror(errno)); 118 | } 119 | } 120 | 121 | void subscriber_init() { 122 | 123 | account = publisher_subscribe(PUBLISH_ID, PUB_MSG_PUBLISH_NEW_BOOK|PUB_MSG_PUBLISH_STOP_PRODUCTION|PUB_MSG_PUBLISH_DISCOUNT_BOOK, notification, NULL); 124 | 125 | sprintf(writer_list_g[0].writer.writername, "Jeffrey_Deaver"); 126 | writer_list_g[0].type = PUB_MSG_PUBLISH_NEW_BOOK | PUB_MSG_PUBLISH_STOP_PRODUCTION; 127 | SUBSCRIBER_LOG("About \"Jeffrey_Deaver\", I have all books, so only wait new release!\n"); 128 | 129 | sprintf(writer_list_g[1].writer.writername, "Hiroshi_Mori"); 130 | writer_list_g[1].type = PUB_MSG_PUBLISH_NEW_BOOK | PUB_MSG_PUBLISH_DISCOUNT_BOOK | PUB_MSG_PUBLISH_STOP_PRODUCTION; 131 | SUBSCRIBER_LOG("About \"Hiroshi_Mori\", I have almost books, but I can't buy some books.\n"); 132 | SUBSCRIBER_LOG("I have to buy it before stop production!\n"); 133 | 134 | sprintf(writer_list_g[2].writer.writername, "Ryotaro_Shiba"); 135 | writer_list_g[2].type = PUB_MSG_PUBLISH_DISCOUNT_BOOK; 136 | SUBSCRIBER_LOG("About \"Ryotaro_Shiba\", I have no money to buy all his books...\n"); 137 | SUBSCRIBER_LOG("If there are discount, I will buy it.\n"); 138 | 139 | create_socket(); 140 | 141 | pthread_create(&tid, NULL, subscriber_main, NULL); 142 | } 143 | void subscriber_exit() { 144 | //stop thread 145 | stop_running(); 146 | publish_msg_detail_t msg; 147 | notification((0x01<<10), &msg, NULL); 148 | pthread_join(tid, NULL); 149 | 150 | //close socket 151 | close(WRITE_SOCK); 152 | } 153 | -------------------------------------------------------------------------------- /publisher/sample/subscriber.h: -------------------------------------------------------------------------------- 1 | #ifndef SUBSCRIBER_ 2 | #define SUBSCRIBER_ 3 | void subscriber_init(); 4 | void subscriber_exit(); 5 | #endif 6 | -------------------------------------------------------------------------------- /publisher/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/publisher/publisher_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CFLAGS = -g -O0 7 | test_SOURCES = main.c 8 | -------------------------------------------------------------------------------- /state/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib include test 2 | -------------------------------------------------------------------------------- /state/README.md: -------------------------------------------------------------------------------- 1 | # State (StateMachine) 2 | The library for Linux C language to use State pattern. 3 | 4 | # How to use 5 | After build all, please link libstate_manager.so library or libstate_machine.so library. 6 | API header is in state_manager.h/state_machine.h 7 | 8 | Please see wiki "https://github.com/developer-kikikaikai/design_pattern_for_c/wiki/State-and-StateMachine" for more detai. 9 | -------------------------------------------------------------------------------- /state/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = state_machine.h state_manager.h 2 | -------------------------------------------------------------------------------- /state/include/state_machine.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file state_machine.h 3 | * @brief This is API for Sate machine 4 | **/ 5 | #ifndef STATE_MACHINE_H_ 6 | #define STATE_MACHINE_H_ 7 | #include "state_manager.h" 8 | #include "event_threadpool.h" 9 | DP_H_BEGIN 10 | 11 | /*! @struct state_event_info_t 12 | * @brief event ID and related state functions 13 | */ 14 | typedef struct state_event_info_t { 15 | int event;/*!< event event id */ 16 | size_t state_num;/*!< state num*/ 17 | state_info_t *state_infos;/*!< state list, please see state_manager.h defition*/ 18 | } state_event_info_t; 19 | 20 | /*! @struct state_machine_t 21 | * @brief StateMachine class member definition 22 | */ 23 | struct state_machine_t; 24 | /** @brief StateMachine class definition */ 25 | typedef struct state_machine_t *StateMachine; 26 | 27 | typedef struct state_machine_info { 28 | StateMachine state_machine; 29 | int thread_num; 30 | } state_machine_info_t, *StateMachineInfo; 31 | 32 | /** 33 | * @brief Create StateMachineInfo class 34 | * @param[in] event_num event size 35 | * @param[in] event_infos list of event state data 36 | * @param[in] threadpool event threadpool instance by creating event_threadpool API if you want to use state machine in other threads 37 | * @retval !=NULL this class handle 38 | * @retval NULL error 39 | */ 40 | StateMachineInfo state_machine_new(size_t event_num, const state_event_info_t * event_infos, EventTPoolManager threadpool ); 41 | /** 42 | * @brief update sate 43 | * 44 | * @param[in] this StateMachineInfo class instance returned at state_machine_new 45 | * @param[in] event_info update list of event state data. 46 | * @retval STATE_MNG_SUCCESS success 47 | * @retval other failed 48 | */ 49 | int state_machine_update_machine(StateMachineInfo this, const state_event_info_t * event_info); 50 | /** 51 | * @brief set state 52 | * 53 | * @param[in] this StateMachineInfo class instance returned at state_machine_new 54 | * @param[in] state update state, if there is no state in set list, state is changed to latest order. 55 | * @return none 56 | */ 57 | void state_machine_set_state(StateMachineInfo this, int state); 58 | /** 59 | * @brief get state 60 | * 61 | * @param[in] this StateMachineInfo class instance returned at state_machine_new 62 | * @return state 63 | */ 64 | int state_machine_get_current_state(StateMachineInfo this); 65 | /** 66 | * @brief call event trigger 67 | * 68 | * @param[in] this StateMachineInfo class instance returned at state_machine_new 69 | * @param[in] event event id related to this function 70 | * @param[in] arg event argument 71 | * @param[in] arglen event argument len 72 | * @param[in] response response callback method. If you set is_multithread=true , you must set this response callback, 73 | * @retval return_value of method if you set by single thread mode 74 | * @retval STATE_MNG_SUCCESS and result is in callback you set callback if you set by multi thread mode. 75 | */ 76 | int state_machine_call_event(StateMachineInfo this, int event, void *arg, int arglen, void (*response)(int result)); 77 | /** 78 | * @brief set state 79 | * 80 | * @param[in] this StateMachine class instance returned at state_machine_new 81 | * @return none 82 | */ 83 | void state_machine_show(StateMachineInfo this); 84 | /** 85 | * @brief free StateMachine class 86 | * 87 | * @param[in] this StateMachine class instance returned at state_machine_new 88 | * @return none 89 | */ 90 | void state_machine_free(StateMachineInfo this); 91 | DP_H_END 92 | #endif 93 | -------------------------------------------------------------------------------- /state/include/state_manager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file state_manager.h 3 | * @brief This is API for Sate design pattern 4 | **/ 5 | #ifndef STATE_MANAGER_ 6 | #define STATE_MANAGER_ 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | 10 | #define STATE_MNG_SUCCESS (0) 11 | #define STATE_MNG_FAILED (-1) 12 | 13 | /*! @struct state_info_t 14 | * @brief state method definition, to know detail, add parameter "name". It is set by STATE_MNG_SET_INFO_INIT or STATE_MNG_SET_INFO macro. Please use it. 15 | */ 16 | typedef struct state_info_t { 17 | int state;/*! state value related function*/ 18 | char *name;/*! name, function name defined by macro. So please use macro*/ 19 | int (*state_method)(void *arg);/*! state method called at state_manager_call */ 20 | } state_info_t; 21 | 22 | /*! @def STATE_MNG_SET_INFO_INIT 23 | @brief Macro to initialize state_info_t. Please use this macro, It set function name of method, so it support to know definition relationsip of state and function. 24 | */ 25 | #define STATE_MNG_SET_INFO_INIT(instate, fname) {.state=(instate), .name=#fname, .state_method = (fname)} 26 | /*! @def STATE_MNG_SET_INFO 27 | @brief Macro to initialize state_info_t after define state_info_t. Please use this macro, It set function name of method, so it support to know definition relationsip of state and function. 28 | */ 29 | #define STATE_MNG_SET_INFO(info, instate, fname) {(info).state=(instate); (info).name=#fname; (info).state_method = (fname) ; } 30 | 31 | /*! @struct state_manager_t 32 | * @brief StateManager class member definition, detail is defined in C file 33 | */ 34 | struct state_manager_t; 35 | /** @brief StateManager class definition, to management state*/ 36 | typedef struct state_manager_t *StateManager; 37 | 38 | /** 39 | * @brief Create StateManager class 40 | * 41 | * @param[in] state_info_num num of state_info_t, we can set list of state af this API 42 | * @param[in] state state_info pinters, please define state_info_t's in some function, and set this pointer in here. 43 | * this library change state method by state_manager_set_state, and call method when using state_manager_call 44 | * @retval !=NULL this class handle 45 | * @retval NULL error 46 | */ 47 | StateManager state_manager_new(size_t state_info_num, const state_info_t * state); 48 | /** 49 | * @brief update method related to state 50 | * 51 | * @param[in] this StateManager instance returned at state_manager_new, 52 | * @param[in] state info of state. If there is no state, it is add to state list 53 | * @retval STATE_MNG_SUCCESS success 54 | * @retval other failed to add 55 | */ 56 | int state_manager_update_method(StateManager this, const state_info_t * state); 57 | /** 58 | * @brief set state 59 | * 60 | * @param[in] this StateManager instance returned at state_manager_new, 61 | * @param[in] state state, if there is no state in set list, state is changed to latest order. 62 | * @return none 63 | */ 64 | void state_manager_set_state(StateManager this, int state); 65 | /** 66 | * @brief get current state 67 | * 68 | * @param[in] this StateManager instance returned at state_manager_new, 69 | * @return state value or STATE_MNG_FAILED if you don't set state 70 | */ 71 | int state_manager_get_current_state(StateManager this); 72 | /** 73 | * @brief call state method 74 | * 75 | * @param[in] this StateManager instance returned at state_manager_new, 76 | * @param[in] arg argument vakue 77 | * @retval STATE_MNG_FAILED failed 78 | * @retval other return value of state_method 79 | */ 80 | int state_manager_call(StateManager this, void *arg); 81 | /** 82 | * @brief show current state table 83 | * 84 | * @param[in] this StateManager instance returned at state_manager_new, 85 | * @return none 86 | */ 87 | void state_manager_show(StateManager this); 88 | /** 89 | * @brief free StateManager class 90 | * 91 | * @param[in] this StateManager instance returned at state_manager_new, 92 | * @return none 93 | */ 94 | void state_manager_free(StateManager this); 95 | DP_H_END 96 | #endif 97 | -------------------------------------------------------------------------------- /state/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/state/state_am.conf 3 | 4 | lib_LTLIBRARIES = libstate_manager.la libstate_machine.la 5 | 6 | libstate_manager_la_SOURCES = state_manager.c 7 | libstate_manager_la_LDFLAGS=-shared $(top_srcdir)/design_pattern_util/lib/libdputil.la -Xlinker -rpath -Xlinker $(libdir) 8 | libstate_manager_la_LDFLAGS+=-Wl,--version-script,state_manager.map 9 | 10 | libstate_machine_la_SOURCES = state_machine.c 11 | libstate_machine_la_LDFLAGS=-shared libstate_manager.la -Xlinker -rpath -Xlinker $(libdir) 12 | libstate_machine_la_LDFLAGS+= $(THREADPOOL_DIR)/lib/libevent_threadpool.la -Xlinker -rpath -Xlinker $(libdir) 13 | libstate_machine_la_LDFLAGS+= -Wl,--version-script,state_machine.map 14 | -------------------------------------------------------------------------------- /state/lib/state_machine.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | state_machine_new; 4 | state_machine_update_machine; 5 | state_machine_set_state; 6 | state_machine_get_current_state; 7 | state_machine_call_event; 8 | state_machine_show; 9 | state_machine_free; 10 | state_machine_call_event_directry; 11 | local: *; 12 | }; 13 | -------------------------------------------------------------------------------- /state/lib/state_manager.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file state_manager.c 3 | * @brief Implement of State design petten library API, defined in state_manager.h, only care state_manager class 4 | **/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "state_manager.h" 10 | #include "dp_util.h" 11 | 12 | /************* 13 | * public define 14 | *************/ 15 | 16 | /*! @struct state_manager_state_info_t 17 | * @brief state info definition. instance storaged by list 18 | */ 19 | struct state_manager_state_info_t; 20 | typedef struct state_manager_state_info_t * StateManagerStateInfo; 21 | struct state_manager_state_info_t { 22 | StateManagerStateInfo next; 23 | StateManagerStateInfo prev; 24 | state_info_t state; 25 | }; 26 | 27 | /*! @struct state_manager_t 28 | * @brief StateManager instance definition. 29 | */ 30 | struct state_manager_t { 31 | StateManagerStateInfo head; 32 | StateManagerStateInfo tail; 33 | StateManagerStateInfo current_state; 34 | }; 35 | 36 | /*! @name private API for state_manager_t */ 37 | /* @{ */ 38 | /*! Add new state. */ 39 | static int state_manager_add_new_state(StateManager this, const state_info_t * state); 40 | /*! Find state. */ 41 | StateManagerStateInfo state_manager_find_state(StateManager this, int state); 42 | /* @} */ 43 | /************* 44 | * private API 45 | *************/ 46 | static int state_manager_add_new_state(StateManager this, const state_info_t * state) { 47 | /*allocate and copy state info*/ 48 | StateManagerStateInfo state_info=calloc(1, sizeof(*state_info)); 49 | if(!state_info) { 50 | DEBUG_ERRPRINT("allocate state_info error\n"); 51 | return STATE_MNG_FAILED; 52 | } 53 | 54 | memcpy(&state_info->state, state, sizeof(state_info_t)); 55 | /*push to list*/ 56 | dputil_list_push((DPUtilList)this, (DPUtilListData)state_info); 57 | return STATE_MNG_SUCCESS; 58 | } 59 | 60 | StateManagerStateInfo state_manager_find_state(StateManager this, int state) { 61 | StateManagerStateInfo state_info=this->head; 62 | while(state_info) { 63 | if(state_info->state.state == state) { 64 | break; 65 | } 66 | state_info=state_info->next; 67 | } 68 | 69 | return state_info; 70 | } 71 | /************* 72 | * public interface API implement 73 | *************/ 74 | StateManager state_manager_new(size_t state_info_num, const state_info_t * state) { 75 | StateManager instance = calloc(1, sizeof(*instance)); 76 | if( !instance ) { 77 | DEBUG_ERRPRINT("allocate error\n"); 78 | goto err; 79 | } 80 | 81 | /*set state info into manager*/ 82 | size_t i=0; 83 | for( i = 0; i < state_info_num; i ++) { 84 | /*allocate and copy state info*/ 85 | if(state_manager_add_new_state(instance, &state[i]) != STATE_MNG_SUCCESS) { 86 | goto err; 87 | } 88 | } 89 | 90 | return instance; 91 | err: 92 | state_manager_free(instance); 93 | return NULL; 94 | } 95 | 96 | int state_manager_update_method(StateManager this, const state_info_t * state) { 97 | if(!this || !state) { 98 | return STATE_MNG_FAILED; 99 | } 100 | 101 | int ret = STATE_MNG_SUCCESS; 102 | StateManagerStateInfo state_info = state_manager_find_state(this, state->state); 103 | if(state_info) { 104 | memcpy(&state_info->state, state, sizeof(state_info_t)); 105 | } else { 106 | ret = state_manager_add_new_state(this, state); 107 | } 108 | return ret; 109 | } 110 | 111 | void state_manager_set_state(StateManager this, int state) { 112 | if(!this) { 113 | return; 114 | } 115 | this->current_state = state_manager_find_state(this, state); 116 | } 117 | 118 | int state_manager_get_current_state(StateManager this) { 119 | if(!this) { 120 | return STATE_MNG_FAILED; 121 | } 122 | 123 | int current_state = STATE_MNG_FAILED; 124 | if(this->current_state) { 125 | current_state = this->current_state->state.state; 126 | } 127 | return current_state; 128 | } 129 | int state_manager_call(StateManager this, void *arg) { 130 | /*fail safe*/ 131 | if(!this) { 132 | return STATE_MNG_FAILED; 133 | } 134 | 135 | if(!this->current_state) { 136 | DEBUG_ERRPRINT("You don't set state\n"); 137 | return STATE_MNG_FAILED; 138 | } 139 | 140 | int (*state_method)(void *arg) = this->current_state->state.state_method; 141 | return state_method(arg); 142 | } 143 | 144 | void state_manager_show(StateManager this) { 145 | if(!this) { 146 | return; 147 | } 148 | 149 | fprintf(stderr, "-------- Show state table --------\n"); 150 | if(this->current_state) { 151 | fprintf(stderr, "[Current state: %d] [method: %s] \n", this->current_state->state.state, this->current_state->state.name); 152 | } else { 153 | fprintf(stderr, "[Currently no set state]\n"); 154 | } 155 | 156 | StateManagerStateInfo state_info=this->head; 157 | while(state_info) { 158 | fprintf(stderr,"\t[state: %d] [method: %s]\n", state_info->state.state, state_info->state.name); 159 | state_info=state_info->next; 160 | } 161 | fprintf(stderr,"----------------------------------\n"); 162 | 163 | } 164 | 165 | void state_manager_free(StateManager this) { 166 | if(!this) { 167 | return; 168 | } 169 | 170 | StateManagerStateInfo state_info=(StateManagerStateInfo)dputil_list_pop((DPUtilList)this); 171 | while(state_info) { 172 | free(state_info); 173 | state_info=(StateManagerStateInfo)dputil_list_pop((DPUtilList)this); 174 | } 175 | free(this); 176 | } 177 | -------------------------------------------------------------------------------- /state/lib/state_manager.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | state_manager_new; 4 | state_manager_update_method; 5 | state_manager_set_state; 6 | state_manager_get_current_state; 7 | state_manager_call; 8 | state_manager_show; 9 | state_manager_free; 10 | state_machine_new; 11 | state_machine_update_machine; 12 | state_machine_set_state; 13 | state_machine_call_event; 14 | state_machine_show; 15 | state_machine_free; 16 | local: *; 17 | }; 18 | -------------------------------------------------------------------------------- /state/state_am.conf: -------------------------------------------------------------------------------- 1 | #common header deifinition 2 | include $(top_srcdir)/am.conf 3 | 4 | AM_CPPFLAGS+=-I$(STATE_DIR)/include -I$(THREADPOOL_DIR)/include 5 | INCLUDES_PATH+=-I$(STATE_DIR)/include -I$(THREADPOOL_DIR)/include 6 | 7 | AM_LDFLAGS+=$(STATE_DIR)/lib/libstate_machine.la 8 | AM_LDFLAGS+=$(STATE_DIR)/lib/libstate_manager.la 9 | -------------------------------------------------------------------------------- /state/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/state/state_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CFLAGS = -g -O0 7 | test_SOURCES = test_state_manager.c test_state_machine.c main.c 8 | test_LDFLAGS = $(AM_LDFLAGS) $(top_srcdir)/threadpool/lib/libevent_threadpool.la 9 | -------------------------------------------------------------------------------- /state/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "test_state_manager.h" 3 | #include "test_state_machine.h" 4 | 5 | int main(int argc, char *argv[]) { 6 | if(test_state_manager()) { 7 | printf("Failed to test state_manager\n"); 8 | return -1; 9 | } 10 | printf("Success state_manager test!!\n"); 11 | 12 | if(test_state_machine()) { 13 | printf("Failed to test state_machine\n"); 14 | return -1; 15 | } 16 | printf("Success state_machine test!!\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /state/test/test_state_machine.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_STATE_MACHINE_H_ 2 | #define TEST_STATE_MACHINE_H_ 3 | #include "state_machine.h" 4 | int test_state_machine(); 5 | #endif 6 | -------------------------------------------------------------------------------- /state/test/test_state_manager.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_STATE_MANAGER_H_ 2 | #define TEST_STATE_MANAGER_H_ 3 | #include "state_manager.h" 4 | int test_state_manager(); 5 | #endif 6 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # How to test? 2 | 3 | 1. build and install libraries (please see [How to use](https://github.com/developer-kikikaikai/design_pattern_for_c/blob/master/README.md)) 4 | 2. call ./test/testAll.sh 5 | 6 | -------------------------------------------------------------------------------- /test/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | result_check() { 3 | result=`echo "if( $1 > 85.00 ) 1 else 0" | bc` 4 | return ${result} 5 | } 6 | 7 | result=0 8 | #get coverage 9 | LIST=`find . -name lib` 10 | for data in $LIST; 11 | do 12 | cd ${data} 13 | DATA=`ls .libs/*.gcno` 14 | for info in $DATA 15 | do 16 | coverage=`gcov -s . $info | grep "Lines executed" | cut -c 16-20` 17 | result_check $coverage 18 | if [ $? != 1 ]; then 19 | echo "#####test ${data}/$info coverage failed ($coverage %)!! Please check test case" 20 | result=-1 21 | else 22 | echo "${data}/$info coverage is $coverage %!!" 23 | fi 24 | done 25 | cd - > /dev/null 26 | done 27 | 28 | exit 0 29 | -------------------------------------------------------------------------------- /test/coverageResult.sh: -------------------------------------------------------------------------------- 1 | if [ "x$1" != "x" ]; then 2 | grep -3 "#####" $1 3 | else 4 | #check result 5 | find . -name *gcov |xargs grep -3 "#####" 6 | fi 7 | -------------------------------------------------------------------------------- /test/testAll.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #find test name 4 | LIST=`find . -name test | grep -v .libs` 5 | for data in $LIST 6 | do 7 | #skip directory 8 | dircheck=`file $data | awk -F" " '{print $2}'` 9 | if [ "x${dircheck}" = "xdirectory" ]; then 10 | continue; 11 | fi 12 | 13 | basefile=`echo $data | xargs basename` 14 | length=`expr ${#data} - ${#basefile}` 15 | dirname=`echo $data | cut -c 1-${length}` 16 | 17 | cd $dirname 18 | ./$basefile > /dev/null 2>&1 19 | if [ $? != 0 ]; then 20 | echo "test $data failed!!" 21 | exit 1 22 | fi 23 | cd - 24 | echo "===$data Success!!" 25 | done 26 | 27 | exit 0 28 | -------------------------------------------------------------------------------- /threadpool/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib event_if include test 2 | -------------------------------------------------------------------------------- /threadpool/README.md: -------------------------------------------------------------------------------- 1 | # Threadpool 2 | The library for Linux C language to use Threadpool pattern. 3 | All of this thread is used main loop by libevent, so if user add fd with event, create or add new event in thread. 4 | 5 | # How to use 6 | After build all, please link libevent_threadpool.so library. 7 | API header is in event_threadpool.h 8 | 9 | Please see wiki "https://github.com/developer-kikikaikai/design_pattern_for_c/wiki/Threadpool" for more detai. 10 | 11 | # To use full fd 12 | 13 | Please update /etc/sysctl.conf 14 | 15 | ``` 16 | net.ipv4.tcp_max_syn_backlog = 8192 17 | net.core.somaxconn=8192 18 | ``` 19 | 20 | and up /etc/security/limits.conf like 21 | 22 | ``` 23 | * soft nofile 8192 24 | * hard nofile 8192 25 | root soft nofile 8192 26 | root hard nofile 8192 27 | ``` 28 | 29 | # How to check max of fds? 30 | 31 | Please check 32 | 33 | ``` 34 | ulimit -Sn 35 | ``` 36 | -------------------------------------------------------------------------------- /threadpool/event_if/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/state/state_am.conf 3 | 4 | lib_LTLIBRARIES = 5 | 6 | COMMON_LDFLAGS=-shared $(top_srcdir)/design_pattern_util/lib/libdputil.la -Xlinker -rpath -Xlinker $(libdir) -I. 7 | 8 | if TPOOLEVENT_SELECT 9 | lib_LTLIBRARIES += libevent_if_select.la 10 | libevent_if_select_la_SOURCES = event_if_select.c 11 | libevent_if_select_la_LDFLAGS=$(COMMON_LDFLAGS) 12 | endif 13 | 14 | if TPOOLEVENT_LIBEVENT 15 | lib_LTLIBRARIES += libevent_if_libevent.la 16 | libevent_if_libevent_la_SOURCES = event_if_libevent.c 17 | libevent_if_libevent_la_LDFLAGS=$(COMMON_LDFLAGS) -levent 18 | endif 19 | 20 | if TPOOLEVENT_LIBEV 21 | lib_LTLIBRARIES += libevent_if_libev.la 22 | libevent_if_libev_la_SOURCES = event_if_libev.c 23 | libevent_if_libev_la_LDFLAGS=$(COMMON_LDFLAGS) -lev 24 | endif 25 | 26 | if TPOOLEVENT_EPOLL 27 | lib_LTLIBRARIES += libevent_if_epoll.la 28 | libevent_if_epoll_la_SOURCES = event_if_epoll.c 29 | libevent_if_epoll_la_LDFLAGS=$(COMMON_LDFLAGS) 30 | endif 31 | -------------------------------------------------------------------------------- /threadpool/event_if/event_if_epoll.c: -------------------------------------------------------------------------------- 1 | #include "tpool_event_if.h" 2 | #include "dp_debug.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define EVENT_EPOLL_DEFMAX (4096) 9 | //loop to add event 10 | #define EVENT_EPOLL_TIMEOUT (50) 11 | 12 | struct event_epoll_t { 13 | int epfd; 14 | int maxevents; 15 | int curevent_cnt; 16 | int is_stop; 17 | }; 18 | 19 | typedef struct event_epoll_t event_epoll_t, *EventEpoll; 20 | 21 | struct event_epoll_handler_t { 22 | event_subscriber_t subscriber; 23 | void *arg; 24 | }; 25 | typedef struct event_epoll_handler_t event_epoll_handler_t, *EventEpollHandler; 26 | 27 | static inline int convert_etpoll_eveid2own(int eventflag) { 28 | int ret_eveflag=0; 29 | if(eventflag&EV_TPOOL_READ) ret_eveflag |= EPOLLIN; 30 | if(eventflag&EV_TPOOL_WRITE) ret_eveflag |= EPOLLOUT; 31 | if(eventflag&EV_TPOOL_HUNGUP) ret_eveflag |= EPOLLHUP; 32 | return ret_eveflag; 33 | } 34 | 35 | static inline short convert_etpoll_ownid2eve(int eventflag) { 36 | int ret_eveflag=0; 37 | if(eventflag&EPOLLIN) ret_eveflag |= EV_TPOOL_READ; 38 | if(eventflag&EPOLLOUT) ret_eveflag |= EV_TPOOL_WRITE; 39 | if(eventflag&EPOLLHUP) ret_eveflag |= EV_TPOOL_HUNGUP; 40 | return ret_eveflag; 41 | } 42 | 43 | /*! @name API for event if */ 44 | /*@{*/ 45 | /** event new */ 46 | EventInstance event_if_new(void) { 47 | //create main instance 48 | EventEpoll instance = calloc(1,sizeof(*instance)); 49 | if(!instance) return NULL; 50 | 51 | //set member value 52 | instance->maxevents = EVENT_EPOLL_DEFMAX; 53 | instance->epfd = epoll_create(EVENT_EPOLL_DEFMAX); 54 | if(instance->epfd == -1) { 55 | DEBUG_ERRPRINT("Failed to open epoll!\n" ); 56 | instance->epfd=0; 57 | goto err; 58 | } 59 | 60 | return instance; 61 | err: 62 | event_if_free(instance); 63 | return NULL; 64 | } 65 | 66 | /** add new event */ 67 | EventHandler event_if_add(EventInstance this, EventSubscriber subscriber, void *arg) { 68 | 69 | EventEpoll base = (EventEpoll)this; 70 | /*max size reached*/ 71 | if(base->maxevents <= base->curevent_cnt) { 72 | DEBUG_ERRPRINT("#######Oversize of event!\n"); 73 | return NULL; 74 | } 75 | 76 | EventEpollHandler instance = calloc(1, sizeof(*instance)); 77 | if(!instance) { 78 | DEBUG_ERRPRINT("#######calloc error!\n"); 79 | return NULL; 80 | } 81 | 82 | //use subscriber for handler to get fd and delete event 83 | memcpy(&instance->subscriber, subscriber, sizeof(instance->subscriber)); 84 | instance->arg = arg; 85 | 86 | struct epoll_event ev; 87 | ev.events = convert_etpoll_eveid2own(subscriber->eventflag); 88 | ev.data.ptr = instance; 89 | 90 | /*add event*/ 91 | if(epoll_ctl(base->epfd, EPOLL_CTL_ADD, subscriber->fd, &ev) == -1) { 92 | DEBUG_ERRPRINT("Failed to new event! %s\n" , strerror(errno)); 93 | goto err; 94 | } 95 | 96 | base->curevent_cnt++; 97 | 98 | return instance; 99 | err: 100 | free(instance); 101 | return NULL; 102 | } 103 | 104 | /** update registered event */ 105 | void * event_if_update(EventInstance this, EventHandler handler, EventSubscriber subscriber, void *arg) { 106 | EventEpoll base = (EventEpoll)this; 107 | EventEpollHandler instance = (EventEpollHandler) handler; 108 | 109 | /*is different event?*/ 110 | if(instance->subscriber.eventflag != subscriber->eventflag) { 111 | /*update event*/ 112 | struct epoll_event event; 113 | event.events = convert_etpoll_eveid2own(subscriber->eventflag); 114 | event.data.ptr = handler; 115 | if(epoll_ctl(base->epfd, EPOLL_CTL_MOD, subscriber->fd, &event)==-1) { 116 | DEBUG_ERRPRINT("Failed to modify event! %s\n" , strerror(errno)); 117 | } 118 | } 119 | 120 | /*copy subscribe*/ 121 | memcpy(&instance->subscriber, subscriber, sizeof(instance->subscriber)); 122 | instance->arg = arg; 123 | 124 | return handler; 125 | } 126 | 127 | /** delete event */ 128 | void event_if_del(EventInstance this, EventHandler handler) { 129 | EventEpoll base = (EventEpoll)this; 130 | EventEpollHandler instance = (EventEpollHandler) handler; 131 | if(epoll_ctl(base->epfd, EPOLL_CTL_DEL, instance->subscriber.fd, NULL)) { 132 | DEBUG_ERRPRINT("Failed to delete event! %s\n", strerror(errno) ); 133 | } 134 | DEBUG_PRINT("free handle %p!\n", handler ); 135 | free(handler); 136 | base->curevent_cnt--; 137 | } 138 | 139 | int event_if_getfd(EventHandler handler) { 140 | return ((EventEpollHandler)handler)->subscriber.fd; 141 | } 142 | 143 | /** main loop of this event */ 144 | int event_if_loop(EventInstance this) { 145 | EventEpoll base = (EventEpoll)this; 146 | int old_maxevents; 147 | int ret=0; 148 | struct epoll_event *events = malloc(base->maxevents * sizeof(struct epoll_event)); 149 | if(!events) { 150 | return -1; 151 | } 152 | memset(events, 0, base->maxevents * sizeof(struct epoll_event)); 153 | 154 | old_maxevents = base->maxevents; 155 | int cnt=0, i=0, loop=0; 156 | short eventflag; 157 | EventEpollHandler handler; 158 | base->is_stop=0; 159 | while(!base->is_stop) { 160 | loop=0; 161 | memset(events, 0, base->maxevents * sizeof(struct epoll_event)); 162 | cnt = epoll_wait(base->epfd, events, base->maxevents, EVENT_EPOLL_TIMEOUT); 163 | if(cnt<0) { 164 | DEBUG_PRINT("Exit loop!\n" ); 165 | ret = -1; 166 | break; 167 | } 168 | 169 | for(i=0;isubscriber.event_callback(handler->subscriber.fd, eventflag, handler->arg); 175 | } 176 | } 177 | DEBUG_PRINT("exit main\n" ); 178 | 179 | free(events); 180 | return ret; 181 | } 182 | 183 | /** break event */ 184 | void event_if_loopbreak(EventInstance this) { 185 | EventEpoll base = (EventEpoll)this; 186 | base->is_stop=1; 187 | } 188 | 189 | /** exit after main loop */ 190 | void event_if_exit(EventInstance this) { 191 | return; 192 | } 193 | 194 | /** free event if instance */ 195 | void event_if_free(EventInstance this) { 196 | EventEpoll instance = (EventEpoll)this; 197 | if(!instance) return; 198 | if(instance->epfd) close(instance->epfd); 199 | free(instance); 200 | } 201 | /*@}*/ 202 | -------------------------------------------------------------------------------- /threadpool/event_if/event_if_libev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libevent_if_libev plugin for threadpool, used libev (developed Marc Alexander Lehmann) 3 | * 4 | * Redistribution and use in source and binary forms, with or without modifica- 5 | * tion, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, 8 | * this list of conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- 16 | * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- 18 | * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- 22 | * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 23 | * OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * the GNU General Public License ("GPL") version 2 or any later version, 27 | * in which case the provisions of the GPL are applicable instead of 28 | * the above. If you wish to allow the use of your version of this file 29 | * only under the terms of the GPL and not to allow others to use your 30 | * version of this file under the BSD license, indicate your decision 31 | * by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL. If you do not delete the 33 | * provisions above, a recipient may use your version of this file under 34 | * either the BSD or the GPL. 35 | */ 36 | #include "tpool_event_if.h" 37 | #include "dp_util.h" 38 | #include 39 | #include 40 | #include 41 | 42 | struct event_libev_manager_t { 43 | struct ev_loop * loop; 44 | int is_stop; 45 | }; 46 | 47 | typedef struct event_libev_manager_t * EventLibevManager; 48 | 49 | struct event_libev_handler_t { 50 | EventLibevManager base; 51 | void (*event_callback)(int socketfd, int eventflag, void * event_arg); 52 | void *arg; 53 | ev_io watch; 54 | }; 55 | 56 | typedef struct event_libev_handler_t event_libev_handler_t, *EventLibevHandler; 57 | 58 | static inline int convert_etpoll_eveid2own(int eventflag) { 59 | int ret_eveflag=0; 60 | if(eventflag&EV_TPOOL_READ) ret_eveflag |= EV_READ; 61 | if(eventflag&EV_TPOOL_WRITE) ret_eveflag |= EV_WRITE; 62 | if(eventflag&EV_TPOOL_HUNGUP) ret_eveflag |= EV_ERROR; 63 | return ret_eveflag; 64 | } 65 | 66 | static inline int convert_etpoll_own2eveid(int eventflag) { 67 | int ret_eveflag=0; 68 | if(eventflag&EV_READ) ret_eveflag |= EV_TPOOL_READ; 69 | if(eventflag&EV_WRITE) ret_eveflag |= EV_TPOOL_WRITE; 70 | if(eventflag&EV_ERROR) ret_eveflag |= EV_TPOOL_HUNGUP; 71 | return ret_eveflag; 72 | } 73 | 74 | static int event_if_is_stop(EventLibevManager this) { 75 | int is_stop; 76 | is_stop = this->is_stop; 77 | return is_stop; 78 | } 79 | 80 | static void event_if_subscribe_cb(EV_P_ ev_io *w, int revents) { 81 | EventLibevHandler handler = (EventLibevHandler)w->data; 82 | if(event_if_is_stop(handler->base)) return; 83 | 84 | int eventflag = convert_etpoll_own2eveid(revents); 85 | 86 | handler->event_callback(handler->watch.fd, eventflag, handler->arg); 87 | } 88 | 89 | static void event_if_libev_handler_init(EventLibevManager base, EventLibevHandler handler, EventSubscriber subscriber, void *arg) { 90 | handler->base=base; 91 | handler->event_callback = subscriber->event_callback; 92 | handler->arg = arg; 93 | /*initialize watch*/ 94 | ev_io_init(&handler->watch, event_if_subscribe_cb, subscriber->fd, convert_etpoll_eveid2own(subscriber->eventflag)); 95 | /*set user data*/ 96 | handler->watch.data = handler; 97 | 98 | /*start watch*/ 99 | ev_io_start(base->loop, &handler->watch); 100 | } 101 | 102 | /*! @name API for event if */ 103 | /*@{*/ 104 | /** event new */ 105 | EventInstance event_if_new(void) { 106 | EventLibevManager instance = calloc(1, sizeof(*instance)); 107 | if(!instance) return NULL; 108 | 109 | instance->loop = ev_loop_new(0); 110 | if(!instance->loop) goto err; 111 | 112 | return instance; 113 | err: 114 | 115 | free(instance); 116 | return NULL; 117 | } 118 | 119 | /** add new event */ 120 | EventHandler event_if_add(EventInstance this, EventSubscriber subscriber, void *arg) { 121 | 122 | EventLibevManager base = (EventLibevManager)this; 123 | 124 | /*add event*/ 125 | EventLibevHandler handler = calloc(1, sizeof(*handler)); 126 | if(!handler) { 127 | DEBUG_ERRPRINT("Failed to new event!\n" ); 128 | return NULL; 129 | } 130 | 131 | event_if_libev_handler_init(base, handler, subscriber, arg); 132 | return handler; 133 | } 134 | 135 | /** update registered event */ 136 | void * event_if_update(EventInstance this, EventHandler handler, EventSubscriber subscriber, void *arg) { 137 | EventLibevManager base = (EventLibevManager)this; 138 | EventLibevHandler libev_handler = (EventLibevHandler)handler; 139 | if(event_if_is_stop((EventLibevManager)this)) return NULL; 140 | 141 | /*stop first*/ 142 | ev_io_stop(base->loop, &libev_handler->watch); 143 | 144 | /*re-add*/ 145 | event_if_libev_handler_init(base, libev_handler, subscriber, arg); 146 | 147 | return handler; 148 | } 149 | 150 | /** delete event */ 151 | void event_if_del(EventInstance this, EventHandler handler) { 152 | EventLibevManager base = (EventLibevManager)this; 153 | EventLibevHandler libev_handler = (EventLibevHandler) handler; 154 | if(event_if_is_stop((EventLibevManager)this)) return; 155 | 156 | ev_io_stop(base->loop, &libev_handler->watch); 157 | free(libev_handler); 158 | } 159 | 160 | int event_if_getfd(EventHandler handler) { 161 | return ((EventLibevHandler)handler)->watch.fd; 162 | } 163 | 164 | /** main loop to wait event */ 165 | int event_if_loop(EventInstance this) { 166 | EventLibevManager base = (EventLibevManager) this; 167 | ev_loop (base->loop, 0); 168 | return 0; 169 | } 170 | 171 | /** break event */ 172 | void event_if_loopbreak(EventInstance this) { 173 | EventLibevManager base = (EventLibevManager) this; 174 | base->is_stop = 1; 175 | ev_unloop (base->loop, EVUNLOOP_ONE); 176 | } 177 | 178 | /** exit after main loop */ 179 | void event_if_exit(EventInstance this) { 180 | EventLibevManager base = (EventLibevManager)this; 181 | ev_loop_destroy(base->loop); 182 | } 183 | 184 | /** free event if instance */ 185 | void event_if_free(EventInstance this) { 186 | EventLibevManager base = (EventLibevManager)this; 187 | free(base); 188 | } 189 | /*@}*/ 190 | -------------------------------------------------------------------------------- /threadpool/event_if/event_if_libevent.c: -------------------------------------------------------------------------------- 1 | #include "tpool_event_if.h" 2 | #include "dp_debug.h" 3 | #include 4 | #include 5 | 6 | struct event_libevent_handler_t { 7 | event_subscriber_t subscriber; 8 | void *arg; 9 | struct event * event; 10 | }; 11 | 12 | typedef struct event_libevent_handler_t event_libevent_handler_t, *EventLibeventHandler; 13 | 14 | static inline short convert_etpoll_eveid2own(int eventflag) { 15 | short ret_eveflag=EV_PERSIST; 16 | if(eventflag&EV_TPOOL_READ) ret_eveflag |= EV_READ; 17 | if(eventflag&EV_TPOOL_WRITE) ret_eveflag |= EV_WRITE; 18 | #ifdef EV_CLOSED 19 | if(eventflag&EV_TPOOL_HUNGUP) ret_eveflag |= EV_CLOSED; 20 | #endif 21 | return ret_eveflag; 22 | } 23 | 24 | static inline int convert_etpoll_own2eveid(short eventflag) { 25 | int ret_eveflag=0; 26 | if(eventflag&EV_READ) ret_eveflag |= EV_TPOOL_READ; 27 | if(eventflag&EV_WRITE) ret_eveflag |= EV_TPOOL_WRITE; 28 | #ifdef EV_CLOSED 29 | if(eventflag&EV_CLOSED) ret_eveflag |= EV_TPOOL_HUNGUP; 30 | #endif 31 | return ret_eveflag; 32 | } 33 | 34 | static void event_if_libevent_callback(evutil_socket_t fd, short eventflag, void * arg) { 35 | EventLibeventHandler instance = (EventLibeventHandler)arg; 36 | int eflag = convert_etpoll_own2eveid(eventflag); 37 | instance->subscriber.event_callback(fd, eflag, instance->arg); 38 | } 39 | 40 | /*! @name API for event if */ 41 | /*@{*/ 42 | /** event new */ 43 | EventInstance event_if_new(void) { 44 | return event_base_new(); 45 | } 46 | 47 | /** add new event */ 48 | EventHandler event_if_add(EventInstance this, EventSubscriber subscriber, void *arg) { 49 | 50 | struct event_base * base = (struct event_base *)this; 51 | 52 | /*add event*/ 53 | EventLibeventHandler instance = (EventLibeventHandler)calloc(1, sizeof(*instance)); 54 | if(!instance) return NULL; 55 | 56 | memcpy(&instance->subscriber, subscriber, sizeof(instance->subscriber)); 57 | instance->arg = arg; 58 | instance->event = event_new(base, subscriber->fd, convert_etpoll_eveid2own(subscriber->eventflag), event_if_libevent_callback, instance); 59 | if(!instance->event) { 60 | DEBUG_ERRPRINT("Failed to new event!\n" ); 61 | goto err; 62 | } 63 | 64 | if(event_add(instance->event, NULL) == -1) { 65 | DEBUG_ERRPRINT("Failed to add event!\n" ); 66 | goto err; 67 | } 68 | 69 | return instance; 70 | err: 71 | if(instance->event) event_free(instance->event); 72 | free(instance); 73 | return NULL; 74 | } 75 | 76 | /** update registered event */ 77 | void * event_if_update(EventInstance this, EventHandler handler, EventSubscriber subscriber, void *arg) { 78 | struct event_base * event_base = (struct event_base *)this; 79 | EventLibeventHandler eventinfo = (EventLibeventHandler)handler; 80 | 81 | /*delete and add to update*/ 82 | event_if_del(event_base, eventinfo); 83 | eventinfo = event_if_add(this, subscriber, arg); 84 | 85 | #if 0 86 | /*This function support after 2.1.2-alpha*/ 87 | /*restart loop and reload settings*/ 88 | event_base_loopcontinue(event_base); 89 | #endif 90 | return eventinfo; 91 | } 92 | 93 | /** delete event */ 94 | void event_if_del(EventInstance this, EventHandler handler) { 95 | EventLibeventHandler instance = (EventLibeventHandler)handler; 96 | event_del(instance->event); 97 | event_free(instance->event); 98 | free(instance); 99 | } 100 | 101 | int event_if_getfd(EventHandler handler) { 102 | EventLibeventHandler instance = (EventLibeventHandler)handler; 103 | return event_get_fd(instance->event); 104 | } 105 | 106 | /** main loop of this event */ 107 | int event_if_loop(EventInstance this) { 108 | event_base_dispatch((struct event_base *)this); 109 | return 0; 110 | } 111 | 112 | /** break event */ 113 | void event_if_loopbreak(EventInstance this) { 114 | event_base_loopbreak((struct event_base *)this); 115 | } 116 | 117 | /** exit after main loop */ 118 | void event_if_exit(EventInstance this) { 119 | struct event_base * base = (struct event_base *)this; 120 | if(event_base_got_break(base)) { 121 | event_base_loopbreak(base); 122 | } 123 | } 124 | 125 | /** free event if instance */ 126 | void event_if_free(EventInstance this) { 127 | event_base_free((struct event_base *)this); 128 | } 129 | /*@}*/ 130 | -------------------------------------------------------------------------------- /threadpool/include/Makefile.am: -------------------------------------------------------------------------------- 1 | include_HEADERS = event_threadpool_data.h event_threadpool.h tpool_event_if.h 2 | -------------------------------------------------------------------------------- /threadpool/include/event_threadpool.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file event_threadpool.h 3 | * This is API as ThreadPool design petten by using libevent 4 | **/ 5 | #ifndef EVENT_THREADPOOL_H_ 6 | #define EVENT_THREADPOOL_H_ 7 | #include "event_threadpool_data.h" 8 | #include "dp_define.h" 9 | DP_H_BEGIN 10 | 11 | /*! @name API for EventTPoolManager instance */ 12 | /*@{*/ 13 | /** 14 | * new EventTPoolManager 15 | * @param[in] thread_num size of thread. If this is negative value, this library set thread CPU number * 2 16 | * @param[in] is_threadsafe if you use this instance in multi thread, please set 1. 17 | * @param[in] plugin_path if you want to choose plugin. Default : choose higher priority plugin from prefix 18 | * @retval !=NULL this class handle 19 | * @retval NULL error 20 | * @note when call it, start thread which has event_base struct. Those threads pool event fd, and call event function. 21 | */ 22 | EventTPoolManager event_tpool_manager_new(int thread_num, int is_threadsafe, const char * plugin_path); 23 | /** 24 | * destructor of EventTPoolManager 25 | * @param[in] this EventTPoolManager instance returned at event_tpool_new. 26 | * @note when call it, stop all threads. 27 | */ 28 | void event_tpool_manager_free(EventTPoolManager this); 29 | /** 30 | * get size of thread 31 | * @param[in] this EventTPoolManager instance returned at event_tpool_new. 32 | * @retval size of thread 33 | * @retval -1 error 34 | */ 35 | size_t event_tpool_manager_get_threadnum(EventTPoolManager this); 36 | /*@}*/ 37 | 38 | /*! @name API for EventThreadPool */ 39 | /*@{*/ 40 | /** 41 | * add EventSubscriber to threadpool 42 | * @param[in] this EventTPoolManager instance returned at event_tpool_new. 43 | * @param[in] subscriber EventSubscriber 44 | * @param[in] arg argument for event_callback 45 | * @retval result: thread number (0-thread_num-1) which subscriber added, event_handle is used for update 46 | * @retval result: <0 error (no resource, or if a same fd's subscriber was already registred) 47 | * @note if there already exist same fd's subscriber, it occur error 48 | */ 49 | event_tpool_add_result_t event_tpool_add(EventTPoolManager this, EventSubscriber subscriber, void * arg); 50 | /** 51 | * add EventSubscriber to threadpool, if you want to choose thead, please use it. 52 | * @param[in] this EventTPoolManager instance returned at event_tpool_new. 53 | * @param[in] threadid thread id (0-thread_num-1) 54 | * @param[in] subscriber EventSubscriber 55 | * @param[in] arg argument for event_callback 56 | * @retval result: thread number (0-thread_num-1) which subscriber added, event_handle is used for update 57 | * @retval result: <0 error (no resource, or if a same fd's subscriber was already registred) 58 | * @note if there already exist same fd's subscriber, it occur error 59 | */ 60 | event_tpool_add_result_t event_tpool_add_thread(EventTPoolManager this, int threadid, EventSubscriber subscriber, void * arg); 61 | /** 62 | * update EventSubscriber to threadpool. if you want to choose thead, please use it. 63 | * @param[in] this EventTPoolManager instance returned at event_tpool_new. 64 | * @param[in] event_handle handler of event returned at event_tpool_add/event_tpool_add_thread 65 | * @param[in] subscriber EventSubscriber 66 | * @param[in] arg argument for event_callback 67 | * @retval result: thread number (0-thread_num-1) which subscriber added 68 | * @retval result: <0 error (no resource, or if a same fd's subscriber was already registred) 69 | * @note if there already exist same fd's subscriber, it will override 70 | * @note this API doesn't remove other thread's same fd setting. 71 | * @note handle will update 72 | */ 73 | event_tpool_add_result_t event_tpool_update(EventTPoolManager this, EventTPoolThreadInfo event_handle, EventSubscriber subscriber, void * arg); 74 | /** 75 | * delete EventSubscriber to threadapool. 76 | * @param[in] this EventTPoolManager instance returned at event_tpool_new. 77 | * @param[in] fd removed fd (related to subscriber) 78 | * @return none 79 | * @note this API doesn't close fd, please close ownself. 80 | */ 81 | void event_tpool_del(EventTPoolManager this, int fd); 82 | 83 | /** 84 | * Update member at fork, please call this API on child process if you use fork 85 | * @param[in] this EventTPoolManager instance returned at event_tpool_new. 86 | * @note Please care "The child process is created with a single thread--the one that called fork()." 87 | * at the child process, all of pooled threads don't copy. 88 | */ 89 | void event_tpool_atfork_child(EventTPoolManager this); 90 | 91 | /** 92 | * Set thread stack size. Default is 256 KByte. 93 | * @param[in] stack_size stack size. 94 | * @note Please call it before calling event_tpool_manager_new. 95 | */ 96 | void event_tpool_set_stack_size(size_t stack_size); 97 | /*@}*/ 98 | DP_H_END 99 | #endif 100 | -------------------------------------------------------------------------------- /threadpool/include/event_threadpool_data.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file event_threadpool_data.h 3 | * This is API as ThreadPool data definition for ThreadPooldesign petten by using libevent 4 | **/ 5 | #ifndef EVENT_THREADPOOL_DATA_H_ 6 | #define EVENT_THREADPOOL_DATA_H_ 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | 10 | /*! @name Used class name definition.*/ 11 | /*@{*/ 12 | /*! @struct event_tpool_manager_t 13 | * EventTPoolManager class instance definition, member is defined in event_tpool_manager.c. 14 | */ 15 | struct event_tpool_manager_t; 16 | /** EventTPoolManager class definition */ 17 | typedef struct event_tpool_manager_t * EventTPoolManager; 18 | 19 | 20 | #define EV_TPOOL_READ (0x01<<0) 21 | #define EV_TPOOL_WRITE (0x01<<1) 22 | #define EV_TPOOL_HUNGUP (0x01<<2) 23 | 24 | /*! @struct event_subscriber_t 25 | * EventSubscriber class instance definition, this is storaged in any threads. 26 | */ 27 | struct event_subscriber_t { 28 | int fd;/*!< file descripter of this subscriber */ 29 | int eventflag;/**< OR value of EV_TPOOL_XXX definition*/ 30 | void (*event_callback)(int socketfd, int eventflag, void * event_arg); 31 | }; 32 | 33 | /** EventSubscriber class definition */ 34 | typedef struct event_subscriber_t event_subscriber_t, * EventSubscriber; 35 | 36 | /*! @struct event_tpool_fd_data_t 37 | * added event handler class instance definition 38 | */ 39 | struct event_tpool_thread_info_t; 40 | typedef struct event_tpool_thread_info_t * EventTPoolThreadInfo; 41 | 42 | /** add result definition */ 43 | struct event_tpool_add_result_t { 44 | int result; 45 | EventTPoolThreadInfo event_handle; 46 | }; 47 | 48 | typedef struct event_tpool_add_result_t event_tpool_add_result_t; 49 | 50 | DP_H_END 51 | /*@}*/ 52 | #endif 53 | -------------------------------------------------------------------------------- /threadpool/include/tpool_event_if.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file event_if.h 3 | * This is API definition for event wrapper plugin. Threadpool loads this plugin. 4 | **/ 5 | #ifndef TPOOL_EVENT_IF_H_ 6 | #define TPOOL_EVENT_IF_H_ 7 | #include "dp_define.h" 8 | DP_H_BEGIN 9 | 10 | #include "event_threadpool_data.h" 11 | 12 | /*! @name event instance definition*/ 13 | /*@{*/ 14 | /*! Event management instance which get from event_if_new. Definition is in plugin */ 15 | typedef void * EventInstance; 16 | /*! Event handler related to fd. Definition is in plugin */ 17 | typedef void * EventHandler; 18 | /*@}*/ 19 | 20 | /*! @name API for event if plugin interface*/ 21 | /*@{*/ 22 | 23 | /** 24 | * new event instance 25 | * @param[in] none 26 | * @retval !=NULL this class handle 27 | * @retval NULL error 28 | * @note when call it, stop all threads. 29 | */ 30 | EventInstance event_if_new(void); 31 | /** 32 | * add event handler related to fd 33 | * @param[in] this EventInstance instance returned at event_if_new. 34 | * @param[in] subscriber EventSubscriber 35 | * @param[in] arg argument for event_callback 36 | * @retval !=NULL event handler instance 37 | * @retval NULL error 38 | */ 39 | EventHandler event_if_add(EventInstance this, EventSubscriber subscriber, void *arg); 40 | /** 41 | * update event handler related to fd 42 | * @param[in] this EventInstance instance returned at event_if_new. 43 | * @param[in] handler EventHandler instance returned at event_if_add. 44 | * @param[in] subscriber EventSubscriber 45 | * @param[in] arg argument for event_callback 46 | * @retval !=NULL new event handler instance 47 | * @retval NULL error 48 | */ 49 | EventHandler event_if_update(EventInstance this, EventHandler handler, EventSubscriber subscriber, void *arg); 50 | /** 51 | * delete event handler related to fd 52 | * @param[in] this EventInstance instance returned at event_if_new. 53 | * @param[in] handler EventHandler instance returned at event_if_add. 54 | * @return none 55 | */ 56 | void event_if_del(EventInstance this, EventHandler handler); 57 | /** 58 | * get fd related to handler 59 | * @param[in] handler EventHandler instance returned at event_if_add. 60 | * @return fd 61 | */ 62 | int event_if_getfd(EventHandler handler); 63 | /** 64 | * main loop, start to watch event 65 | * @param[in] this EventInstance instance returned at event_if_new. 66 | * @retval 0 Normally stop 67 | * @retval !=0 Error stop 68 | * @note this API brock thread as select, etc 69 | */ 70 | int event_if_loop(EventInstance this); 71 | /** 72 | * break main loop 73 | * @param[in] this EventInstance instance returned at event_if_new. 74 | * @return none 75 | */ 76 | void event_if_loopbreak(EventInstance this); 77 | /** 78 | * exit instances for loop, if plugin want. 79 | * @param[in] this EventInstance instance returned at event_if_new. 80 | * @return none 81 | */ 82 | void event_if_exit(EventInstance this); 83 | /** 84 | * free instances 85 | * @param[in] this EventInstance instance returned at event_if_new. 86 | * @return none 87 | */ 88 | void event_if_free(EventInstance this); 89 | /*@}*/ 90 | DP_H_END 91 | #endif 92 | -------------------------------------------------------------------------------- /threadpool/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/threadpool/threadpool_am.conf 3 | 4 | lib_LTLIBRARIES = libevent_threadpool.la 5 | 6 | libevent_threadpool_la_SOURCES = event_tpool_manager.c event_thread.c 7 | 8 | libevent_threadpool_la_LDFLAGS=-shared $(DPUTIL_DIR)/lib/libdputil.la -Xlinker -rpath -Xlinker $(libdir) 9 | libevent_threadpool_la_LDFLAGS+=-Wl,--version-script,threadpool.map 10 | -------------------------------------------------------------------------------- /threadpool/lib/event_thread.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file event_thread.h 3 | * This is API of event thread 4 | **/ 5 | #ifndef EVENT_THREAD_H_ 6 | #define EVENT_THREAD_H_ 7 | #include "event_threadpool_data.h" 8 | #include "pthread.h" 9 | 10 | /*! @name msg definition */ 11 | /*@{*/ 12 | struct event_tpool_thread_t; 13 | typedef struct event_tpool_thread_t event_tpool_thread_t, * EventTPoolThread; 14 | /*@}*/ 15 | 16 | /*! @name API for thread */ 17 | /*@{*/ 18 | /** create and thread instance */ 19 | EventTPoolThread event_tpool_thread_new(size_t thread_size); 20 | /** start thread */ 21 | void event_tpool_thread_start(EventTPoolThread this); 22 | /** stop thread, and remove resource*/ 23 | void event_tpool_thread_stop(EventTPoolThread this); 24 | /** add new subscriber */ 25 | void event_tpool_thread_add(EventTPoolThread this, EventSubscriber subscriber, void * arg); 26 | /** update subscriber */ 27 | void event_tpool_thread_update(EventTPoolThread this, EventSubscriber subscriber, void * arg); 28 | /** delete subscriber */ 29 | void event_tpool_thread_del(EventTPoolThread this, int fd); 30 | 31 | void event_thread_atfork_child(EventTPoolThread this); 32 | 33 | void event_thread_set_stack_size(size_t stack_size); 34 | 35 | int event_tpool_thread_load_plugin(const char *plugin_path); 36 | void event_tpool_thread_unload_plugin(void); 37 | /*@}*/ 38 | #endif 39 | -------------------------------------------------------------------------------- /threadpool/lib/threadpool.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | event_tpool_manager_new; 4 | event_tpool_manager_free; 5 | event_tpool_manager_get_threadnum; 6 | event_tpool_add; 7 | event_tpool_add_thread; 8 | event_tpool_update; 9 | event_tpool_del; 10 | event_tpool_atfork_child; 11 | event_tpool_set_stack_size; 12 | local: *; 13 | }; 14 | -------------------------------------------------------------------------------- /threadpool/test/Makefile.am: -------------------------------------------------------------------------------- 1 | #load common setting 2 | include $(top_srcdir)/threadpool/threadpool_am.conf 3 | 4 | noinst_PROGRAMS = test 5 | 6 | test_CFLAGS = -g -O0 7 | 8 | #Set define option related to event select 9 | if TPOOLEVENT_SELECT 10 | test_CFLAGS += -DTPOOLEVENT_SELECT 11 | endif 12 | if TPOOLEVENT_LIBEVENT 13 | test_CFLAGS += -DTPOOLEVENT_LIBEVENT 14 | endif 15 | if TPOOLEVENT_LIBEV 16 | test_CFLAGS += -DTPOOLEVENT_LIBEV 17 | endif 18 | if TPOOLEVENT_EPOLL 19 | test_CFLAGS += -DTPOOLEVENT_EPOLL 20 | endif 21 | 22 | 23 | test_SOURCES = test_main.c main.c 24 | test_LDFLAGS=${AM_LDFLAGS} $(DPUTIL_DIR)/lib/libdputil.la -Xlinker -rpath -Xlinker $(libdir) 25 | -------------------------------------------------------------------------------- /threadpool/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "config.h" 3 | #include "test_main.h" 4 | 5 | int main(int argc, char *argv[]) { 6 | DPDEBUG_INIT_THREADSAFE 7 | static const char * pluginlist[] = { 8 | #ifdef TPOOLEVENT_LIBEV 9 | EVENT_IF_PLUGIN_PATH"/libevent_if_libev.so", 10 | #endif 11 | #ifdef TPOOLEVENT_LIBEVENT 12 | EVENT_IF_PLUGIN_PATH"/libevent_if_libevent.so", 13 | #endif 14 | #ifdef TPOOLEVENT_EPOLL 15 | EVENT_IF_PLUGIN_PATH"/libevent_if_epoll.so", 16 | #endif 17 | #ifdef TPOOLEVENT_SELECT 18 | EVENT_IF_PLUGIN_PATH"/libevent_if_select.so", 19 | #endif 20 | NULL, 21 | }; 22 | 23 | size_t i=0; 24 | for(i = 0; i < sizeof(pluginlist)/sizeof(pluginlist[0]); i++) { 25 | if(test_main(pluginlist[i])) { 26 | DEBUG_ERRPRINT("####plugin %s error!!\n", (pluginlist[i]==NULL)?"Default":pluginlist[i]); 27 | return -1; 28 | } 29 | } 30 | printf("Succecc to all test!!!\n"); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /threadpool/test/test_main.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_MAIN_H 2 | #define TEST_MAIN_H 3 | #include 4 | #include 5 | #include "dp_debug.h" 6 | int test_main(const char * plugin); 7 | #endif 8 | -------------------------------------------------------------------------------- /threadpool/threadpool_am.conf: -------------------------------------------------------------------------------- 1 | #common header deifinition 2 | include $(top_srcdir)/am.conf 3 | 4 | AM_CPPFLAGS+=-I$(THREADPOOL_DIR)/include 5 | INCLUDES_PATH+=$(THREADPOOL_DIR)/include 6 | 7 | AM_LDFLAGS+=$(THREADPOOL_DIR)/lib/libevent_threadpool.la 8 | --------------------------------------------------------------------------------