策略的更新、加載與同步

????????C語言的C庫提供了策略的更新、加載與同步的方法,這里引入多線程,達到區分讀寫任務(生產者——消費者 模型)的目的。

示例:

/*@brief check strategy to update, reload, synchronized to read(stoped by SIGINT)@author wen`xuanpei@email 15873152445@163.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, don't 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 pointer@parama: 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) can't 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 \"\t<strategy>\"                   >>" STRATEGY_FILE ";""echo \"\t\t<person>\"                   >>" STRATEGY_FILE ";""echo \"\t\t\t<name>john</name>\"        >>" STRATEGY_FILE ";""echo \"\t\t\t<age>18</age>\"            >>" STRATEGY_FILE ";""echo \"\t\t\t<weight>61.38kg</weight>\" >>" STRATEGY_FILE ";""echo \"\t\t\t<married>false</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 \"married=false#\"      >>" 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需要加載后解析到指定的內存結構,同步分給相應的任務使用

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/715842.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/715842.shtml
英文地址,請注明出處:http://en.pswp.cn/news/715842.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Mysql標量子查詢

目錄 子查詢標量子查詢數據準備 子查詢 SQL語句中嵌套select語句&#xff0c;稱為嵌套查詢&#xff0c;又稱子查詢。 SELECT * FROM t1 WHERE column1 ( SELECT column1 FROM t2 ... );子查詢外部的語句可以是insert / update / delete / select 的任何一個&…

git的安裝、使用

文章目錄 安裝gitgit學習網站git初始配置具體配置信息 新建版本庫&#xff08;倉庫&#xff09;git的工作區域和文件狀態工作區域文件狀態git文件提交的基礎指令 git基礎指令1. 版本提交2. 分支創建3. 分支切換4. 分支合并(1) git merge(2) git rebase 5. 在git的提交樹上移動(…

Ps:銳化工具

銳化工具 Sharpen Tool可用于增強圖像局部區域的對比度&#xff0c;從而提高圖像的清晰度和細節&#xff0c;特別適用于提升照片的邊緣定義和紋理細節。 快捷鍵&#xff1a;無 ◆ ◆ ◆ 常用操作方法與技巧 1、如果直接在像素圖像上使用銳化工具&#xff0c;可嘗試使用“漸隱…

怎么優雅地訪問ChatGPT

ChatGPT&#xff0c;這顆璀璨的智能結晶&#xff0c;在2022年歲末之際&#xff0c;由OpenAI實驗室傾力鑄就&#xff0c;猶如夜空中躍動的智慧星辰&#xff0c;點亮了人工智能領域的新紀元。猶如汪洋中的一座燈塔&#xff0c;ChatGPT以其獨特的智慧光輝引人注目&#xff0c;然而…

Linux:kubernetes(k8s)node節點加入master主節點(3)

Linux&#xff1a;kubernetes&#xff08;k8s&#xff09;搭建mater節點&#xff08;kubeadm&#xff0c;kubectl&#xff0c;kubelet&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136415575?spm1001.2014.3001.5502 我在上一章部署好了主節點&…

前端打包部署(黑馬學習筆記)

我們的前端工程開發好了&#xff0c;但是我們需要發布&#xff0c;那么如何發布呢&#xff1f;主要分為2步&#xff1a; 1.前端工程打包 2.通過nginx服務器發布前端工程 前端工程打包 接下來我們先來對前端工程進行打包 我們直接通過VS Code的NPM腳本中提供的build按鈕來完…

從下一代車規MCU厘清存儲器的發展(2)

目錄 1.概述 2.MCU大廠的選擇 2.1 瑞薩自研STT-MRAM 2.2 ST專注PCM 2.3 英飛凌和臺積電聯手RRAM 2.4 NXP如何計劃eNVM 3.小結 1.概述 上篇文章&#xff0c;我們簡述了當前主流的存儲器技術&#xff0c;現在我們來講講各大MCU大廠的技術選擇 2.MCU大廠的選擇 瑞薩日…

redis的RDB和AOF

Redis是一種高性能的鍵值對存儲系統&#xff0c;它支持多種類型的數據結構&#xff0c;如字符串、列表、集合、哈希表、有序集合等。Redis提供了兩種不同的持久化機制來確保數據的安全性&#xff1a;RDB&#xff08;Redis Database&#xff09;和AOF&#xff08;Append Only Fi…

Tomcat布署及優化二-----Mysql和虛擬機

1.Mysql搭Blog 1.1下載安裝包 看一下tomcat狀態 1.2放到指定目錄 cp jpress-v3.2.1.war /usr/local/tomcat/webapps/ cd /usr/local/tomcat/webapps/ 1.3路徑優化 ln -s jpress-v3.2.1 jpress 看jpress權限 1.4生成配置文件 cat >/etc/yum.repos.d/mysql.repo <<E…

掘根寶典之C語言指針詳解

目錄 什么是指針&#xff1f; 與指針相關的運算符 指針類型的意義 指針的大小 初始化 將指針直接指向一個已經存在的變量或內存地址&#xff1a; 使用malloc函數動態分配內存&#xff0c;并將指針指向新分配的內存&#xff1a; 使用calloc函數動態分配內存&#xff0c;并…

Javascript:常量與數據類型

一、前言 介紹完變量之后我們來對常量進行了解一番&#xff0c;關于常量我們需要知道些什么呢&#xff1f; 二、正文 1.常量的基本使用 使用const聲明的變量稱為常量&#xff0c;當某個變量的字面量無需改動的時候就能夠用到常量。 //聲明一個常量 const G 9.8 //輸出這個常量…

您的計算機已被pings勒索病毒感染?恢復您的數據的方法在這里!

導言&#xff1a; 在數字時代&#xff0c;數據是企業和個人生活中不可或缺的一部分。然而&#xff0c;隨著勒索病毒的不斷進化和傳播&#xff0c;我們的數據面臨著前所未有的威脅。其中&#xff0c;.pings 勒索病毒是最新一輪威脅之一&#xff0c;它以其獨特的加密算法和無情的…

leetcode-字符串中的單詞數

434. 字符串中的單詞數 題解&#xff1a; 這個問題可以通過遍歷字符串&#xff0c;當遇到非空格字符時&#xff0c;判斷其前一個字符是否為空格&#xff0c;如果是&#xff0c;則說明這是一個新的單詞的開始&#xff0c;計數器加一。最后返回計數器的值即可。 class Solutio…

【Redis | 第一篇】快速了解Redis

文章目錄 1.快速了解Redis1.1簡介1.2與其他key-value存儲的不同處1.3Redis安裝——Windows環境1.3.1下載redis1.3.2啟動redis1.3.3進入redis客戶端1.3.4修改配置 1.4Redis安裝——Linux環境1.4.1安裝命令1.4.2啟動redis1.4.3進入redis客戶端 1.5配置修改1.6小結 1.快速了解Redi…

MyBatis 學習(七)之 緩存

目錄 1 MyBatis 緩存介紹 2 一級緩存 3 二級緩存 3.1 二級緩存介紹 3.2 二級緩存配置 3.3 二級緩存測試 4 參考文檔 1 MyBatis 緩存介紹 MyBatis 緩存是 MyBatis 中的一個重要特性&#xff0c;用于提高數據庫查詢的性能。MyBatis 提供了一級緩存和二級緩存兩種類型的緩存…

Git與GitHub:解鎖版本控制的魔法盒子

?? 歡迎大家來訪Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭?&#xff5e;?? &#x1f31f;&#x1f31f; 歡迎各位親愛的讀者&#xff0c;感謝你們抽出寶貴的時間來閱讀我的文章。 我是Srlua&#xff0c;在這里我會分享我的知識和經驗。&#x…

cetos7 Docker 安裝 gitlab

一、gitlab 簡單介紹和安裝要求 官方文檔&#xff1a;https://docs.gitlab.cn/jh/install/docker.html 1.1、gitlab 介紹 gitLab 是一個用于代碼倉庫管理系統的開源項目&#xff0c;使用git作為代碼管理工具&#xff0c;并在此基礎上搭建起來的Web服務平臺&#xff0c;通過該平…

(六)Dropout抑制過擬合與超參數的選擇--九五小龐

過擬合 即模型在訓練集上表現的很好&#xff0c;但是在測試集上效果卻很差。也就是說&#xff0c;在已知的數據集合中非常好&#xff0c;再添加一些新數據進來效果就會差很多 欠擬合 即模型在訓練集上表現的效果差&#xff0c;沒有充分利用數據&#xff0c;預測準確率很低&a…

笨辦法學 Python3 第五版(預覽)(一)

原文&#xff1a;Learn Python the Hard Way, 5th Edition (Early Release) 譯者&#xff1a;飛龍 協議&#xff1a;CC BY-NC-SA 4.0 模塊 1&#xff1a;Python 入門 練習 0&#xff1a;準備工作 這個練習沒有代碼。這只是你完成的練習&#xff0c;讓你的計算機運行 Python。…

Unity 游戲設計模式:單例模式

本文由 簡悅 SimpRead 轉碼&#xff0c; 原文地址 mp.weixin.qq.com 單例模式 在 C# 游戲設計中&#xff0c;單例模式是一種常見的設計模式&#xff0c;它的主要目的是確保一個類只有一個實例&#xff0c;并提供一個全局訪問點。單例模式在游戲開發中具有以下幾個作用&#xf…