Thursday, March 15, 2007

模版分离重载

用Boost::bind可以实现很多匪夷所思的绑定,比如将不同类型的参数绑定到一个函数上。在SAGE的回调函数中,希望能提供一个尽量统一的接口,使得用户可以使用function/member function来作为回调函数,回调函数的参数可以是各种类型,SAGE 将自动从输入流中读取该类型的数据并传回给回调函数。
本来想用function1来包装回调函数,以为可以轻松搞定。结果发现当T=void时,不能定义void类型的变量并作为形参……编译出错
苦思冥想了半天,终于用bind绑定函数,然后将bind的返回对象bind_t进行分离重载,重载成L=boost::_bi::list0和list1两个函数,终于搞定。
然后想用同样的方法bind绑定member function,再分离重载……谁又知member function(void)和function(T)都是L=boost::_bi::list1这样的形式……然后再苦思冥想分离……
最后:
void BindedCall( boost::_bi::bind_t〈R, F, boost::_bi::list0〉 Func ) // function(void), 不读入
void BindedCall( boost::_bi::bind_t〈R, F, boost::_bi::list1〈boost::arg〈1〉〉〉 Func ) // function(T), 读入
void BindedCall( boost::_bi::bind_t〈R, F, boost::_bi::list1〈boost::reference_wrapper〈REFT〉〉〉 Func ) // member function(void), 不读入
void BindedCall( boost::_bi::bind_t〈R, F, boost::_bi::list2〈A1,A2〉〉 Func ) // member function(T),读入
这4种形式
知道这并不好看,将就着吧。

分离的模版具体方法参见 boost::bind 和 boost::bind_t Ref:http://blog.csdn.net/lyskyly/archive/2006/10/28/1354273.aspx

Tuesday, March 13, 2007

VS2005 编译后在其他机器中不能正常载入msvcp80.dll

FAT32清单文件的问题早就提过,就不说了。
vcredist 发布包也早装了,也不管用。
曾经的问题再度困扰着我。

在痛苦了一天之后,终于明白了,因为我曾安装了VS2005 SP1 !!!
该死的微软,在安装vs2005 sp1后,dll的版本号也从8.0.50727.42变成了8.0.50727.762,在WinSxS目录下的位置自然也变化了。而竟然,vcredist发布包只提供到.42的版本,所以sp1编译出来的东西自然就找不到dll了。
该死的微软是不是忘记更新这个vc发布包了?我们难道要傻等么?
其实可以这样:
  1. 将Windows\WinSxS下对应的目录(如x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.762_x-ww_6b128700)都copy到目标机器的WinSxS下
  2. 将Windows\WinSxS\Manifests下对应的.manifest和.cat文件copy到目标机器的WinSxS\Manifests下

无论如何,VS2005是令我最头痛的一个vs版本

Boost : VC8 : x64 编译

Boost 1_33_1 thread库要在VC8下编译为amd64版本, 搜了一下发现问题挺多,而且没什么中文资料。
废话少说
  1. 修改libs/threads/src/once.cpp, 将 return ice_wrapper(&InterlockedCompareExchange, dest, exch, cmp); ==> return InterlockedCompareExchange(dest, exch, cmp); 因为Win64下InterlockedCompareExchange成为了intrinsic function
  2. vc-8_0-x86_amd64-tools.jam中修改成: VC_SETUP = "CALL \"$(VC_TOOL_PATH)\\VCVARSx86_amd64.bat\" >nul" ;
  3. 在thread目录下run: ..\..\..\..\bjam -sTOOLS="vc-8_0-x86_amd64" -sBUILD="release debug multi/single static/dynamic"

Reference:

http://article.gmane.org/gmane.comp.lib.boost.threads.devel/13

http://en.allexperts.com/q/C-1040/Building-boost-libraries-64.htm

http://steve.chinavfx.net/?p=22

Thursday, March 01, 2007

SAGE 1 核心底层70%完工

呼,接下去最大的困难是Linux环境下的调试了。不知道那个底层够不够健壮。

顺便提一下碰到的DLL包装上的问题。
一开始生成.dll却不生成.exp和.lib导入库,最后搜破头,终于发现犯了小白错误
没有__declspec(dllexport)定义dll的调用接口。然后写上了发现出来一堆warning,最后排到后来是STL的数据也需要dllexport……这个怎么弄……。最后网上搜了半天还是disable warning的解决方案。
所以Windows下DLL包装要:

# define SAGE_DECLSPEC_IMPORT __declspec(dllimport)
# define SAGE_DECLSPEC_EXPORT __declspec(dllexport)
# define SAGE_API SAGE_DECLSPEC_EXPORT
#pragma warning (disable : 4251)

其中C4251是STL需要dllexport的警告,如果显式声明就要把STL里几乎所有的东西都声明一次了……。哎,c++还是不够美啊,只能粉饰太平眼不见为净了。
而Linux下包装DLL估计就要写DEF文件了……

Friday, December 22, 2006

整理:ICE Log: Hello Demo client runtime error

Hello Demo client runtime error:
Problem:
jump a debug runtime error when invoking remote "helloword()"

Solution:
Enable RTTI in VC project. In 配置属性 - C/C++ - 语言 - 启用运行时类型信息

Reference:
http://www.zeroc.com/vbulletin/archive/index.php/t-844.html

整理:ICE Log: Hello Demo run failure

Hello Demo run failure:

Problem:
The ordinal 2604 could not be located in the dynamic link library LIBEAY32.dll

clicking ok spits this out to the console:

Quote:
server:
.\PluginManagerI.cpp:182: Ice::PluginInitializationException:
plug-in initialization failed: unable to load entry point `IceSSL:create'

Solution:
COPY libeay32.dll and ssleay32.dll from ice\bin to the working directory.
Because Windows will use SYSTEM dll before PATH.

Reference:
http://zeroc.com/vbulletin/showthread.php?t=817

整理:Current Path of ASP.net Application

ASP.net Application invokes a native dll.
The native dll need a conf file under Current Path. But what is the Current Path?
It is not the directory which the native dll locates.
Well....I found the answer is simple.
Because asp.net app is loaded by w3wp.exe, w3wp.exe is under C:\WINDOWS\system32\inetsrv
So the current path is C:\WINDOWS\system32\inetsrv !

整理:Best Practice in MS

总结一下,谈一下ms软件开发的一些best practice,个人体会
Reference: http://blog.csdn.net/shony_zhao/archive/2005/04/25/362014.aspx
1) 充分沟通:每个人都知道自己在干什么,也知道别人在干什么,同时一个代码由owner和一个xp式的buddy共同通晓,这样做review, buddy build都很方便,一个倒下了也不至于block。
2) No Pure Coder:没有纯粹的执行者,每个人都有充分的空间发挥,从feature构思到design到experiment到debug,每个人都可以作为倡导者,这样就不会有边缘人的感觉了……当然除了我,呵呵。
3) PM:PM是不懂也不管具体技术的,负责上下协调,要钱找人,控制进度,联系出行,集合玩乐,总之就是程序员们不喜欢的工作就交给PM啦。而且重要的任务还有调节男女比例,我们这里dev全是男的,2个女生PM就被捧着了,吃饭的时候明显有PM的那桌热闹。
4) 适当文档:其实ATC里代码的注释不是很多的,大段大段没有注释的代码也不少,文档也主要是Design和Spec。但是那些代码都很容易懂,当然匈牙利命名法+好的结构。当然接口定义是很详细的。
5) 包:什么都可以包,包一包就好了 。指针对象用栈对象一包,就不用管del,close了。c++用mc一包,去.net调。好东西啊。
6) 统一Error Code:统一Error Code Define,统一Error Message Map,这样就不会有冲突。
7) Feature Priority:Feature永远做不完,时间永远不够,所以定好P0,P1 ....
想到再加

整理:STL doesn't support UNICODE fully!

现在正好是写blog的时间了,因为那个按照网上的正确代码写成的程序终于开始run了。
先说一下这是如何的一件白痴事情吧:很简单,我不过是要读一个unicode文件,然后把它里面的某几行写到另外一个文件里去罢了。
OK, 看上去是小学生的题目,于是我准备正好练练手,试试看最近学到的standard c++的STL。
wstring, wfstream, wchar_t.......... everything looks correct, except the answer
好了,经过艰苦卓绝的嫌疑排查之后,疑点终于集中在wfstream上了,看上去他每次都只读写byte……(大概荒废了我一个下午)但是他是w-的啊……何况getline里面还有widen('\n')这样的操作。
经过我失败地用C style的东西改写后,work了,看来果然是wfstream的问题,不支持Unicode。
终于……看到变态的解释和解法了:

using namespace std;
typedef codecvt Mybase;
// CLASS Simple_codecvt
class Simple_codecvt : public Mybase

{
public:
typedef wchar_t _E;
typedef char _To;
typedef mbstate_t _St;
explicit Simple_codecvt(size_t _R = 0)

: Mybase(_R) {}
protected:

virtual result do_in(_St& _State, const _To *_F1, const _To *_L1, const _To *&_Mid1, _E *F2, _E *_L2, _E *&_Mid2) const
{return (noconv);}
virtual result do_out(_St& _State, const _E *_F1, const _E *_L1, const _E *&_Mid1, _To *F2, _E *_L2, _To *&_Mid2) const

{return (noconv);}
virtual result do_unshift(_St& _State, _To *_F2, _To *_L2, _To *&_Mid2) const

{return (noconv);}
virtual int do_length(_St& _State, const _To *_F1, const _To *_L1, size_t _N2) const _THROW0()

{return (_N2 < (size_t)(_L1 - _F1)? _N2 : _L1 - _F1); } virtual bool do_always_noconv() const _THROW0()
{return (true);}
virtual int do_max_length() const _THROW0()

{return (2);}
virtual int do_encoding() const _THROW0()

{return (2);}
};
#include
int _tmain(int argc, TCHAR* argv[])

{
const char *fname = "filename.txt"; // or whatever locale loc = _ADDFAC(locale::classic(), new Simple_codecvt);
wofstream myostr;

myostr.imbue(loc);
myostr.open(fname, ios_base::binary);
if (!myostr.is_open())
cerr << "can't write to " << fname << endl;
return 0;
}

算了,我承认我高估STL了,或者说是VC上的STL
不讲了,累死了,有兴趣自己看http://www.codeproject.com/vcpp/stl/upgradingstlappstounicode.asp?df=100&forumid=16224&exp=0&select=646006

整理:IIS 5 vs IIS 6

FT, 搞了半天原来真的是IIS 5和IIS 6的不同
IIS 5所有的App虽然都可以是Isolation(high),但是其本身还是在一个进程空间内,所以如果调用一个外部native dll的singleton对象,所有的App会指向同一个对象……
IIS 6就是真正的在不同进程空间内运行了,不同的App Pool终于是隔开的了
然而,xp是很难装IIS6的……

Thursday, December 21, 2006

光线跟踪MPI并行版本 STEP 1

SolidViewer_MPI 并行msmpi, Win32版本基本完工。
关键词:光线跟踪3d场景渲染,易并行,条状分割
现在在一台机器上开n个mpi进程试验成功,不过好像效率上差不多。
下一步准备研究Win64编程,然后把这个deploy到Windows Cluster上面
话说为啥Window CCS只有x64版本呢?还得我很多东西还要重新改过……

Thursday, December 07, 2006

VS2005超大bug

vs2005我装了x64编译器后(不知道没装之前有没有这个bug):
1)创建最简单win32 console,啥都不改
2)debug下直接run,显示找不到msvcr80d.dll
3)属性里把“使用标准windows库”改成“静态库使用MFC”,run,正确
4)改回“使用标准windows库”, run,就不报错了……

解决方案除了上面说的那个么,还有:
a)在“属性->配置属性->清单工具->常规“下有一个”使用FAT32解决办法,把它选成是,就可以了。(注意:一定要先配置这个选项,然后再编译工程,要不然还是不好用:)
b)到你的工程的文件夹,如(myproject),找到其下的myproject\myproject\Debug\ myproject.rec,把它删掉(删掉整个Debug目录也可以),重新编译,搞定
c)在“属性->配置属性->清单工具->输入输出”,把嵌入manifest选为否

Tuesday, August 29, 2006

自写ThreadPool+select做多线程服务端心得

ThreadPool采用message driven方式,每当select返回一个fd的read请求时,将其包装为Task,丢入ThreadPool的message queue中。等其中的Thread从queue拿出,进行处理。
有三点心得:
1)当read请求已经被包装丢入队列,但还未得到recv处理时,select依然会不停的对这个fd的read进行响应,因此当丢入队列尚未处理时,select应拒绝该fd的read,否则负载越高,越容易重复Task溢出。解决方法是再设一个fd_pending的set,记录此状态下的fd。
2)queue不应是无限长的,在达到一定长度后应拒绝入队请求,以控制负载。同时对队列操作部分要设Critical Section。
3)fd_set的系列操作都是线程不安全的,在多个线程同时操作其时,需要设Critical Section。因此要将fd_set系列操作重新包装,外面加上Enter/Leave Critical Section。