网上找到的资料,整理一下发到这里。

头文件:
 1 #pragma once
 2 
 3 #include <Pm.h>
 4 #include <Winreg.h>
 5 
 6 class SuspendKiller  
 7 {
 8 public:
 9     SuspendKiller();
10     virtual ~SuspendKiller();
11 
12     BOOL StopSuspend(BOOL bFlag);
13 
14 
15 private:
16     BOOL bOverride;
17     BOOL SetBatteryTimeOuts(BOOL bFlag);
18     BOOL LoadBatteryTimeOuts();
19     BOOL NotifyChange();
20     BOOL bLoaded;
21 
22     LPCTSTR chRegKeys[3];
23     LPCWSTR lpTimeOutKey;
24     HKEY  m_hKey;
25     HANDLE hBackLight;
26 
27     DWORD bOldvalues[3];
28 
29 };

实现:
  1 /**************************************************************************************************************************
  2 
  3 Module            :    SuspendKiller
  4 Purpose            :    Avoid WinCE Device going to suspend situation
  5 
  6 Written By        :    D. Ajith Nilantha de Silva
  7 Date Written    :    05/02/2005
  8 
  9 Description        :    This class enable you to stop WinCE systems going to suspend mode.
 10 Tested with ARM4 and ARM4I (Mororolla Freescale MX21 ADS) 
 11 
 12 **************************************************************************************************************************/
 13 #include "stdafx.h"
 14 #include "SuspendKiller.h"
 15 
 16 //////////////////////////////////////////////////////////////////////
 17 // Construction/Destruction
 18 //////////////////////////////////////////////////////////////////////
 19 
 20 SuspendKiller::SuspendKiller()
 21 {
 22     //Registry sub keys that we are going to get/set timeout values
 23     chRegKeys[0]=L"BattUserIdle";
 24     chRegKeys[1]=L"BattSystemIdle";
 25     chRegKeys[2]=L"BattSuspend";
 26 
 27     //Main registry key for the timeouts 
 28     lpTimeOutKey=L"\\System\\CurrentControlSet\\Control\\Power\\Timeouts";
 29 
 30     //Set default values rather than having NULL
 31     bOldvalues[0]=120;
 32     bOldvalues[1]=180;
 33     bOldvalues[2]=240;
 34 
 35     //Initialize the variables
 36     bLoaded=FALSE;
 37     bOverride=FALSE;
 38 
 39 }
 40 
 41 SuspendKiller::~SuspendKiller()
 42 {
 43     //Check whether we have override the settings but never revers it back to original.
 44     if(bOverride)
 45         StopSuspend(FALSE); //If so revers it to original values we got
 46 
 47     CloseHandle(hBackLight); //Release the handle for the backlight
 48     hBackLight=NULL;
 49 
 50 }
 51 
 52 BOOL SuspendKiller::LoadBatteryTimeOuts(){
 53 
 54     DWORD dwType=REG_DWORD;
 55     DWORD dwSize=sizeof(DWORD);
 56 
 57     //Loads the battery timeouts from the registry and fill into the array
 58     for (int c=0;c<3;c++){
 59         RegQueryValueEx(m_hKey,chRegKeys[c],NULL,&dwType,(LPBYTE)&bOldvalues[c],&dwSize);
 60 
 61     }
 62 
 63     bLoaded=TRUE;
 64     return bLoaded;
 65 
 66 }
 67 
 68 
 69 BOOL SuspendKiller::StopSuspend(BOOL bFlag)
 70 {
 71     //Open the main Registry key for get/set operation
 72     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpTimeOutKey ,00&m_hKey)==ERROR_SUCCESS)
 73     {
 74         if (bFlag){ //If Set is requested
 75             LoadBatteryTimeOuts(); //Loads the existing settings from the registry and fill array
 76         }
 77 
 78         SetBatteryTimeOuts(bFlag); //sets the timeouts to never (0)
 79 
 80         RegCloseKey(m_hKey); //Close the Handle for Registry key
 81 
 82         NotifyChange(); //Notify power manager to reload the values from the registry
 83         return TRUE;
 84     }
 85 
 86     return FALSE;
 87 }
 88 
 89 BOOL SuspendKiller::NotifyChange()
 90 {
 91     //Gets the handle to the power manager reload activity timeout event
 92     HANDLE hevReloadActivityTimeouts=OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("PowerManager/ReloadActivityTimeouts"));
 93 
 94     //If we got valid one then invoke the event
 95     if (hevReloadActivityTimeouts) {
 96         SetEvent(hevReloadActivityTimeouts); //Set the state of the event to Signal
 97         CloseHandle(hevReloadActivityTimeouts); //close the handle of the event
 98         return TRUE;
 99     }
100     return FALSE;
101 }
102 
103 BOOL SuspendKiller::SetBatteryTimeOuts(BOOL bFlag)
104 {
105     if (bFlag){ //Reuests to set timeout to Never (0)
106 
107         DWORD data=0;  //Timeout to set
108 
109         for (int c=0;c<3;c++){ //Loop through the subkey array 
110 
111             //Set the timeout
112             RegSetValueEx(m_hKey,chRegKeys[c],0,REG_DWORD,(CONST BYTE*)&data,sizeof(DWORD));
113         }
114         //Force backlight to be power on until we release it
115         hBackLight = SetPowerRequirement(TEXT("BKL1:"), D0, POWER_NAME, NULL, 0); 
116 
117         bOverride=TRUE;
118     }        
119     else
120     {
121         if (!bLoaded && !bOverride) //If we have loaded and override then proceed
122             return FALSE;
123 
124         for (int c=0;c<3;c++){//Loop through the subkey array
125             //Restore the original timeouts we loaded from the registry
126             RegSetValueEx(m_hKey,chRegKeys[c],0,REG_DWORD,(CONST BYTE*)&bOldvalues[c],sizeof(DWORD));
127         }        
128 
129         ReleasePowerRequirement(hBackLight); //Stop forcing full power for the backlight
130 
131         //upate valiables
132         bOverride=FALSE;
133         bLoaded=FALSE;
134     }    
135 
136     return TRUE;
137 }
138 
posted @ 2008-06-17 10:48 摇滚诗人 阅读(97) | 评论 (0)编辑
 

我觉得书里对freelist的描述有点含糊,freelist其实就是一个obj*数组。

obj是实际malloc出来的内存,他里面要么是指针要么是数据,也就是那个

union obj

{

         union obj *free_list_link; //biosli注:指向下一个obj

         char client_data[1];  //或者是用户数据,后面的[]里面必须是1,不然编译器会优化掉

}//sizeof(obj)等于4,因为有指针

 

union说明obj可指向下一个同样大小的obj,也可以被用户使用。

分配完未被使用的obj连成串(利用free_list_link),freelist根据obj的大小找相应的obj*指向他。比如:128kobj串,freelist[11]就指向这个串。

 

利用freelist管理内存的设计技巧:

freelist只管obj串的头一个,就链表操作来讲,就都可以插入、删除都从obj头上下手,如果freelist相应位置指向空了说明当前大小的内存没有了,这样就走相应的流程分配内存,填充自己的obj串。

这种设计使用的条件需要链表串的内容无相关性,记录下来说不准哪天C设计中用的上。

posted @ 2008-06-16 17:29 摇滚诗人 阅读(2) | 评论 (0)编辑
阅读侯捷的《STL源码剖析》有感,于是想把这些想法记录下来。

STL也有一段时间了,容器,迭代器,算法,仿函数等等都是工作中常用的STL组件。

可是往往我们忽略了这些组件的根源——内存管理,因为这个对于STL的使用者可以说是透明的。

内存分配分为两种方式,一是直接调用C++newdelete,另一种直接调用Cmellocfree

    对于第一种形式,它的工作方式是先分配内存,然后对内存进行初始化。

    对于第二种形式,它只对其进行内存分配,不进行其他操作。

而对于SGISTL的一个实现版本),它采用了第二种形式。

今天汤小磊(Fox)同学对这种分配方式的稳定性提出了置疑:如果只分配空间,不进行初始化会不会不稳定?

从理论上讲会的,因为如果对一个对象进行内存分配,不进行初始化,那调用类中成员函数对类属性进行操作时,的确会造成未定义行为。

SGI为什么能正常的工作呢?我认为要归功于STL的巧妙设计和C++的编译器。

首先,模板是一个“编译前行为”。在进行编译前,编译器要替换所有的宏定义,即简单的把宏定义的内容进行替换,接着就要进行模板分析了。对于一个容器vector<int>int类型会被替换到vector所定义的模板中,如果是尖括号里面写的是类,则会定义一个类的类型写进去。也就是说在尖括号里填写不同的内容,就像是定义了一个不同数据结构的vector,数据操作的行为也是vector的。这样就保证了数据操作行为的一致性。

其次,我们看见的容器并完全不是我们“看见的”。咱们随便一个容器的定义(SGI版本):

template <class T, class Alloc = alloc>

class vector{…};

这后面的这个模板参数就是我们现在讨论的内存分配器。也就是说每个容器在定义的时候就已经确定了内存分配的方法,进一步说容器定义内存管理的方法是透明的。(当然这种方法可改,可是如果不看源码,这个操作就是透明的。)

第三,容器使用方法确定了内存分配行为。看一个例子:

如果尖括号里添的是类:

 

class A
{
public:
         A():m_data(
0){}
         
int getData() const
        {
                   
return m_data;
        }
        void setData(const int data)
        {
             m_data 
= data;
        }
private:
        
int m_data;
}
int main()
{
         vector
<A> testVector;
         A tempA;

         testVector.reserve(
100); //告诉vector我要用一个大小为100*sizeof(A)的内存
         for (int i = 0; i < 100++i ) //在循环中没有A的初始化、没有内存再分配
        {
            tempA.setData(i);
            testVector.push_back(tempA);
        }
}

从例子中我们看见一个类作为模板参数传给了vector,因此vector知道了类的数据结构大小。

声明tempA分配空间,并且调用A的构造函数。

调用reserve成员函数,让vector有一个“心理准备”说我要用一个100*sizeof(A)的内存。然后进入循环给tempA中的m_data赋值。

关键一步, testVector.push_back(tempA); 没有调用A的构造函数,而是直接将内存拷贝到vector事先分配好的空间里。

STL中,内存分配的方法全都用容器的成员函数包裹起来了,并且传入成员函数的参数已经被限定为一个对象,这个对象在你声明的时候已经初始化过了,因此,只要你容器用的对,就不用担心你放进容器中的对象没有初始化。这就是SGI采用mallocfree作为内存分配的巧妙之处。

posted @ 2008-04-06 16:55 摇滚诗人 阅读(13) | 评论 (0)编辑
微软的错误提示简直太高深了。高深到只看错误提示,不会明白他想告诉你什么。
先看例子:
 
class A;
typedef 
void (A::*PFUNC) (int); //定义一个指向A类成员函数的指针声明
class A
{
     PFUNC m_pFunc; 
//声明指向函数的指针
public:
     A():m_pFunc(
&A::myFunc){}; //构造函数让m_pFunc指向私有函数myFunc
      void doSomething(int a)
     {
           
/*下面这句话我尝试了一上午
             * 1. m_pFunc(a);
             * 2. *m_pFunc(a);
             * 3. *(this->m_pFunc)(a);
             * 4. this->*(this->m_pFunc) (a);
             * 
             * 全都报一个错误C2064
             
*/
           (
this->*(this->m_pFunc))(a); 
      }
private:
       
void myFunc(int a)
       {
             cout
<<a<<endl;
       }
};
int _tmain(int argc, _TCHAR* argv[]) //测试代码
{
       A myA;
       myA.doSomething(
20);
       system(
"pause");
        
return 0;
}
折腾了一上午搞那个错误C2064: term does not evalute to a function taking 1 arauents,看着好像是这句话的中心在那个“1”上,实际中心应该是“term”。然后这个“term”应该是什么样……尝试了N多种方式,只有最后那一种方式可以搞。
也许自古华山一条路是对的……除了上面那种写法,没有别的方式能在同一个类里调用一个指针函数所指向的成员。
总算整明白了~~大刀阔斧~~继续前进!!
posted @ 2008-04-02 22:38 摇滚诗人 阅读(27) | 评论 (0)编辑

在WinCE的安装工程(cab包)底下可以配置一个Setup.dll,这个东西在安装过程中被加载,并控制安装过程。

SetupDll.dll很简单里面只有四个函数:

 

SETUP_API codeINSTALL_INIT Install_Init( 

HWND hwndParent, 

BOOL fFirstCall, 

BOOL fPreviouslyInstalled, 

LPCTSTR pszInstallDir 



SETUP_API codeINSTALL_EXIT Install_Exit( 

HWND hwndParent, 

LPCTSTR pszInstallDir, 

WORD cFailedDirs, 

WORD cFailedFiles, 

WORD cFailedRegKeys, 

WORD cFailedRegVals, 

WORD cFailedShortcuts 



SETUP_API codeUNINSTALL_INIT Uninstall_Init( 

HWND hwndParent, 

LPCTSTR pszInstallDir 



SETUP_API codeUNINSTALL_EXIT Uninstall_Exit( 

HWND hwndParent 



基本的操作是这样:

在用户选择安装路径后,先执行Install_Init,在安装完成后,执行Install_Exit。

卸载时,先执行Uninstall_Init,在卸载完毕后执行Uninstall_Exit。

这里讨论一下,在安装过程中,遇到可能的情况以及传入函数的参数。

在第一次安装的时候,Install_Init会在用户选择安装路径后执行。

传入Install_Init的参数:

pszInstallDir为:用户刚选择的路径\Program Files\工程名

fFirstCall为TRUE

fPreviouslyInstall为FALSE

安装完成后,执行Install_Exit。

pszInstallDir为:用户选择的路径\Program Files\工程名

卸载时,Uninstall_Init被执行。

参数pszInstallDir为:用户安装时选择的路径\Program Files\工程名

之后执行Uninstall_Exit。

另一种情况,在用户用新的CAB对已有工程进行更新时:

系统先挂载新的CAB中的SetupDll.dll

进入新SetupDll.dll的Install_Init,传入的参数为:

pszInstallDir为:用户上次安装的路径\Program Files\工程名

fFirstCall为TRUE

fPreviouslyInstall为FALSE

之后会弹出询问用户是否卸载上次安装的对话框,如果选择“取消”则程序退出不会执行其他函数。

如果选择“确定”,则会挂载旧版本中的SetupDll.dll,进入Uninstall_Init,传入参数为:pszInstallDir为:用户上次安装的路径\Program Files\工程名

之后执行旧版本的Uninstall_Exit。

在卸载旧版本完毕后,又会出现让用户选择路径的界面:

之后又进入新版本的Install_Init,此时参数变为:

pszInstallDir为:用户新选择的路径\Program Files\工程名

fFirstCall为FALSE

fPreviouslyInstall为FALSE

安装完成后,执行Install_Exit。

pszInstallDir为:用户新选择的路径\Program Files\工程名

另外,在安装过程中,还可以通过注册表,进行新旧setupdll的交互。这种方法比较灵活,怎么方便怎么来吧\^o^/

posted @ 2008-04-02 22:33 摇滚诗人 阅读(37) | 评论 (0)编辑