西安市网站建设,360排名优化工具,焦作做微信网站多少钱,网站运营优化方案C语言的C库提供了策略的更新、加载与同步的方法#xff0c;这里引入多线程#xff0c;达到区分读写任务#xff08;生产者——消费者 模型#xff09;的目的。 示例#xff1a;
/*brief check strategy to update, reload, synchronized to read(stoped by SIGINT)author… C语言的C库提供了策略的更新、加载与同步的方法这里引入多线程达到区分读写任务生产者——消费者 模型的目的。 示例
/*brief check strategy to update, reload, synchronized to read(stoped by SIGINT)author wenxuanpeiemail 15873152445163.com(query for any question here)
*/
#include pthread.h//pthread_(create|exit), pthread_rwlock_(init|destroy|wrlock|rdlock|unlock),
#include unistd.h//sleep,
#include errno.h//cerrno//errno,
//stat
#include sys/types.h
#include sys/stat.h
#include signal.h//csignal//sig_atomic_t,signal, SIG.,
#include stdio.h//cstdio//fopen/fclose,perror,fread/fwrite,size_t,NULL,printf,
#include stdlib.h//cstdlib//abort,calloc,free,
#include string.h//cstring//memset,strlen,
#include time.h//ctime//time_t,/*define and select a strategy file type here*/
#define FORMAT_UNKNOWN (0)
#define FORMAT_XML (1)
#define FORMAT_JSON (2)
#define FORMAT_INI (3)
#if 0
# define STRATEGY_FORMAT FORMAT_XML
#elif 0
# define STRATEGY_FORMAT FORMAT_JSON
#elif 1
# define STRATEGY_FORMAT FORMAT_INI
#else
# define STRATEGY_FORMAT FORMAT_UNKNOWN
#endif
/*auto concate for strategy file path*/
#define concate(x, y) x y//
#if STRATEGY_FORMAT FORMAT_XML
# define STRATEGY_SUFFIX .xml
#elif STRATEGY_FORMAT FORMAT_JSON
# define STRATEGY_SUFFIX .json
#elif STRATEGY_FORMAT FORMAT_INI
# define STRATEGY_SUFFIX .ini
#else//FORMAT_UNKNOWN
# define STRATEGY_SUFFIX .txt
#endif
#define STRATEGY_FILE concate(/tmp/strategy, STRATEGY_SUFFIX)
#define STRATEGY_FILE_MAX_SIZE _IO_BUFSIZ
#define thread_failed(s, msg) \
do{ \errno s, perror(msg); \abort(); \
}while(0)/*to stop the update-thread and main-thread:by user signal SIGINTnotice:to keep data consistence of thread access, dont optmize to cache */
static volatile int stop 0;
static void handle_exception(sig_atomic_t sig){signal(sig, SIG_IGN);stop 1;
}
/*exception protection:shadow other signals except SIGINT(SIGKILL,SIGSTOP is special)*/
static void shadow_exception(){sig_atomic_t sig;for(sig 1; sig 64; sig){if(sig SIGINT)continue;if(sig 31 sig 34)continue;signal(sig, SIG_IGN);}
}/*to load and update strategy file:by the latest update time(content modification or fresh time only)*/
static time_t latestUpdate;
/*to minimized lock conflict:split reader and writer*/
static pthread_rwlock_t rwLock;
/*to keep integrity of strategy file data:by lock and swap pointer(minimized lock conflict)*/
static char *strategyContent/* NULL */;
static char *strategyContentBak/* NULL */;
/*to make more concurrency of reader, copy a strategy self, use it without lock conflict*/
static char *strategyContentCopy/* NULL*/;//improve performance(for reader)
/*brief swap for any type of pointerparama: pointer1(the length is the same as size_t)b: pointer2(the length is the same as size_t)problem solved(user may be interested in it)convert failed for rvalue(expression) cant be write:(size_t)strategyContent ^ (size_t)strategyContentBakso, write as follows:get address convert address type dereference(access momory forcely)*(size_t*)strategyContent ^ *(size_t*)strategyContentBak;
*/
#define swap_pointer(a, b) _swap_pointer((size_t*)a, (size_t*)b)//wrapper for use it easily!!!
static void _swap_pointer(register size_t *a, register size_t *b){*a ^ *b;*b ^ *a;*a ^ *b;
}
/*swap strategy file buffer*/
static void swap(){int s;if( (s pthread_rwlock_wrlock(rwLock)) )thread_failed(s, pthread_rwlock_wrlock);
#ifndef NDEBUG/*for view of debug*/printf(\nuser update the strategy file now!\n);
#endifswap_pointer(strategyContent, strategyContentBak);pthread_rwlock_unlock(rwLock);
}
/*reload and update strategy file*/
static void reload(time_t currentUpdate){FILE *fp NULL;latestUpdate currentUpdate;if( (fp fopen(STRATEGY_FILE, r)) ){memset(strategyContentBak, 0, sizeof(char) * STRATEGY_FILE_MAX_SIZE);//keep clean for textfread(strategyContentBak, sizeof(char), STRATEGY_FILE_MAX_SIZE, fp);fclose(fp), fp NULL;swap();}else{perror(fopen);abort();}
}
/*update-thread:check if file is freshed, then reloadexcecption protection:after remove strategy file */
static void *update(void* args){struct stat fbuf;time_t currentUpdate 0;while(!stop){if(-1 stat(STRATEGY_FILE, fbuf) ){perror(stat);//to get position, __FILE__,__FUNCTION__,__LINE__ may be usedgoto __next_round;//avoid fresh the screen frequently}currentUpdate fbuf.st_mtime;if(currentUpdate latestUpdate)reload(currentUpdate);
__next_round:sleep(4);}
#ifndef NDEBUG/*for view of debug*/printf(\nupdate-thread exit now!\n);
#endifpthread_exit(NULL);
}/*allocate and deallocate for system resource*/
static char hasInit/* 0*/;
static void init(){int s;pthread_t tid;signal(SIGINT, handle_exception);if( (s pthread_create(tid, NULL, update, NULL)))thread_failed(s, pthread_create);if( (s pthread_rwlock_init(rwLock, NULL)) )thread_failed(s, pthread_rwlock_init);if( !(strategyContent calloc(sizeof(char), STRATEGY_FILE_MAX_SIZE) ) ){perror(calloc);abort();}if( !(strategyContentBak calloc(sizeof(char), STRATEGY_FILE_MAX_SIZE) ) ){perror(calloc);abort();}if( !(strategyContentCopy calloc(sizeof(char), STRATEGY_FILE_MAX_SIZE) ) ){perror(calloc);abort();}hasInit 1;
}
static void destroy(){if(hasInit){pthread_rwlock_destroy(rwLock);free(strategyContent), strategyContent NULL;free(strategyContentBak), strategyContentBak NULL;free(strategyContentCopy), strategyContentCopy NULL;}
}/*compatible for multi-thread shared read:read and use the strategy file*/
static int readCount/* 0 */;
static void read_use(){int s;if( (s pthread_rwlock_rdlock(rwLock)) )thread_failed(s, pthread_rwlock_rdlock);memcpy(strategyContentCopy, strategyContent, STRATEGY_FILE_MAX_SIZE * sizeof(char));pthread_rwlock_unlock(rwLock);printf(\n%dth read strategyContent:\n, readCount);//CLIfwrite(strategyContent, sizeof(char), strlen(strategyContent), stdout);
}/*prepare strategy file for test*/
static void prepare(){
#if STRATEGY_FORMAT FORMAT_XML//.xmlsystem(echo \?xml version\\\1.0\\\ encoding\\\utf-8\\\?\ STRATEGY_FILE ;echo \root\ STRATEGY_FILE ;echo \\tstrategy\ STRATEGY_FILE ;echo \\t\tperson\ STRATEGY_FILE ;echo \\t\t\tnamejohn/name\ STRATEGY_FILE ;echo \\t\t\tage18/age\ STRATEGY_FILE ;echo \\t\t\tweight61.38kg/weight\ STRATEGY_FILE ;echo \\t\t\tmarriedfalse/married\ STRATEGY_FILE ;echo \\t\t/person\ STRATEGY_FILE ;echo \\t/strategy\ STRATEGY_FILE ;echo \/root\ STRATEGY_FILE );
#elif STRATEGY_FORMAT FORMAT_JSON//.jsonsystem(echo \{\ STRATEGY_FILE ;echo \\t\\\strategy\\\:{\ STRATEGY_FILE ;echo \\t\t\\\person\\\:{\ STRATEGY_FILE ;echo \\t\t\t\\\name\\\:\\\john\\\,\ STRATEGY_FILE ;echo \\t\t\t\\\age\\\:\\\18\\\,\ STRATEGY_FILE ;echo \\t\t\t\\\weight\\\:\\\61.38kg\\\,\ STRATEGY_FILE ;echo \\t\t\t\\\married\\\:\\\false\\\\ STRATEGY_FILE ;echo \\t\t}\ STRATEGY_FILE ;echo \\t}\ STRATEGY_FILE ;echo \}\ STRATEGY_FILE);
#elif STRATEGY_FORMAT FORMAT_INI//.inisystem(echo \[strategy]\ STRATEGY_FILE ;echo \id 1234567890#\ STRATEGY_FILE ;echo \name john#\ STRATEGY_FILE ;echo \age 18#\ STRATEGY_FILE ;echo \weight 61.38kg#\ STRATEGY_FILE ;echo \marriedfalse#\ STRATEGY_FILE);
#else//.txtsystem(touch STRATEGY_FILE);
#endif
}/*main frame here*/
int main(){shadow_exception();prepare();init();while(!stop){sleep(2);read_use();}
#ifndef NDEBUG/*for view of debug*/printf(\nmain-thread waitting to collect resource ... \n);sleep(10);
#endifdestroy();return 0;
} 小结
1可以使用异步信号通知的方式保持访问标志变量的一致性 将更新线程与主线程停下来
2通过最后一次修改时间与上一次做比对来确定配置文件是否有更新在同步更新时要注意清理上一次配置文件的内容 并 保持本次配置文件的完整性
3读时共享写时互斥(w-w,w-r), 区分writer与reader, 让需要配置的多线程最大程度并发同时将需要同步竞争的数据拷贝来进一步提高reader并发量
4更新配置文件一般是比较轻松的任务可以最大限度让出CPU给系统其它任务使用
提示实际开发当中配置文件会比较复杂与业务逻辑强相关常见的有XML, JSON, INI, TXT需要加载后解析到指定的内存结构同步分给相应的任务使用