re: CEnumClass—類型安全的枚舉類型 Kevin Lynx 2008-08-13 10:05
我覺得,用你這個(gè)類與普通的enum相比,更多時(shí)候我們需要的是一個(gè)方便的enum,即使它沒有你這個(gè)class安全;
如果我沒弄錯(cuò)的話,你這個(gè)類雖然sizeof為sizeof(int),但這并不是你所說(shuō)的“同時(shí)也沒有占用任何額外的空間”,因?yàn)檫€有很多static常量。
@陳梓瀚(vczh)
就我所查閱的文檔來(lái)看,似乎沒有。coroutine.yiled/resume可能算是吧。
re: 自己寫的一個(gè)GUI框架的消息機(jī)制 Kevin Lynx 2008-08-07 09:17
@eXile
我亦覺得,樓主局限于native win32的思維方式。在對(duì)消息的處理上,遵從的是WIN32的消息機(jī)制。
不過(guò)從代碼看來(lái)(LRESULT之類),這個(gè)框架可能沒有考慮跨平臺(tái)特性。所以停留在WINDOWS上也沒什么。
個(gè)人拙見。:)
re: 建立異步操作組件:隊(duì)列和線程 Kevin Lynx 2008-08-06 13:11
@francis
thread2沒有獲得CPU權(quán)!thread2沒有被調(diào)度!
這里的用法完全是條件變量的標(biāo)準(zhǔn)用法,如果你硬是要從理論上認(rèn)為它有問題,那你可以去查條件變量相關(guān)資料。這里的結(jié)構(gòu)和條件變量通用用法一樣。你甚至可以找本操作系統(tǒng)書,在上面找到條件變量的使用結(jié)構(gòu)。你想推翻這一切?建議你大量查閱條件變量相關(guān)資料。如果你還認(rèn)為有問題,你應(yīng)該去對(duì)發(fā)明條件變量的某個(gè)可能已經(jīng)死掉的牛人說(shuō):你這個(gè)條件變量的結(jié)構(gòu)有問題。
re: 建立異步操作組件:隊(duì)列和線程 Kevin Lynx 2008-08-06 09:07
@francis
我讀了幾遍你的這次回復(fù),希望我沒有誤解你的意思:
thread1被激活,取數(shù)據(jù),就可能導(dǎo)致container的size為0,一旦size為0,thread3繼續(xù)push的時(shí)候就可能會(huì)激活thread2。如果OS一直沒有調(diào)度到thread2,那么,container就可能經(jīng)歷過(guò)多次size為0,size不為0,也就是thread1和thread3發(fā)生多次數(shù)據(jù)交互。thread2看起來(lái)是慘了,因?yàn)閏ontainer曾經(jīng)有數(shù)據(jù),但是thread2卻沒取到?為什么呢?thread2根本沒被OS調(diào)度到,從沒有獲取到CPU控制權(quán),它又有什么理由不wait?
歸根結(jié)底,你說(shuō)的這個(gè)問題,只是因?yàn)閠hread2沒有被調(diào)度到而已。
re: 建立異步操作組件:隊(duì)列和線程 Kevin Lynx 2008-08-05 09:00
@francis
詳述下這種會(huì)出現(xiàn)問題的情況。如果可以模擬出現(xiàn)的話,麻煩基于multi_list這個(gè)類制造這種情況。
re: 建立異步操作組件:隊(duì)列和線程 Kevin Lynx 2008-08-04 22:28
@francis
while( _container.size() == 0 ) _condition.wait();
僅當(dāng)為空的情況下才wait的。代碼在邏輯上不存在大問題,因?yàn)檫@個(gè)基礎(chǔ)部件已經(jīng)被用于實(shí)際項(xiàng)目(用于保存驗(yàn)證服務(wù)器端的驗(yàn)證帳號(hào))。
re: 建立異步操作組件:隊(duì)列和線程 Kevin Lynx 2008-08-04 16:43
@francis
我們看一次常規(guī)的同步操作:
push_front()
{
guard<mutex_type> g(_mutex );
...
}
pop_front()
{
guadr<mutex_type> g(_mutex );
...
}
那么,在消費(fèi)者線程里可能會(huì)不斷地去檢查隊(duì)列大小是否為0(size操作同樣會(huì)涉及到同步),
這浪費(fèi)了CPU資源。而如果:
pop_front()
{
guadr<mutex_type> g(_mutex );
while( size == 0 ) _cond.wait();
}
當(dāng)大小為0時(shí),wait操作將阻塞此線程,從而讓出了CPU資源(wait會(huì)阻塞)。
另一方面,如果每次push操作都進(jìn)行條件變量的signal,這個(gè)所謂的原語(yǔ)操作開銷有多大?
查看condition::signal/wait代碼,其內(nèi)部還存在一個(gè)_wait_count的同步。另外,如果
每次push都signal的話,那么pop操作也需要進(jìn)行wait,這樣以來(lái)它其實(shí)已經(jīng)不是條件變量,
而是信號(hào)量了。
我們所要的效果,就是在隊(duì)列元素為0時(shí),進(jìn)行pop操作的時(shí)候讓其阻塞而已。
re: 建立異步操作組件:隊(duì)列和線程 Kevin Lynx 2008-08-04 12:55
@francis
關(guān)鍵在于,signal和wait會(huì)對(duì)外部mutex做操作。參見kl_condition.h相關(guān)代碼。
re: 建立異步操作組件:隊(duì)列和線程 Kevin Lynx 2008-08-03 10:40
@francis
你可以查找‘條件變量’(condition variable)的相關(guān)資料。
signal只在隊(duì)列尺寸為0時(shí)的push操作中調(diào)用,因?yàn)樵趐op中會(huì)在隊(duì)列尺寸為0時(shí)wait.
@Strive
很巧, 我恰好看過(guò)這個(gè)網(wǎng)站,感覺是個(gè)少年天才的主頁(yè)。之前搜索QQ協(xié)議,發(fā)現(xiàn)的。還下了他寫的QQ客戶端,不過(guò)有問題,我登陸Q后,就被T了。
@zx
高并發(fā)數(shù)不見得要使用async(不明白你所謂的Async模式是什么?我假設(shè)是異步IO),也不見得要使用Overlapped IO (我也不明白你說(shuō)的"IO的overlapped",我假設(shè)是windows下的Overlapped IO),一個(gè)event-driven的網(wǎng)路模型就很不錯(cuò)了。
@x-matrix
本文的重點(diǎn)在于對(duì)HTTP協(xié)議的解析,而不是開發(fā)高并發(fā)網(wǎng)絡(luò)框架。:)
re: GP技術(shù)的展望——先有鴻鈞后有天 Kevin Lynx 2008-07-26 22:33
longshanks終于又發(fā)文了。學(xué)習(xí)。
@happyday
取元素只是從樹根取,取了后需要對(duì)整棵樹進(jìn)行調(diào)整。
插入元素插入到最下最右的節(jié)點(diǎn),插入后需要進(jìn)行微小的調(diào)整。
總之元素的增加/減少,都需要重新調(diào)整整棵樹使其依然為一個(gè)堆。
re: 日志該怎么記錄? Kevin Lynx 2008-07-18 10:48
越來(lái)越寫得水了。
@true
那就應(yīng)該沒問題了。‘應(yīng)用程序初始化失敗’,你用的是VS2005吧?那就跟BOOST沒關(guān)系了。新的問題跟項(xiàng)目設(shè)定有關(guān)系。具體搜索下網(wǎng)絡(luò)吧。:)
我以前編譯ASIO例子程序的時(shí)候,就顯示地忽略了以下兩個(gè)庫(kù):
libboost_date_time-vc80-mt-gd-1_34_1.lib
libboost_regex-vc80-mt-gd-1_34_1.lib
但是,libboost_system-vc80-mt-gd-1_35.lib則沒遇到過(guò),你顯示地忽略掉看下如何?
re: VS2005編譯libevent Kevin Lynx 2008-07-07 12:53
libevent在windows下似乎沒多大實(shí)用價(jià)值(因?yàn)橛玫氖莝elect)。spserver的作者寫了個(gè)IOCP版本。
貌似是有這樣的現(xiàn)象,例如libevent的VC6工程文件用RAR解開后就是壞的。
re: GameRes里面某位大師的語(yǔ)錄 Kevin Lynx 2008-06-26 21:51
‘游戲之家站長(zhǎng)’的故事源遠(yuǎn)流長(zhǎng)。。。
偶然發(fā)現(xiàn)LZ博客有我以前CSDN的鏈接,呵呵,現(xiàn)在我換到CPPBLOG來(lái)了,更新下鏈接吧。
re: 建立異步操作組件:隊(duì)列和線程[未登錄] Kevin Lynx 2008-06-26 09:14
@飯中淹
前面我說(shuō)了,condition和guard使用的是同一個(gè)mutex,在condition的wait里,會(huì)先_external_mutex.release();,然后push的時(shí)候,就不會(huì)阻塞在guard那里,于是condition.signal(元素為0時(shí),看下代碼),然后pop里的condition.wait就過(guò)了。
re: 建立異步操作組件:隊(duì)列和線程 Kevin Lynx 2008-06-25 21:42
@飯中淹
不會(huì)的,condition和guard使用的都是同一個(gè)mutex。guard用于一般的同步,condition用于隊(duì)列元素為0時(shí)的臨界條件。
@true
事實(shí)上是我寫的. :D 我寫著玩,但是被用到我們的產(chǎn)品里。
比較有意思的:
/// my fucking and ugly sorted queue only for ServerInfo struct, because i want
/// everytime i push_back an element in the queue, it will update the element
/// which _ls_id && _ws_id && _gs_id already existes.I adapted this queue so that
/// it can be used in my multi_list. :D I'm a such programmer
template <typename _Tp, typename _AllocType = std::allocator<_Tp> >
class my_fucking_list;
/// partial version for ServerInfo
template <typename _AllocType>
class my_fucking_list<ServerInfo, _AllocType>
{
public:
re: 建立異步操作組件:隊(duì)列和線程[未登錄] Kevin Lynx 2008-06-25 16:22
@true
貌似你誤解我意思了;)
’阻塞時(shí)不能退出‘:
例如線程里 WaitFor...INFINITE了,那么它就無(wú)法處理消息,也無(wú)法判斷退出標(biāo)志變量,代碼卡在這里了。
’他更及時(shí),不用參與排隊(duì)‘:
這個(gè)跟上面不是說(shuō)的同一個(gè)問題,隊(duì)列是用于實(shí)際業(yè)務(wù)處理,例如寫日志,上面那個(gè)說(shuō)的是線程。
有道理,對(duì)于用struct寫文件這種情況,很容易因?yàn)閟truct的字節(jié)對(duì)齊問題導(dǎo)致想不到的BUG。尤其是采用直接將struct以二進(jìn)制方式寫入文件的方式寫文件。
re: SGI STL的內(nèi)存池 Kevin Lynx 2008-06-15 09:40
@Gohan
rebind可以讓allocator<Tp>的保存者分配其他類型的內(nèi)存。例如,當(dāng)實(shí)例化list時(shí)(例如list<int,my_allocator<int> > ),在list內(nèi)部就保存著一個(gè)my_allocator<int>,但是list需要為自己分配list_node,就是說(shuō)它需要另一個(gè)allocator,那么這個(gè)時(shí)候就可以通過(guò)rebind來(lái)完成。
re: SGI STL的內(nèi)存池 Kevin Lynx 2008-06-13 12:36
@關(guān)中刀客
STL默認(rèn)那個(gè)內(nèi)存池。。。STL默認(rèn)沒內(nèi)存池。SGI的STL里那個(gè)內(nèi)存池不是標(biāo)準(zhǔn)的。VC下的STL就沒這個(gè)。
re: (C++)一個(gè)愚蠢的錯(cuò)誤 Kevin Lynx 2008-06-07 09:27
錯(cuò)誤就是 memset( ...string ) ?
有點(diǎn)巧,我同事也犯過(guò)這個(gè)錯(cuò)。:D
@關(guān)中刀客
難道不開源?不知道能否分享下代碼。
我之前在google,baidu都搜索過(guò)你這個(gè)東西,沒有發(fā)現(xiàn)類似googlecode之類的項(xiàng)目地址。。
re: IRR的效果圖 Kevin Lynx 2008-06-06 16:21
@true
這些是irrlicht引擎的DEMO圖
@關(guān)中刀客
傳說(shuō)哥們和我同年同月差一天就同日生(我10號(hào):d)
還有,一直想看下你的cobra是個(gè)什么東西
@jigloo
"網(wǎng)絡(luò)層用reactor模式封裝異步IO" 似乎proactor才是用于封裝異步IO的吧?
關(guān)于你提出的這幾層封裝,不知道是否可以提供個(gè)簡(jiǎn)單的整體類圖?不甚感激。
日志對(duì)于一個(gè)系統(tǒng)來(lái)說(shuō)確實(shí)是必不可少的基礎(chǔ)模塊。
我用模板寫了個(gè)不依賴于具體‘寫’的日志類,簡(jiǎn)單的日志等級(jí)過(guò)濾。
///
/// @file kl_logger.h
/// @author Kevin Lynx
/// @date 4.21.2008
///
#ifndef ___KL_LOGGER_H_
#define ___KL_LOGGER_H_
#include <assert.h>
#include <stdarg.h>
#include <time.h>
#include <fstream>
#include "kl_compiler_cfg.h"
KL_COMMON_NAMESPACE_BEGIN
/// log level
enum log_level
{
LL_MIN = -1,
LL_ERROR,
LL_WARNING,
LL_INFO,
LL_DEBUG,
LL_MAX
};
///
/// default log pre-string, add system time and log level.
///
struct default_log_prestr
{
/// output pre-string in the buffer
/// @return the offset of the buf.
std::size_t operator() ( char *buf, int level )
{
char time[9];
char date[9];
_strtime( time );
_strdate( date );
const char *ll_desc = 0;
switch( level )
{
case LL_ERROR:
ll_desc = "ERROR";
break;
case LL_WARNING:
ll_desc = "WARNING";
break;
case LL_INFO:
ll_desc = "INFO";
break;
case LL_DEBUG:
ll_desc = "DEBUG";
break;
default:
ll_desc = "UNKNOWN";
}
// combine
sprintf( buf, "%s %s %s : ", date, time, ll_desc );
return strlen( buf ) ;
}
};
///
///
/// A simple logger class to write log information.
///
/// @param _Output where the log information to put, it must implement 'log( const char*)' function.
/// @param _PreStr used to write the pre-string of the log text like : 4.21.2008 : something.
/// @param string_size used when format string.(static buffer is more fast than dynamic buffer)
template <typename _Output, typename _PreStr = default_log_prestr, std::size_t _string_size = 1024>
class logger
{
public:
/// output object type
typedef _Output output_type;
/// pre-string type
typedef _PreStr prestr_type;
/// string size used when formatting strings.
enum
{
string_size = _string_size
};
public:
/// constructor
logger() :
_output( 0 ), _level( LL_DEBUG )
{
}
/// destructor
~logger()
{
}
/// set the output manager, you must call this function before you
/// log anything.
void set_output( output_type *ot )
{
assert( ot != 0 && "logger::set_output : invalid arguments." );
_output = ot;
}
/// write log text
void write_only( int level, const char *format, ... )
{
assert( _output != 0 && "logger::write_only : You must set up the output manager before you log anything." );
static char buf[string_size];
// checck the level
if( level > _level ) return ;
// format the string
va_list list;
va_start( list, format );
vsprintf( buf, format, list );
va_end( list );
// output the log text
_output->log( buf );
}
/// write log text and append prestring
void write( int level, const char *format, ... )
{
assert( _output != 0 && "logger::write : You must set up the output manager before you log anything." );
static char buf[string_size];
// checck the level
if( level > _level ) return ;
// append pre-string
std::size_t pos = _prestr( buf, level );
// format the string
va_list list;
va_start( list, format );
vsprintf( &buf[pos], format, list );
va_end( list );
// output the log text
_output->log( buf );
}
/// set log level
void set_level( int level )
{
assert( level > LL_MIN && level < LL_MAX && "logger::set_level : invalid arguments." );
_level = level;
}
/// get the log level
int get_level()
{
return _level;
}
private:
/// output manager to collect log text.
output_type *_output;
/// pre-str to append some text before the log text
prestr_type _prestr;
/// log level
int _level;
};
///
/// The file log output manager, write log text to the file.
///
class file_output
{
public:
/// constructor
file_output()
{
}
/// this constructor will open the file
file_output( const std::string filename, std::ios_base::openmode _Mode = std::ios_base::out ) :
_file_handle( filename.c_str(), _Mode )
{
}
/// destructor
~file_output()
{
}
/// open the file if it's not open
bool open( const std::string filename, std::ios_base::openmode _Mode = std::ios_base::out )
{
if( _file_handle.is_open() )
{
return false;
}
_file_handle.open( filename.c_str(), _Mode );
return _file_handle.is_open();
}
/// log
void log( const char *str )
{
assert( _file_handle.is_open() && "file_output::log : you cannot write anything before you open the file!" );
_file_handle << str ;
_file_handle.flush();
}
private:
/// output file
std::ofstream _file_handle;
};
KL_COMMON_NAMESPACE_END
#endif // end ___KL_LOGGER_H_
貌似console下也可以調(diào)用GetAsyncKeyState
re: 突破select的FD_SETSIZE限制 Kevin Lynx 2008-05-20 14:24
@eXile
謝謝提醒,win_fd_set_adapter.hpp確實(shí)是個(gè)方案。那估計(jì)是用__WSAFDIsSet也不是問題了。:)
re: 突破select的FD_SETSIZE限制 Kevin Lynx 2008-05-20 13:03
@2nd guest
我覺得這個(gè)東西不復(fù)雜,只要保持模塊對(duì)外接口的簡(jiǎn)潔,維護(hù)這么小的模塊不會(huì)那么復(fù)雜。
re: 我開始感到厭倦了... Kevin Lynx 2008-05-20 11:32
有同感,工作前很喜歡編程,身體越來(lái)越差,現(xiàn)在坐著就痛,編程的激情也被磨滅了。并且我薪水也低。所以很不爽。
re: 腳本編程瑣話 Kevin Lynx 2008-05-16 17:46
= = 都忘了你以前是怎樣的,貌似現(xiàn)在還可以
@xbzg
忽略即可,基本上你還需要忽略其他幾個(gè)默認(rèn)鏈接的boost庫(kù)
re: 彩虹島游戲登陸過(guò)程分析 Kevin Lynx 2008-05-14 14:43
看能不能分析下網(wǎng)絡(luò)封包?
re: 周記:找回激情 Kevin Lynx 2008-05-11 08:24
還是給個(gè)評(píng)論:
其實(shí)關(guān)于程序結(jié)構(gòu),其實(shí)就是我眼中的軟件架構(gòu),這種東西的經(jīng)驗(yàn)主要還是通過(guò)自己寫大程序總結(jié)獲得,配合設(shè)計(jì)模式軟件工程之類的理論,上升得會(huì)比較快,尤其是寫個(gè)庫(kù)出來(lái),更會(huì)挑戰(zhàn)自己這方面的能力。簡(jiǎn)單的功能封裝并不是一個(gè)庫(kù)該干的(這話熟悉吧?)當(dāng)然看其他開源庫(kù)也會(huì)獲取相關(guān)經(jīng)驗(yàn)。對(duì)于boost我不敢說(shuō)啥,很大很惶恐,只能單個(gè)小庫(kù)地仰慕一下。
自我感覺現(xiàn)在有模板編程的思想,不過(guò)這東西,僅能用于基礎(chǔ)模塊的搭建。(我很滿意我的日志類,用Andrei書中的術(shù)語(yǔ)就是policy :D和我的multi_list :D---Bugs眼中的過(guò)度設(shè)計(jì)--確實(shí)有點(diǎn)過(guò)度)
算法相關(guān)問題,我至今覺得那些書上的算法很少能帶給我們直接的實(shí)踐機(jī)會(huì)。可能你至今沒在工作中用到DP吧?不過(guò)我從不忽視算法的作用,在我眼中算法是讓人擁有堅(jiān)實(shí)編程基礎(chǔ)的東西。所以有時(shí)候解決一個(gè)問題的時(shí)候,總有點(diǎn)捉襟見肘的感覺。不過(guò)想想,沒辦法啊,環(huán)境所致。哥們你就忍了吧。
@Xw.Y
我的意思是硬件那一層(網(wǎng)絡(luò)協(xié)議棧)中的東西(鏈路層)
@test
感謝的經(jīng)驗(yàn)分享,現(xiàn)在選擇基本明了了,選lua也符合我自己的美學(xué)觀念。:D
@Qestion
Stackless Python is an enhanced version of the Python programming language. It allows programmers to reap the benefits of thread-based programming without the performance and complexity problems associated with conventional threads. The microthreads that Stackless adds to Python are a cheap and lightweight convenience which can if used properly, give the following benefits:
Improved program structure.
More readable code.
Increased programmer productivity.
似乎很有意思
@劍孤寒
貌似有個(gè)tolua++可以很輕松地解決這個(gè)問題。
re: 讓我痛苦得涕淚橫流的Qt Kevin Lynx 2008-05-05 18:00
據(jù)說(shuō)qt4與qt3(以及之前的版本)有很大變化。
我以前用QT基本上是在qt designer里做好了界面,然后再寫代碼,基本不用VS集成的那個(gè)。qmake其實(shí)挺好。
@yafare
例如?舉個(gè)例子代碼看看?(從對(duì)話框給的內(nèi)容來(lái)看,似乎就是因?yàn)楹瘮?shù)調(diào)用錯(cuò)誤)
re: 累到想吐 Kevin Lynx 2008-04-24 20:32
我也累。。~_~##
還在加班。。。
@亨德列克
不是那一行錯(cuò)了,App和Game兩個(gè)類分屬不同模塊,為了不讓兩個(gè)模塊耦合,這里使用Listener *listener = (Listener*) p,而不是(App*)p。
giscn和eXile (他刪除了他的第二條評(píng)論:) )的方法是正確的。可以被采用,再次表示感謝。
這讓我意識(shí)到,void*在C++里缺乏安全性。