由于第二人生是一個3D顯示的軟件,因此它就需要不斷地從服務器下載大量數據,比如紋理圖片,不同的角色是使用不同的紋理圖片來實現不同的衣服外表的。當顯示這些角色時,就使用從服務器下載的紋理圖片。如果顯示的人物角色比較多,比如有30個人時,這些紋理圖片就需要保存到磁盤里。那么怎么樣保存到磁盤里呢?保存到磁盤里就需要一個好的文件系統來保存,以及讀取數據出來。讀寫磁盤是一項比較慢的工作,因此需要使用一個線程來實現。還有時讀寫文件并不需要及時性的動作,可以讓線程等到CPU空閑時再去做這些事情。
?
LLVFSThread類是繼承LLQueuedThread類,這樣LLVFSThread就變成消息循環處理類了。只需要不斷地添加請求到消息隊列里,然后再實現消息處理函數,就實現相應的功能了。
#001?//static
#002?void LLVFSThread::initClass(bool local_is_threaded)
#003?{
#004?
???? llassert(sLocal == NULL);
#005?
???? sLocal = new LLVFSThread(local_is_threaded);
#006?}
上面實始化虛擬文件系統線程類。
?
?
#001?LLVFSThread::handle_t LLVFSThread::read(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
#002?
??????????????????????????????????????????????????????????????????? U8* buffer, S32
#003?offset, S32 numbytes, U32 priority, U32 flags)
#004?{
?
獲取處理的句柄。
#005?
???? handle_t handle = generateHandle();
#006?
?
獲取這個請求的執行優先級。
#007?
???? priority = llmax(priority, (U32)PRIORITY_LOW); // All reads are at least PRIORITY_LOW
?
創建讀取數據請求消息。
#008?
???? Request* req = new Request(handle, priority, flags, FILE_READ, vfs, file_id, file_type,
#009?
?????????????????????????????????????????????? ???buffer, offset, numbytes);
#010?
?
添加這個消息到消息隊列。
#011?
???? bool res = addRequest(req);
#012?
???? if (!res)
#013?
???? {
#014?
??????????? llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
#015?
??????????? req->deleteRequest();
#016?
??????????? handle = nullHandle();
#017?
???? }
#018?
#019?
???? return handle;
#020?}
?
虛擬文件系統需要實現讀取里面的文件數據出來,上面函數LLVFSThread::read就是實現這樣的功能。
?
#001?S32 LLVFSThread::readImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
#002?
?????????????????????????????????????????????? ???U8* buffer, S32 offset, S32 numbytes)
#003?{
?
獲取線程句柄。
#004?
???? handle_t handle = generateHandle();
#005?
?
創建立即讀取數據請求,主要優先級不一樣。
#006?
???? Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0, FILE_READ, vfs, file_id, file_type,
#007?
?????????????????????????????????????????????? ???buffer, offset, numbytes);
#008?
????
?
添加請求到消息隊列。
#009?
???? S32 res = addRequest(req) ? 1 : 0;
#010?
???? if (res == 0)
#011?
???? {
#012?
??????????? llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
#013?
??????????? req->deleteRequest();
#014?
???? }
#015?
???? else
#016?
???? {
#017?
??????????? llverify(waitForResult(handle, false) == true);
#018?
??????????? res = req->getBytesRead();
#019?
??????????? completeRequest(handle);
#020?
???? }
#021?
???? return res;
#022?}
?
上面的函數實現立即讀取數據的要求。
?
#001?LLVFSThread::handle_t LLVFSThread::write(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
#002?
??????????????????????????????????????????????????????????????????? ?U8* buffer, S32
#003?offset, S32 numbytes, U32 flags)
#004?{
?
獲取線程句柄。
#005?
???? handle_t handle = generateHandle();
#006?
?
添加寫文件數據到虛擬文件系統的請求。
#007?
???? Request* req = new Request(handle, 0, flags, FILE_WRITE, vfs, file_id, file_type,
#008?
?????????????????????????????????????????????? ???buffer, offset, numbytes);
#009?
?
添加消息請求到消息隊列。
#010?
???? bool res = addRequest(req);
#011?
???? if (!res)
#012?
???? {
#013?
??????????? llerrs << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << llendl;
#014?
??????????? req->deleteRequest();
#015?
??????????? handle = nullHandle();
#016?
???? }
#017?
????
#018?
???? return handle;
#019?}
?
上面的函數實現寫數據到虛擬文件系統的消息請求。在其后面還有LLVFSThread::writeImmediate函數,這個函數實現立即寫數據到虛擬文件系統的請求。通過四個函數就可以添加讀取數據和寫數據到虛擬文件系統的請求,而這些請求又是怎么樣處理的呢?下次再帶你去理解它。
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
