女人被狂躁到高潮视频免费无遮挡,内射人妻骚骚骚,免费人成小说在线观看网站,九九影院午夜理论片少妇,免费av永久免费网址

當(dāng)前位置:首頁 > > 充電吧
[導(dǎo)讀]SKYNET設(shè)計綜述講到模塊被稱為服務(wù)?!胺?wù)間可以自由發(fā)送消息。每個模塊可以向 Skynet 框架注冊一個 callback 函數(shù),用來接收發(fā)給它的消息。”還提到“把一個符合規(guī)范的 C 模塊,從動態(tài)

SKYNET設(shè)計綜述講到模塊被稱為服務(wù)。“服務(wù)間可以自由發(fā)送消息。每個模塊可以向 Skynet 框架注冊一個 callback 函數(shù),用來接收發(fā)給它的消息?!边€提到“把一個符合規(guī)范的 C 模塊,從動態(tài)庫(so 文件)中啟動起來,綁定一個永不重復(fù)(即使模塊退出)的數(shù)字 id 做為其 handle 。Skynet 提供了名字服務(wù),還可以給特定的服務(wù)起一個易讀的名字,而不是用 id 來指代它。id 和運行時態(tài)相關(guān),無法保證每次啟動服務(wù),都有一致的 id ,但名字可以?!苯裉煲治龅膬蓚€文件skynet_handle.c和skynet_handle.h就是實現(xiàn)名字服務(wù)的。

而WIKI中的CLUSTER講到的是harbor相關(guān)的內(nèi)容,“每個 skynet 服務(wù)都有一個全網(wǎng)唯一的地址,這個地址是一個 32bit 數(shù)字,其高 8bit 標識著它所屬 slave 的號碼。即 harbor id 。在 master/slave 網(wǎng)絡(luò)中,id 為 0 是保留的。所以最多可以有 255 個 slave 節(jié)點?!?/p>

前面寫這么一大段東西都是分析代碼所需要的,不是為了湊字數(shù),也不是為了別的原因。下面開始分析代碼。

#include?"skynet.h"

#define?DEFAULT_SLOT_SIZE?4
#define?MAX_SLOT_SIZE?0x40000000

//名字服務(wù)結(jié)構(gòu),一個名字對應(yīng)一個handle
struct?handle_name?{
????char?*?name;?//服務(wù)名字
????uint32_t?handle;?//服務(wù)ID,下面以handle來稱呼
};
//保存handle/name列表的數(shù)據(jù)結(jié)構(gòu),skynet_handle_init會初始化它
struct?handle_storage?{
????struct?rwlock?lock;

????uint32_t?harbor;//這就是wiki里提到的harbor!!
????uint32_t?handle_index;?//必須從1開始
????int?slot_size;?//數(shù)組長度
????struct?skynet_context?**?slot;?//數(shù)組,實際上里面存的是服務(wù)的上下文
????
????int?name_cap;?//容量
????int?name_count;?//長度或者說個數(shù)
????struct?handle_name?*name;?//數(shù)組
};

static?struct?handle_storage?*H?=?NULL;

//注冊服務(wù),返回給它一個handle
uint32_t
skynet_handle_register(struct?skynet_context?*ctx)?{
????struct?handle_storage?*s?=?H;

????rwlock_wlock(&s->lock);
????//死循環(huán),所以服務(wù)數(shù)量如果太大了你懂得
????for?(;;)?{
????????int?i;
????????for?(i=0;islot_size;i++)?{?//遍歷服務(wù)列表,找個空位
????????????uint32_t?handle?=?(i+s->handle_index)?&?HANDLE_MASK;?//只取后24位
????????????int?hash?=?handle?&?(s->slot_size-1);?//&操作符,就是取到一個小于s->slot_size-1的值,slot_size-1源碼下方有詳細解釋。
????????????if?(s->slot[hash]?==?NULL)?{?//沒有hash碰撞,好巧
????????????????s->slot[hash]?=?ctx;
????????????????s->handle_index?=?handle?+?1;?//handle_index增加了

????????????????rwlock_wunlock(&s->lock);

????????????????handle?|=?s->harbor;?//?位操作或,把harbor?id附上去,實在不理解你就把它當(dāng)加法吧
????????????????return?handle;
????????????}
????????}
//不幸的事情發(fā)生了,一直都在HASH碰撞,也就是說坑已經(jīng)填滿了
????????assert((s->slot_size*2?-?1)?slot_size?*?2?*?sizeof(struct?skynet_context?*));
//老套路,數(shù)據(jù)清零
????????memset(new_slot,?0,?s->slot_size?*?2?*?sizeof(struct?skynet_context?*));
//把老數(shù)據(jù)拷過來,要重新hash,但是handle_index沒增加
????????for?(i=0;islot_size;i++)?{
????????????int?hash?=?skynet_context_handle(s->slot[i])?&?(s->slot_size?*?2?-?1);
????????????assert(new_slot[hash]?==?NULL);
????????????new_slot[hash]?=?s->slot[i];
????????}
????????skynet_free(s->slot);
????????s->slot?=?new_slot;?//直接替換指針
????????s->slot_size?*=?2;?//容量擴大一倍
????}
//容量都擴一倍了,再試試會不會hash碰撞吧,再碰我們就再擴大一倍
}
//退休某個服務(wù),反注冊
int
skynet_handle_retire(uint32_t?handle)?{
????int?ret?=?0;
????struct?handle_storage?*s?=?H;

????rwlock_wlock(&s->lock);
//取有效位hash
????uint32_t?hash?=?handle?&?(s->slot_size-1);
//取服務(wù)上下文,一會兒要釋放的
????struct?skynet_context?*?ctx?=?s->slot[hash];
//較驗這個服務(wù)是存在的,而且確實對應(yīng)的就是這個handle
????if?(ctx?!=?NULL?&&?skynet_context_handle(ctx)?==?handle)?{
????????s->slot[hash]?=?NULL;?//把空位讓出來
????????ret?=?1;
????????int?i;
????????int?j=0,?n=s->name_count;
????????for?(i=0;?iname[i].handle?==?handle)?{
????????????????skynet_free(s->name[i].name);?//釋放內(nèi)存
????????????????continue;
????????????}?else?if?(i!=j)?{?//這里在做數(shù)組元素刪除操作,把后面的都往前移一下
????????????????s->name[j]?=?s->name[i];
????????????}
????????????++j;//元素刪除輔助
????????}
????????s->name_count?=?j;
????}?else?{
????????ctx?=?NULL;
????}

????rwlock_wunlock(&s->lock);
//這里就釋放服務(wù)了
????if?(ctx)?{
????????//?release?ctx?may?call?skynet_handle_*?,?so?wunlock?first.
????????skynet_context_release(ctx);
????}

????return?ret;
}

//全部退休了
void?
skynet_handle_retireall()?{
????struct?handle_storage?*s?=?H;
????for?(;;)?{
????????int?n=0;
????????int?i;
????????for?(i=0;islot_size;i++)?{
????????????rwlock_rlock(&s->lock);
????????????struct?skynet_context?*?ctx?=?s->slot[i];?//取服務(wù)上下文
????????????uint32_t?handle?=?0;
????????????if?(ctx)
????????????????handle?=?skynet_context_handle(ctx);
????????????rwlock_runlock(&s->lock);
????????????if?(handle?!=?0)?{?//對服務(wù)上下文的handle進行“退休”
????????????????if?(skynet_handle_retire(handle))?{
????????????????????++n;
????????????????}
????????????}
????????}
????????if?(n==0)
????????????return;
????}
}

struct?skynet_context?*?
skynet_handle_grab(uint32_t?handle)?{
????struct?handle_storage?*s?=?H;
????struct?skynet_context?*?result?=?NULL;

????rwlock_rlock(&s->lock);

????uint32_t?hash?=?handle?&?(s->slot_size-1);
????struct?skynet_context?*?ctx?=?s->slot[hash];
????if?(ctx?&&?skynet_context_handle(ctx)?==?handle)?{
????????result?=?ctx;
????????skynet_context_grab(result);?//引用計數(shù)+1
????}

????rwlock_runlock(&s->lock);

????return?result;
}

//通過name找handle
//算法是二分查找法
//二分查找法請自行g(shù)ooge/bing/baidu
uint32_t?
skynet_handle_findname(const?char?*?name)?{
????struct?handle_storage?*s?=?H;

????rwlock_rlock(&s->lock);

????uint32_t?handle?=?0;

????int?begin?=?0;
????int?end?=?s->name_count?-?1;
????while?(beginname[mid];
????????int?c?=?strcmp(n->name,?name);?//strcmp是個c系統(tǒng)函數(shù)
????????if?(c==0)?{?//找到匹配的名字
????????????handle?=?n->handle;
????????????break;
????????}
????????if?(c<0)?{?//當(dāng)前位置的名字?<?要查找的名字,到后半部分去找
????????????begin?=?mid?+?1;
????????}?else?{?//當(dāng)前位置的名字?>要查找的名字,到前半部分去找
????????????end?=?mid?-?1;
????????}
????}

????rwlock_runlock(&s->lock);

????return?handle;
}

//把name插入到name數(shù)組中,再關(guān)聯(lián)handle
static?void
_insert_name_before(struct?handle_storage?*s,?char?*name,?uint32_t?handle,?int?before)?{
//擴容
????if?(s->name_count?>=?s->name_cap)?{
????????s->name_cap?*=?2;?//擴容
????????assert(s->name_cap?name_cap?*?sizeof(struct?handle_name));?//開一個新數(shù)組,容量是老數(shù)據(jù)的2倍
????????int?i;
????????for?(i=0;iname[i];
????????}
????????for?(i=before;iname_count;i++)?{?//復(fù)制before及后面的數(shù)據(jù)
????????????n[i+1]?=?s->name[i];
????????}
????????skynet_free(s->name);?//把老數(shù)據(jù)內(nèi)存回收了
????????s->name?=?n;?//把新數(shù)組設(shè)進來
????}?else?{?//空間夠用
????????int?i;
????????for?(i=s->name_count;i>before;i--)?{?//從后往前,一次一個移動數(shù)組元素,把before位置空出來
????????????s->name[i]?=?s->name[i-1];
????????}
????}
//賦值了
????s->name[before].name?=?name;?//名字
????s->name[before].handle?=?handle;?//handle
????s->name_count?++;?//數(shù)量+1
}

//給handle綁定一個name
//name是由小到大順序排列的
//二分查找法,數(shù)據(jù)結(jié)構(gòu)很重要啊,少年
static?const?char?*
_insert_name(struct?handle_storage?*s,?const?char?*?name,?uint32_t?handle)?{
????int?begin?=?0;
????int?end?=?s->name_count?-?1;
????while?(beginname[mid];
????????int?c?=?strcmp(n->name,?name);
????????if?(c==0)?{?//名字已經(jīng)存在了,不能再綁或者重復(fù)綁
????????????return?NULL;
????????}
????????if?(c<0)?{?//當(dāng)前字符串?<?要插入的字符串
????????????begin?=?mid?+?1;?//二分查找后半部分
????????}?else?{?//當(dāng)前字符串?>要插入的字符串
????????????end?=?mid?-?1;?//二分查找前半部分
????????}
????}
????char?*?result?=?skynet_strdup(name);?//字符串復(fù)制
//把name插入到數(shù)組中
????_insert_name_before(s,?result,?handle,?begin);

????return?result;
}

//給handle綁定一個name
const?char?*?
skynet_handle_namehandle(uint32_t?handle,?const?char?*name)?{
????rwlock_wlock(&H->lock);

????const?char?*?ret?=?_insert_name(H,?name,?handle);

????rwlock_wunlock(&H->lock);

????return?ret;
}

//初始化handle_storage
void?
skynet_handle_init(int?harbor)?{
????assert(H==NULL);
????struct?handle_storage?*?s?=?skynet_malloc(sizeof(*H));
????s->slot_size?=?DEFAULT_SLOT_SIZE;?//初始數(shù)組大小,slot_size是會變大的
????s->slot?=?skynet_malloc(s->slot_size?*?sizeof(struct?skynet_context?*));?//分配內(nèi)存
????memset(s->slot,?0,?s->slot_size?*?sizeof(struct?skynet_context?*));?//數(shù)據(jù)清零

????rwlock_init(&s->lock);
????//?reserve?0?for?system
????s->harbor?=?(uint32_t)?(harbor?&?0xff)?<<?HANDLE_REMOTE_SHIFT;?//這就是wiki中提到的,前8位是harbor?id,HANDLE_REMOTE_SHIFT為24
????s->handle_index?=?1;?//
????s->name_cap?=?2;?//暫時只讓放2個
????s->name_count?=?0;?//空的
????s->name?=?skynet_malloc(s->name_cap?*?sizeof(struct?handle_name));

????H?=?s;

????//?Don't?need?to?free?H
}

代碼中有個很巧妙的設(shè)計,就是s->slot_size-1,它的低位二進制永遠都是1。不信你看,剛開始slot_size是4,4-1就是3,擴了以后是8,8-1就是7,然后16,32....。這樣的話,和任何數(shù)字與操作,都不會丟失“有效的”低位。

好了,到此為止,代碼也看完了??偨Y(jié)一下,skynet_handle.c實際上就做了兩個核心的事情,一是給服務(wù)分配一個handle,二是把handle和name關(guān)聯(lián)起來。

把handle和name關(guān)聯(lián)起來比較容易懂,實際上使用一個數(shù)組,關(guān)聯(lián)的時候使用二分查找到數(shù)組里查名字,如果名字不存在,就插入一個元素,然后把名字和handle關(guān)聯(lián)起來。插入元素的時候,如果數(shù)組空間不足了,就擴容為原來的2倍。

而給服務(wù)分配handle稍復(fù)雜一些,實際上也是使用一個slot數(shù)組,數(shù)組下標使用的是一個hash,數(shù)組元素指向服務(wù)的上下文。這個hash的算法是比較簡單粗暴的,就是看從handle_indx開始累計到slot_size,看中間有沒有空閑的下標(也就是下標指向為null的),如果遍歷完了還是沒有,就把slot擴大一倍,還是沒有就再擴大一倍,直到找到空位為止,或者是slot長度超出限制為止。

取到了handle以后呢,還要將harbor id附到handle的高8位。

作者:shihuaping0918@163.com

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉