re: CEnumClass—類型安全的枚舉類型 Kevin Lynx 2008-08-13 10:05
我覺得,用你這個類與普通的enum相比,更多時候我們需要的是一個方便的enum,即使它沒有你這個class安全;
如果我沒弄錯的話,你這個類雖然sizeof為sizeof(int),但這并不是你所說的“同時也沒有占用任何額外的空間”,因為還有很多static常量。
@陳梓瀚(vczh)
就我所查閱的文檔來看,似乎沒有。coroutine.yiled/resume可能算是吧。
re: 自己寫的一個GUI框架的消息機制 Kevin Lynx 2008-08-07 09:17
@eXile
我亦覺得,樓主局限于native win32的思維方式。在對消息的處理上,遵從的是WIN32的消息機制。
不過從代碼看來(LRESULT之類),這個框架可能沒有考慮跨平臺特性。所以停留在WINDOWS上也沒什么。
個人拙見。:)
re: 建立異步操作組件:隊列和線程 Kevin Lynx 2008-08-06 13:11
@francis
thread2沒有獲得CPU權!thread2沒有被調度!
這里的用法完全是條件變量的標準用法,如果你硬是要從理論上認為它有問題,那你可以去查條件變量相關資料。這里的結構和條件變量通用用法一樣。你甚至可以找本操作系統書,在上面找到條件變量的使用結構。你想推翻這一切?建議你大量查閱條件變量相關資料。如果你還認為有問題,你應該去對發明條件變量的某個可能已經死掉的牛人說:你這個條件變量的結構有問題。
re: 建立異步操作組件:隊列和線程 Kevin Lynx 2008-08-06 09:07
@francis
我讀了幾遍你的這次回復,希望我沒有誤解你的意思:
thread1被激活,取數據,就可能導致container的size為0,一旦size為0,thread3繼續push的時候就可能會激活thread2。如果OS一直沒有調度到thread2,那么,container就可能經歷過多次size為0,size不為0,也就是thread1和thread3發生多次數據交互。thread2看起來是慘了,因為container曾經有數據,但是thread2卻沒取到?為什么呢?thread2根本沒被OS調度到,從沒有獲取到CPU控制權,它又有什么理由不wait?
歸根結底,你說的這個問題,只是因為thread2沒有被調度到而已。
re: 建立異步操作組件:隊列和線程 Kevin Lynx 2008-08-05 09:00
@francis
詳述下這種會出現問題的情況。如果可以模擬出現的話,麻煩基于multi_list這個類制造這種情況。
re: 建立異步操作組件:隊列和線程 Kevin Lynx 2008-08-04 22:28
@francis
while( _container.size() == 0 ) _condition.wait();
僅當為空的情況下才wait的。代碼在邏輯上不存在大問題,因為這個基礎部件已經被用于實際項目(用于保存驗證服務器端的驗證帳號)。
re: 建立異步操作組件:隊列和線程 Kevin Lynx 2008-08-04 16:43
@francis
我們看一次常規的同步操作:
push_front()
{
guard<mutex_type> g(_mutex );
...
}
pop_front()
{
guadr<mutex_type> g(_mutex );
...
}
那么,在消費者線程里可能會不斷地去檢查隊列大小是否為0(size操作同樣會涉及到同步),
這浪費了CPU資源。而如果:
pop_front()
{
guadr<mutex_type> g(_mutex );
while( size == 0 ) _cond.wait();
}
當大小為0時,wait操作將阻塞此線程,從而讓出了CPU資源(wait會阻塞)。
另一方面,如果每次push操作都進行條件變量的signal,這個所謂的原語操作開銷有多大?
查看condition::signal/wait代碼,其內部還存在一個_wait_count的同步。另外,如果
每次push都signal的話,那么pop操作也需要進行wait,這樣以來它其實已經不是條件變量,
而是信號量了。
我們所要的效果,就是在隊列元素為0時,進行pop操作的時候讓其阻塞而已。
re: 建立異步操作組件:隊列和線程 Kevin Lynx 2008-08-04 12:55
@francis
關鍵在于,signal和wait會對外部mutex做操作。參見kl_condition.h相關代碼。
re: 建立異步操作組件:隊列和線程 Kevin Lynx 2008-08-03 10:40
@francis
你可以查找‘條件變量’(condition variable)的相關資料。
signal只在隊列尺寸為0時的push操作中調用,因為在pop中會在隊列尺寸為0時wait.
re: 實現自己的http server Kevin Lynx 2008-08-01 16:08
@Strive
很巧, 我恰好看過這個網站,感覺是個少年天才的主頁。之前搜索QQ協議,發現的。還下了他寫的QQ客戶端,不過有問題,我登陸Q后,就被T了。
re: 實現自己的http server Kevin Lynx 2008-07-31 08:56
@zx
高并發數不見得要使用async(不明白你所謂的Async模式是什么?我假設是異步IO),也不見得要使用Overlapped IO (我也不明白你說的"IO的overlapped",我假設是windows下的Overlapped IO),一個event-driven的網路模型就很不錯了。
@x-matrix
本文的重點在于對HTTP協議的解析,而不是開發高并發網絡框架。:)
re: GP技術的展望——先有鴻鈞后有天 Kevin Lynx 2008-07-26 22:33
longshanks終于又發文了。學習。
@happyday
取元素只是從樹根取,取了后需要對整棵樹進行調整。
插入元素插入到最下最右的節點,插入后需要進行微小的調整。
總之元素的增加/減少,都需要重新調整整棵樹使其依然為一個堆。
re: 日志該怎么記錄? Kevin Lynx 2008-07-18 10:48
越來越寫得水了。
@true
那就應該沒問題了。‘應用程序初始化失敗’,你用的是VS2005吧?那就跟BOOST沒關系了。新的問題跟項目設定有關系。具體搜索下網絡吧。:)
我以前編譯ASIO例子程序的時候,就顯示地忽略了以下兩個庫:
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則沒遇到過,你顯示地忽略掉看下如何?
re: VS2005編譯libevent Kevin Lynx 2008-07-07 12:53
libevent在windows下似乎沒多大實用價值(因為用的是select)。spserver的作者寫了個IOCP版本。
貌似是有這樣的現象,例如libevent的VC6工程文件用RAR解開后就是壞的。
re: GameRes里面某位大師的語錄 Kevin Lynx 2008-06-26 21:51
‘游戲之家站長’的故事源遠流長。。。
偶然發現LZ博客有我以前CSDN的鏈接,呵呵,現在我換到CPPBLOG來了,更新下鏈接吧。
re: 建立異步操作組件:隊列和線程[未登錄] Kevin Lynx 2008-06-26 09:14
@飯中淹
前面我說了,condition和guard使用的是同一個mutex,在condition的wait里,會先_external_mutex.release();,然后push的時候,就不會阻塞在guard那里,于是condition.signal(元素為0時,看下代碼),然后pop里的condition.wait就過了。
re: 建立異步操作組件:隊列和線程 Kevin Lynx 2008-06-25 21:42
@飯中淹
不會的,condition和guard使用的都是同一個mutex。guard用于一般的同步,condition用于隊列元素為0時的臨界條件。
re: 為什么很多人喜歡在代碼中寫錯別字呢[未登錄] Kevin Lynx 2008-06-25 17:13
@true
事實上是我寫的. :D 我寫著玩,但是被用到我們的產品里。
re: 為什么很多人喜歡在代碼中寫錯別字呢[未登錄] Kevin Lynx 2008-06-25 16:41
比較有意思的:
/// 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: 建立異步操作組件:隊列和線程[未登錄] Kevin Lynx 2008-06-25 16:22
@true
貌似你誤解我意思了;)
’阻塞時不能退出‘:
例如線程里 WaitFor...INFINITE了,那么它就無法處理消息,也無法判斷退出標志變量,代碼卡在這里了。
’他更及時,不用參與排隊‘:
這個跟上面不是說的同一個問題,隊列是用于實際業務處理,例如寫日志,上面那個說的是線程。
re: 從wave文件的讀寫看程序中struct的設計 Kevin Lynx 2008-06-16 11:21
有道理,對于用struct寫文件這種情況,很容易因為struct的字節對齊問題導致想不到的BUG。尤其是采用直接將struct以二進制方式寫入文件的方式寫文件。
re: SGI STL的內存池 Kevin Lynx 2008-06-15 09:40
@Gohan
rebind可以讓allocator<Tp>的保存者分配其他類型的內存。例如,當實例化list時(例如list<int,my_allocator<int> > ),在list內部就保存著一個my_allocator<int>,但是list需要為自己分配list_node,就是說它需要另一個allocator,那么這個時候就可以通過rebind來完成。
re: SGI STL的內存池 Kevin Lynx 2008-06-13 12:36
@關中刀客
STL默認那個內存池。。。STL默認沒內存池。SGI的STL里那個內存池不是標準的。VC下的STL就沒這個。
re: (C++)一個愚蠢的錯誤 Kevin Lynx 2008-06-07 09:27
錯誤就是 memset( ...string ) ?
有點巧,我同事也犯過這個錯。:D
@關中刀客
難道不開源?不知道能否分享下代碼。
我之前在google,baidu都搜索過你這個東西,沒有發現類似googlecode之類的項目地址。。
re: IRR的效果圖 Kevin Lynx 2008-06-06 16:21
@true
這些是irrlicht引擎的DEMO圖
@關中刀客
傳說哥們和我同年同月差一天就同日生(我10號:d)
還有,一直想看下你的cobra是個什么東西
re: 寫了個簡單的聊天服務器 Kevin Lynx 2008-06-06 10:59
@jigloo
"網絡層用reactor模式封裝異步IO" 似乎proactor才是用于封裝異步IO的吧?
關于你提出的這幾層封裝,不知道是否可以提供個簡單的整體類圖?不甚感激。
re: 【原創】系統設計之 必備外圍功能-log Kevin Lynx 2008-06-05 17:50
日志對于一個系統來說確實是必不可少的基礎模塊。
我用模板寫了個不依賴于具體‘寫’的日志類,簡單的日志等級過濾。
///
/// @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下也可以調用GetAsyncKeyState
re: 突破select的FD_SETSIZE限制 Kevin Lynx 2008-05-20 14:24
@eXile
謝謝提醒,win_fd_set_adapter.hpp確實是個方案。那估計是用__WSAFDIsSet也不是問題了。:)
re: 突破select的FD_SETSIZE限制 Kevin Lynx 2008-05-20 13:03
@2nd guest
我覺得這個東西不復雜,只要保持模塊對外接口的簡潔,維護這么小的模塊不會那么復雜。
re: 我開始感到厭倦了... Kevin Lynx 2008-05-20 11:32
有同感,工作前很喜歡編程,身體越來越差,現在坐著就痛,編程的激情也被磨滅了。并且我薪水也低。所以很不爽。
re: 腳本編程瑣話 Kevin Lynx 2008-05-16 17:46
= = 都忘了你以前是怎樣的,貌似現在還可以
re: ACE與ASIO之間關于Socket編程的比較 Kevin Lynx 2008-05-15 19:56
@xbzg
忽略即可,基本上你還需要忽略其他幾個默認鏈接的boost庫
re: 彩虹島游戲登陸過程分析 Kevin Lynx 2008-05-14 14:43
看能不能分析下網絡封包?
re: 周記:找回激情 Kevin Lynx 2008-05-11 08:24
還是給個評論:
其實關于程序結構,其實就是我眼中的軟件架構,這種東西的經驗主要還是通過自己寫大程序總結獲得,配合設計模式軟件工程之類的理論,上升得會比較快,尤其是寫個庫出來,更會挑戰自己這方面的能力。簡單的功能封裝并不是一個庫該干的(這話熟悉吧?)當然看其他開源庫也會獲取相關經驗。對于boost我不敢說啥,很大很惶恐,只能單個小庫地仰慕一下。
自我感覺現在有模板編程的思想,不過這東西,僅能用于基礎模塊的搭建。(我很滿意我的日志類,用Andrei書中的術語就是policy :D和我的multi_list :D---Bugs眼中的過度設計--確實有點過度)
算法相關問題,我至今覺得那些書上的算法很少能帶給我們直接的實踐機會。可能你至今沒在工作中用到DP吧?不過我從不忽視算法的作用,在我眼中算法是讓人擁有堅實編程基礎的東西。所以有時候解決一個問題的時候,總有點捉襟見肘的感覺。不過想想,沒辦法啊,環境所致。哥們你就忍了吧。
re: tcp要點學習-基礎概念 Kevin Lynx 2008-05-09 18:08
@Xw.Y
我的意思是硬件那一層(網絡協議棧)中的東西(鏈路層)
re: lua和python誰更適用于嵌入MMORPG? Kevin Lynx 2008-05-08 09:22
@test
感謝的經驗分享,現在選擇基本明了了,選lua也符合我自己的美學觀念。:D
re: lua和python誰更適用于嵌入MMORPG? Kevin Lynx 2008-05-07 16:06
@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.
似乎很有意思
re: lua和python誰更適用于嵌入MMORPG? Kevin Lynx 2008-05-06 19:15
@劍孤寒
貌似有個tolua++可以很輕松地解決這個問題。
re: 讓我痛苦得涕淚橫流的Qt Kevin Lynx 2008-05-05 18:00
據說qt4與qt3(以及之前的版本)有很大變化。
我以前用QT基本上是在qt designer里做好了界面,然后再寫代碼,基本不用VS集成的那個。qmake其實挺好。
re: 調試經驗總結-VC下的錯誤對話框 Kevin Lynx 2008-04-28 09:15
@yafare
例如?舉個例子代碼看看?(從對話框給的內容來看,似乎就是因為函數調用錯誤)
re: 累到想吐 Kevin Lynx 2008-04-24 20:32
我也累。。~_~##
還在加班。。。
@亨德列克
不是那一行錯了,App和Game兩個類分屬不同模塊,為了不讓兩個模塊耦合,這里使用Listener *listener = (Listener*) p,而不是(App*)p。
giscn和eXile (他刪除了他的第二條評論:) )的方法是正確的。可以被采用,再次表示感謝。
這讓我意識到,void*在C++里缺乏安全性。