[fw]multi-thread concepts

January 9th, 2014 by bettermanlu

1.1 Atomicity Violation

http://www.parallellabs.com/2010/11/13/concurrency-bugs-1/

http://www.parallellabs.com/2010/11/23/concurrency-bugs-2/

 

http://docs.oracle.com/cd/E19205-01/820-0619/geojs/index.html

1.2 What is a Data Race?

The Thread Analyzer detects data-races that occur during the execution of a multi-threaded process. A data race occurs when:

  • two or more threads in a single process access the same memory location concurrently, and
  • at least one of the accesses is for writing, and
  • the threads are not using any exclusive locks to control their accesses to that memory.

When these three conditions hold, the order of accesses is non-deterministic, and the computation may give different results from run to run depending on that order. Some data-races may be benign (for example, when the memory access is used for a busy-wait), but many data-races are bugs in the program.

 

1.3 What is a Deadlock?

Deadlock describes a condition in which two or more threads are blocked (hung) forever because they are waiting for each other. There are many causes of deadlocks. The Thread Analyzer detects deadlocks that are caused by the inappropriate use of mutual exclusion locks. This type of deadlock is commonly encountered in multi-threaded applications. A process with two or more threads can deadlock when the following conditions hold:

  • Threads that are already holding locks request new locks
  • The requests for new locks are made concurrently
  • Two or more threads form a circular chain in which each thread waits for a lock which is held by the next thread in the chain

Here is a simple example of a deadlock condition:

Thread 1 holds lock A and requests lock B
Thread 2 holds lock B and requests lock A

 

 

A deadlock can be of two types: A potential deadlock or an actual deadlock. A potential deadlock does not necessarily occur in a given run, but can occur in any execution of the program depending on the scheduling of threads and the timing of lock requests by the threads. An actual deadlock is one that occurs during the execution of a program. An actual deadlock causes the threads involved to hang, but may or may not cause the whole process to hang.

 

  • Comments Off
  • Posted in java

[fw]Android network connection listener example code

November 13th, 2013 by bettermanlu

http://www.xinotes.org/notes/note/1526/

  1. With standalone broadcast receiver
    • AndroidManifest.xml:
      <?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="com.android.networkreceiver"
            android:versionCode="1"
            android:versionName="1.0">
          <uses-sdk android:minSdkVersion="8"/>
          <application android:label="@string/app_name" android:icon="@drawable/icon">
      	<receiver android:name="NetworkReceiver">
      	    <intent-filter>
      		<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
      	    </intent-filter>
      	</receiver>
          </application>
      </manifest>
    • Java code:
      package com.android.networkreceiver;
      
      import android.content.BroadcastReceiver;
      import android.content.Context;
      import android.content.Intent;
      import android.net.ConnectivityManager;
      import android.net.NetworkInfo;
      import android.util.Log;
      
      public class NetworkReceiver extends BroadcastReceiver {
          private static final String LOGTAG = "NetworkReceiver";
      
          @Override
          public void onReceive(Context ctx, Intent intent) {
      	Log.i(LOGTAG, "Action: " + intent.getAction());
          	if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
      	    NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
      	    String typeName = info.getTypeName();
      	    String subtypeName = info.getSubtypeName();
      	    boolean available = info.isAvailable();
      	    Log.i(LOGTAG, "Network Type: " + typeName 
      			+ ", subtype: " + subtypeName
      			+ ", available: " + available);
      	}
          }
      }
  2. Register listener inside Activity programmatically
    • AndroidManifest.xml:
      <?xml version="1.0" encoding="utf-8"?>
      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="com.android.networklistener"
            android:versionCode="1"
            android:versionName="1.0">
          <uses-sdk android:minSdkVersion="8"/>
          <application android:label="@string/app_name" android:icon="@drawable/icon">
                  <activity android:name="NetworkListenerActivity"
                        android:label="@string/app_name">
                  <intent-filter>
                      <action android:name="android.intent.action.MAIN" />
                      <category android:name="android.intent.category.LAUNCHER" />
                  </intent-filter>
              </activity>
          </application>
      </manifest>
    • Java code:
      package com.android.networklistener;
      
      import android.app.Activity;
      import android.os.Bundle;
      import android.content.BroadcastReceiver;
      import android.content.Context;
      import android.content.IntentFilter;
      import android.content.Intent;
      import android.net.ConnectivityManager;
      import android.net.NetworkInfo;
      import android.util.Log;
      import android.widget.TextView;
      
      public class NetworkListenerActivity extends Activity {
          private static final String LOGTAG = "NetworkListenerActivity";
      
          private IntentFilter mNetworkStateChangedFilter;
          private BroadcastReceiver mNetworkStateIntentReceiver;
          private String mTypeName = "Unknown";
          private String mSubtypeName = "Unknown";
          private boolean mAvailable = false;
      
          private TextView statusField;
      
          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
      
      	mNetworkStateChangedFilter = new IntentFilter();
      	mNetworkStateChangedFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
      
      	mNetworkStateIntentReceiver = new BroadcastReceiver() {
      	    @Override
      	    public void onReceive(Context context, Intent intent) {
      		if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
      		    NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
      		    mTypeName = info.getTypeName();
      		    mSubtypeName = info.getSubtypeName();
      		    mAvailable = info.isAvailable();
      		    Log.i(LOGTAG, "Network Type: " + mTypeName 
      				+ ", subtype: " + mSubtypeName
      				+ ", available: " + mAvailable);
      		    updateScreen();
      		}
      	    }
      	};
      
              setContentView(R.layout.main);
          }
      
          private void updateScreen() {
      	statusField = (TextView) findViewById(R.id.networkStatus);
      	statusField.setText("Network Type: " + mTypeName + "\n"
      			  + "Network subtype: " + mSubtypeName + "\n"
      			  + "Available: " + mAvailable);
          }
      
          @Override
          protected void onResume() {
      	Log.d(LOGTAG, "onResume");
      	super.onResume();
      	registerReceiver(mNetworkStateIntentReceiver, mNetworkStateChangedFilter);
      	unregisterReceiver(mNetworkStateIntentReceiver);
      	registerReceiver(mNetworkStateIntentReceiver, mNetworkStateChangedFilter);
          }
      
          @Override
          protected void onPause() {
      	Log.d(LOGTAG, "onPause");
      	super.onPause();
      	unregisterReceiver(mNetworkStateIntentReceiver);
          }
      }

    Register/unregister broadcast receiver in onResume/onPause works because the connectivity change broadcast is sticky. I intentionally used two registerReceiver calls in onResume to demonstrate this - onReceive will be called once for each registration.

[fwd]posts : Android–Multithreading in a UI environment

October 31st, 2013 by bettermanlu

1. Android – Multithreading in a UI environment

http://www.aviyehuda.com/blog/2010/12/20/android-multithreading-in-a-ui-environment/

Why do we need multithreading in Android applications?
Let’s say you want to do a very long operation when the user pushes a button.
If you are not using another thread, it will look something like this:

 

1 ((Button)findViewById(R.id.Button01)).setOnClickListener(          
2              new OnClickListener() {
3       
4          @Override
5          public void onClick(View v) {
6             int result = doLongOperation();
7             updateUI(result);
8          }
9       });

What will happen?
The UI freezes. This is a really bad UI experience. The program may even crash.

The problem in using threads in a UI environment
So what will happen if we use a Thread for a long running operation.
Let’s try a simple example:

01 ((Button)findViewById(R.id.Button01)).setOnClickListener(
02 new OnClickListener() {
03          
04          @Override
05          public void onClick(View v) {
06             
07             (new Thread(new Runnable() {
08                
09                @Override
10                public void run() {
11                     int result = doLongOperation();
12                     updateUI(result);
13                }
14             })).start();
15             
16          }

The result in this case is that the application crashes.
12-07 16:24:29.089: ERROR/AndroidRuntime(315): FATAL EXCEPTION: Thread-8
12-07 16:24:29.089: ERROR/AndroidRuntime(315): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
12-07 16:24:29.089: ERROR/AndroidRuntime(315): at ...

Clearly the Android OS wont let threads other than the main thread change UI elements.

But why?
Android UI toolkit, like many other UI environments, is not thread-safe.

The solution

  • A queue of messages. Each message is a job to be handled.
  • Threads can add messages.
  • Only a single thread pulls messages one by one from the queue.

 

The same solution was implemented in swing (Event dispatching thread
and SwingUtilities.invokeLater() )

 
Handler
The Handler is the middleman between a new thread and the message queue.
Option 1 – Run the new thread and use the handler to send messages for ui changes

01 final Handler myHandler = new Handler(){
02    @Override
03 public void handleMessage(Message msg) {
04       updateUI((String)msg.obj);
05 }
06    
07 };
08
09 (new Thread(new Runnable() {
10    
11    @Override
12    public void run() {
13       Message msg = myHandler.obtainMessage();
14       
15       msg.obj = doLongOperation();
16       
17       myHandler.sendMessage(msg);
18    }
19 })).start();

* keep in mind that updating the UI should still be a short operation, since the UI freezes during the updating process.

Other possibilities:
handler.obtainMessage with parameters
handler.sendMessageAtFrontOfQueue()
handler.sendMessageAtTime()
handler.sendMessageDelayed()
handler.sendEmptyMessage()

 

Option 2 – run the new thread and use the handler to post a runnable which updates the GUI.

01 final Handler myHandler = new Handler();
02             
03             (new Thread(new Runnable() {
04                
05                @Override
06                public void run() {
07                   final String res = doLongOperation();
08                   myHandler.post(new Runnable() {
09                      
10                      @Override
11                      public void run() {
12                         updateUI(res);
13                      }
14                   });
15                }
16             })).start();
17             
18          }

android multithreading

Looper
If we want to dive a bit deeper into the android mechanism we have to understand what is a Looper.
We have talked about the message queue that the main thread pulls messages and runnables from it and executes them.
We also said that each handler you create has a reference to this queue.
What we haven’t said yet is that the main thread has a reference to an object named Looper.
The Looper gives the Thread the access to the message queue.
Only the main thread has executes to the Looper by default.

Lets say you would like to create a new thread and you also want to take advantage of the message queue functionality in that thread.

01 (new Thread(new Runnable() {
02
03                   @Override
04                   public void run() {
05
06                      innerHandler = new Handler();
07                      
08                      Message message = innerHandler.obtainMessage();
09                      innerHandler.dispatchMessage(message);
10                   }
11                })).start();

Here we created a new thread which uses the handler to put a message in the messages queue.

This will be the result:
12-10 20:41:51.807: ERROR/AndroidRuntime(254): Uncaught handler: thread Thread-8 exiting due to uncaught exception
12-10 20:41:51.817: ERROR/AndroidRuntime(254): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
12-10 20:41:51.817: ERROR/AndroidRuntime(254): at android.os.Handler.(Handler.java:121)
12-10 20:41:51.817: ERROR/AndroidRuntime(254): at ...

The new created thread does not have a Looper with a queue attached to it. Only the UI thread has a Looper.
We can however create a Looper for the new thread.
In order to do that we need to use 2 functions: Looper.prepare() andLooper.loop().

01 (new Thread(new Runnable() {
02
03                @Override
04                public void run() {
05
06                   Looper.prepare();
07                   innerHandler = new Handler();
08                         
09                   Message message = innerHandler.obtainMessage();
10                   innerHandler.dispatchMessage(message);
11                   Looper.loop();
12                }
13             })).start();

 

If you use this option, don’t forget to use also the quit() function so the Looper will not loop for ever.

1 @Override
2    protected void onDestroy() {
3       innerHandler.getLooper().quit();
4       super.onDestroy();
5    }

 

AsyncTask
I have explained to you that a Handler is the new thread’s way to communicate with the UI thread.
If while reading this you were thinking to yourself, isn’t there an easier way to do all of that… well, you know what?! There is.

Android team has created a class called AsyncTask which is in short a thread that can handle UI.

Just like in java you extend the class Thread and a SwingWorker in Swing, in Android you extend the class AsyncTask.
There is no interface here like Runnable to implement I’m afraid.

01 class MyAsyncTask extends AsyncTask<Integer, String, Long> {
02       
03       @Override
04       protected Long doInBackground(Integer... params) {
05          
06          long start = System.currentTimeMillis();
07          for (Integer integer : params) {
08             publishProgress("start processing "+integer);
09             doLongOperation();
10             publishProgress("done processing "+integer);
11          }
12          
13          return start - System.currentTimeMillis();
14       }
15
16       
17       
18       @Override
19       protected void onProgressUpdate(String... values) {
20          updateUI(values[0]);
21       }
22       
23       @Override
24       protected void onPostExecute(Long time) {
25          updateUI("Done with all the operations, it took:"+
26                                      time + " millisecondes");
27       }
28
29       @Override
30       protected void onPreExecute() {
31          updateUI("Starting process");
32       }
33       
34       
35       public void doLongOperation() {
36          
37          try {
38             Thread.sleep(1000);
39          catch (InterruptedException e) {
40             e.printStackTrace();
41          }
42          
43       }
44       
45     }

 

This is how you start this thread:

1 MyAsyncTask aTask = new MyAsyncTask();
2 aTask.execute(12345);

 

AsyncTask defines 3 generic types:
AsyncTask<{type of the input}, {type of the update unit}, {type of the result}>
You don’t have to use all of them – simply use ‘Void’ for any of them.

 

Notice that AsyncTask has 4 operations, which are executed by order.
1. onPreExecute() – is invoked before the execution.
2. onPostExecute() - is invoked after the execution.
3. doInBackground() - the main operation. Write your heavy operation here.
4. onProgressUpdate() – Indication to the user on progress. It is invoked every time publishProgress() is called.

* Notice: doInBackground() is invoked on a background thread where onPreExecute(), onPostExecute() and onProgressUpdate() are invoked on the UI thread since their purpose is to update the UI.

Android developer website also mentions these 4 rules regarding the AsyncTask:

  • The task instance must be created on the UI thread.
  • execute(Params…) must be invoked on the UI thread.
  • Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params…), onProgressUpdate(Progress…) manually.
  • The task can be executed only once (an exception will be thrown if a second execution is attempted.)

Timer + TimerTask
Another option is to use a Timer.
Timer is a comfortable way to dispatch a thread in the future, be it once or more.

Instead of doing this:

01 Runnable threadTask = new Runnable() {
02    
03    @Override
04    public void run() {
05       
06       while(true){
07          try {
08             Thread.sleep(2000);
09          catch (InterruptedException e) {
10             e.printStackTrace();
11          }
12          
13          doSomething();
14       }
15    }
16 };
17    
18 (new Thread(threadTask)).start();

do this:

1 TimerTask timerTask = new TimerTask() {     
2    @Override
3    public void run() {
4       doSomething();      
5    }
6 };
7
8 Timer timer = new Timer();
9 timer.schedule(timerTask, 2000,2000);

which is a bit more elegant.

Bare in mind, you still have to use Handler if you need to do UI operations.

Download sources:

zip Download demo project 1
zip Download demo project 2

 

2. Toast和Looper。Handler消息循环机制。

http://jeff-pluto-1874.iteye.com/blog/869710

(1) Looper类别用来为一个线程开启一个消息循环。默认情况下Android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环)

Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。

 

(2) 通常是通过Handler对象来与Looper交互的。Handler可看做是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。

默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,在主线程中定义,其是与主线程的Looper绑定。

mainHandler = new Handler() 等价于new Handler(Looper.myLooper()).

Looper.myLooper():Return the Looper object associated with the current thread 获取当前进程的looper对象。

还有一个类似的 Looper.getMainLooper() 用于获取主线程的Looper对象。

 

(3) 在非主线程中直接new Handler() 会报如下的错误:

E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()

原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。

 

(4) Looper.loop(); 让Looper开始工作,从消息队列里取消息,处理消息。

注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。

 

(5) 基于以上知识,可实现主线程给子线程(非主线程)发送消息。

[fw]Activity的Launch mode详解 singleTask正解

June 29th, 2013 by bettermanlu

http://www.cnblogs.com/xiaoQLu/archive/2011/09/29/2195742.html

Activity有四种加载模式:standard(默认), singleTop, singleTask和 singleInstance。以下逐一举例说明他们的区别:

 

standard:Activity的默认加载方法,即使某个Activity在Task栈中已经存在,另一个activity通过Intent跳转到该activity,同样会新创建一个实例压入栈中。例如:现在栈的情况为:A B C D,在D这个Activity中通过Intent跳转到D,那么现在的栈情况为: A B C D D 。此时如果栈顶的D通过Intent跳转到B,则栈情况为:A B C D D B。此时如果依次按返回键,D  D C B A将会依次弹出栈而显示在界面上。

 

singleTop:如果某个Activity的Launch mode设置成singleTop,那么当该Activity位于栈顶的时候,再通过Intent跳转到本身这个Activity,则将不会创建一个新的实例压入栈中。例如:现在栈的情况为:A B C D。D的Launch mode设置成了singleTop,那么在D中启动Intent跳转到D,那么将不会新创建一个D的实例压入栈中,此时栈的情况依然为:A B C D。但是如果此时B的模式也是singleTop,D跳转到B,那么则会新建一个B的实例压入栈中,因为此时B不是位于栈顶,此时栈的情况就变成了:A B C D B。

 

singleTask:如果某个Activity是singleTask模式,那么Task栈中将会只有一个该Activity的实例。例如:现在栈的情况为:A B C D。B的Launch mode为singleTask,此时D通过Intent跳转到B,则栈的情况变成了:A B。而C和D被弹出销毁了,也就是说位于B之上的实例都被销毁了。

关于singleTask这个网上颇有争议,包括google api上的说明也让我看的是一头雾水,自己用实例亲测,终于算是搞清楚了

正解:1.singleTask 并不一定处于栈底

2.singleTask 并一定会是栈底的根元素

3.singleTask 并不一定会启动新的task

情况一:如果在本程序中启动singleTask的activity:假设ActivityA是程序的入口,是默认的模式(standard),ActivityB是singleTask 模式,由ActivityA启动,刚ActivityB不会位于栈底,不是根元素,不会启动新的task,此种情况ActivityB会和ActivityA在一个栈中,位于ActivityA上面

情况二:如果ActivityB由另外一个程序启动:假设apkA是情况一中的应用,apkB是测试程序,在apkB中启动apkA中的ActivityB,刚ActivityB会位于栈底,是根元素,会启动新的task

注意:singleTask模式的Activity不管是位于栈顶还是栈底,再次运行这个Activity时,都会destory掉它上面的Activity来保证整个栈中只有一个自己,切记切记

singleInstance:将Activity压入一个新建的任务栈中。例如:Task栈1的情况为:A B C。C通过Intent跳转到D,而D的Launch mode为singleInstance,则将会新建一个Task栈2。此时Task栈1的情况还是为:A B C。Task栈2的情况为:D。此时屏幕界面显示D的内容,如果这时D又通过Intent跳转到D,则Task栈2中也不会新建一个D的实例,所以两个栈的情况也不会变化。而如果D跳转到C,则栈1的情况变成了:A B C C,因为C的Launch mode为standard,此时如果再按返回键,则栈1变成:A B C。也就是说现在界面还显示C的内容,不是D。

好了,现在有一个问题就是这时这种情况下如果用户点击了Home键,则再也回不到D的即时界面了。如果想解决这个问题,可以为D在Manifest.xml文件中的声明加上:

 

<intent-filter>

<action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.LAUNCHER” />

</intent-filter>

 

加上这段之后,也就是说该程序中有两个这种声明,另一个就是那个正常的根activity,在打成apk包安装之后,在程序列表中能看到两个图标,但是如果都运行的话,在任务管理器中其实也只有一个。上面的情况点击D的那个图标就能回到它的即时界面(比如一个EditText,以前输入的内容,现在回到之后依然存在)。

 

PS:intent-filter中 <action android:name=”android.intent.action.MAIN” />和 <category android:name=”android.intent.category.LAUNCHER” />两个过滤条件缺一不可才会在程序列表中添加一个图标,图标下的显示文字是android:label设定的字符串。

[fw][ATL]An excellent tutorial: ATL and Connection Points

December 23rd, 2012 by bettermanlu

http://users.iafrica.com/d/da/dart/zen/Articles/ATLConnectionPoints/ATLConnectionPoints.html

Introduction: This article shows how to implement connection points using ATL. This can be done automatically using the AppWizard etc. I chose not to use this method for two reasons. Firstly there seems to be a bug with VC++ 6.0 (I assume its fixed in the service pack), and secondly I wanted to see how it was done.

This is not a full “article” but rather a step-by-step guide to show you how its done.

 


The COM DLL


Create a COM DLL

  • Start a new project – ATL COM AppWizard
  • Use defaults – click finish

Need a COM object

  1. Add ATL object (on Insert menu/ ClassWizard)
  2. Select “Simple Object”
  3. Name object
  4. Do not modify attributes – (ie leave “Support Connection Points” unchecked!)

Add an interface for the events

  1. open the “.idl” file – FileView in “Source Files” folder
  2. Modify to add events, insert the text indicated by the numbers 1 and 2 on the images
  3. Add new CLSID (generated using uuidgen or whatever)

The events interface should now be displayed on the ClassView tab, this means that you can add methds to this interface like any other interface created by ClassView
Add an event

  1. Right click on the event interface (ClassView) and select “Add Method”
  2. Type “OnTest” in the “Method Name” edit box
  3. Click ok – the interface now has a method, the event

Compile the project

  1. This compiles the MIDL files and creates the type libraries
    Always do this before adding support for a event/connection point

Add connection point support to the COM object

  1. Right click the COM object (class view) and select “Implement Connection Point”
  2. Check the event interface box
  3. Click okThe COM object now supports connection points, specifically the event interface you created. VC++ will create a class called “CProxyIxxxx” which will define methods to invoke the events (search for a IConnectionPoint and fire it).
  4. Repeat this evertime you add new events, this will ensure that the Fire_XXX methods are generated

Add a method to the COM object

  1. Right click on the object interface
  2. Add a method called “DoTest”

Make the DoTest method fire the event

  1. Double click the “DoTest” method (on the CConnectionTst class, not the interface)
  2. Add a messagebox so that you will know when the method is called
  3. Add a call to “Fire_OnTest()” wich will call the event handler, if the client application is connected

Build the project.

  1. The COM DLL (source) is ready.

 


The Test Application

 

Create a new “MFC AppWizard(exe)” project

  1. Page 1 – Select “dialog based”
  2. Page 2 – Use defaults, select “Finished”

Setup dialog

  1. Drop a button onto the dialog box
  2. Double click the button to create the OnClick handler

Interface definition includes

  1. Right click the “Source Files” (FileView)” folder
  2. Select “Add File to Folder”
  3. Select the “ConnectDemo_i.c” file from the COM DLL project This file contains the CLSIDs
  4. Right click this file in FileView
  5. Select the “Not using precompiled headers” If you dont do this VC++ will not compile this file
  6. Go back to the “ConnectTestDlg.cpp” file (dialog implementation)
    Add a #include to the “ConnectDemo.h” file from the COM DLL project
    This file defines the interfaces etc

Add ATL support

  1. There may be a more elegant way to do this, but this works…
  2. Select “New ATL Object” from the Insert menu
  3. Click “yes” when asked if you would like to add ATL support
  4. Click cancel – dont add an ATL object

Add a COM class which will connect to the DLL

  1. inherit from IDispatchImpl
  2. param 1 – IConnectionTstEvents – Events interface
  3. param 2 – &IID_IConnectionTstEvents – Events interface CLSID
  4. param 3 – &CLSID_ConnectionTst – CLSID of DLL in which events reside
  5. inherit from CComObjectRoot
  6. Add constructor
  7. Add COM_MESSAGE_MAP
    Add entry for IDispatch and IConnectionTstEvents
  8. Add all methods from event interface, in this case only OnTest
  9. Define action for event handler

OnButton1 code

  1. Call CoInitialize
  2. Init the global CComModule variable (_Module)
  3. Create an instance of the CTstConnect class
  4. Call CreateInstance to return a pointer to the IID_IConnectionTst interface
  5. Create an instance of the client object (CTstConnect)
  6. Call DoTest – test what happens when not connected
  7. Call AtlAdvise to connect to server
  8. Call DoTest – event will now be fired
  9. Call AltUnAdvise – disconnect
  10. Call DoTest – no event will be fired
  11. Release server object
  12. Call CoUninitialize

[fw][ATL]Handling COM Events in ATL

December 23rd, 2012 by bettermanlu

http://resources.esri.com/help/9.3/arcgisdesktop/com/com/vcpp/events.htm

Below is a summary of terminology used here when discussing COM events in Visual C++ and ATL.

Inbound interface This is the normal case where a COM object implements a predefined interface.

Outbound Interface This is an interface of methods that a COM object will fire at various times. For example, the Map coclass will fire an event on the IActiveViewEvents in response to changes in the map.

Event Source The source COM object will fire events to an outbound interface when certain actions occur. For example, the Map coclass is a source of IActiveViewEvents and will fire theIActiveViewEvents::ItemAdded event when a new layer is added to the map. The source object can have any number of clients, or event sink objects , listening to events. Also, a source object may have more than one outbound interface; for example, the Map coclass also fires events on an IMapEvents interface. An event source will typically declare its outbound interfaces in IDL with the [source] tag.

Event Sink A COM object that listens to events is said to be a “sink” for events. The sink object implements the outbound interface; this is not always advertised in the type libraries because the sink may listen to events internally. An event sink typically  uses the connection point mechanism to register its interest in the events of a source object.

Connection Point COM objects that are the source of events typically use the connection point mechanism to allow sinks to hook up to a source. The connection point interfaces are the standard COM interfaces IConnectionPointContainer and IConnectionPoint .

Fire Event When a source object needs to inform all the sinks of a particular action, the source is said to “fire” an event. This results in the source iterating all the sinks and making the same method call on each. For example, when a layer is added to a map, the Map coclass is said to fire the ItemAdded event. So all the objects listening to the Map‘s outbound IActiveViewEvents interface will be called on their implementation of the ItemAdded method.

Advise and unadvise events To begin receiving events, a sink object is said to “advise” a source object that it needs to receive events. When events are no longer required, the sink will unadvise the source.

The ConnectionPoint Mechanism

The source object implements the IConnectionPointContainer interface to allow sinks to query a source for a specific outbound interface. The following steps are performed to begin listening to an event. ATL implements this with the AtlAdvise method.

  1. The sink will QI the source object’s IConnectionPointContainer and call FindConnectionPoint to supply an interface ID for outbound interfaces. To be able to receive events, the sink object must implement this interface.
  2. The source may implement many outbound interfaces and will return a pointer to a specific connection point object implementing IConnectionPoint to represent one outbound interface.
  3. The sink calls IConnectionPoint::Advise, passing a pointer to its own IUnknown implementation. The source will store this with any other sinks that may be listening to events. If the call to Advisewas successful, the sink will be given an identifier (a simple unsigned long value, called a cookie) to give back to the source at a later point when it no longer needs to listen to events.The connection is now complete; methods will be called on any listening sinks by the source. The sink will typically hold on to an interface pointer to the source, so when a sink has finished listening it can be released from the source object by calling IConnectionPoint::Unadvise. This is implemented with AtlUnadvise.

Connection point mechanism for hooking source to sink objects

[fw][HTTP] HTTP Cookies

December 22nd, 2012 by bettermanlu

Cookies

Cookies allow web servers to store state information in the browser. They are often used to store session variables, user preferences, or user identity. Cookies are not part of the HTTP specification; however, they have become ubiquitous and are sometimes needed for proper interactions with some web sites.

Cookies work in the following way: when a server program wishes to store state information in the client, the server issues a Set-Cookie header its response to the client, which contains the value it wishes to store. The client is expected to store the information from the Set-Cookie header, associated with the URL or domain that issues the cookie. In subsequent requests to that URL or domain, the client should include the cookie information using the Cookie header. The server or CGI program uses this information to return a document tailored to that specific client. The server can set an expiration date for the cookie, or just use it for a session that will not survive beyond the current instance of the browser.

For example, the client may fill in a form opening a new account. The request might read:

POST /sales.ora.com/order.pl HTTP/1.0
[Client headers here]

type=new&firstname=John&lastname=Smith

The server stores this information along with a new account ID, and sends it back in the response:

HTTP/1.0 200 OK
[Server headers here]
Set-Cookie: acct=04382374;domain=.ora.com;Expires=Sun, 16-Feb-2003 04:38:14 GMT;Path=/

The next time the browser visits the site, the client should recognize that a cookie is needed, and send:

GET /order.pl HTTP/1.0
[Client headers here]
Cookie: acct=04382374

More details about cookies are available at:

http://www.netscape.com/newsref/std/cookie_spec.html

[fw]FPO

December 15th, 2012 by bettermanlu

http://blogs.msdn.com/b/larryosterman/archive/2007/03/12/fpo.aspx

FPO

 I was chatting with one of the perf guys last week and he mentioned something that surprised me greatly.  Apparently he’s having perf issues that appear to be associated with a 3rd party driver.  Unfortunately, he’s having problems figuring out what’s going wrong because the vendor wrote the driver used FPO (and hasn’t provided symbols), so the perf guy can’t track the root cause of the problem.

The reason I was surprised was that I didn’t realize that ANYONE was using FPO any more.

What’s FPO?

To know the answer, you have to go way back into prehistory.

Intel’s 8088 processor had an extremely limited set of registers (I’m ignoring the segment registers), they were:

 

AX BX CX DX IP
SI DI BP SP FLAGS

 

With such a limited set of registers, the registers were all assigned specific purposes.  AX, BX, CX, and DX were the “General Purpose” registers, SI and DI were “Index” registers, SP was the “Stack Pointer”, BP was the “Frame Pointer”, IP was the “Instruction Pointer”, and FLAGS was a read-only register that contained several bits that were indicated information about the processors’ current state (whether the result of the previous arithmetic or logical instruction was 0, for instance).

The BX, SI, DI and BP registers were special because they could be used as “Index” registers.  Index registers are critically important to a compiler, because they are used to access memory through a pointer.  In other words, if you have a structure that’s located at offset 0×1234 in memory, you can set an index register to the value 0×1234 and access values relative to that location.  For example:

MOV    BX, [Structure]
MOV    AX, [BX]+4

Will set the BX register to the value of the memory pointed to by [Structure] and set the value of AX to the WORD located at the 4th byte relative to the start of that structure.

One thing to note is that the SP register wasn’t an index register.  That meant that to access variables on the stack, you needed to use a different register, that’s where the BP register came from - the BP register was dedicated to accessing values on the stack.

When the 386 came out, they stretched the various registers to 32bits, and they fixed the restrictions that only BX, SI, DI and BP could be used as index registers.

 

EAX EBX ECX EDX EIP
ESI EDI EBP ESP FLAGS

 

This was a good thing, all of a sudden, instead of being constrained to 3 index registers, the compiler could use 6 of them.

Since index registers are used for structure access, to a compiler they’re like gold – more of them is a good thing, and it’s worth almost any amount of effort to gain more of them.

Some extraordinarily clever person realized that since ESP was now an index register the EBP register no longer had to be dedicated for accessing variables on the stack.  In other words, instead of:

MyFunction:
PUSH    EBP
MOV     EBP, ESP
SUB      ESP, <LocalVariableStorage>
MOV     EAX, [EBP+8]
:
:
MOV     ESP, EBP
POP      EBP
RETD

to access the 1st parameter on the stack (EBP+0 is the old value of EBP, EBP+4 is the return address), you can instead do:

MyFunction:
SUB      SP, <LocalVariableStorage>
MOV     EAX, [ESP+4+<LocalVariableStorage>]
:
:
ADD     SP, <LocalVariableStorage>
RETD

This works GREAT – all of a sudden, EBP can be repurposed and used as another general purpose register!  The compiler folks called this optimization “Frame Pointer Omission”, and it went by the acronym FPO.

But there’s one small problem with FPO.

If you look at the pre-FPO example for MyFunction, you’d notice that the first instruction in the routine was PUSH EBP followed by a MOV EBP, ESP.  That had an interesting and extremely useful side effect.  It essentially created a singly linked list that linked the frame pointer for each of the callers to a function.  From the EBP for a routine, you could recover the entire call stack for a function.  This was unbelievably useful for debuggers – it meant that call stacks were quite reliable, even if you didn’t have symbols for all the modules being debugged.  Unfortunately, when FPO was enabled, that list of stack frames was lost – the information simply wasn’t being tracked.

To solve the is problem, the compiler guys put the information that was lost when FPO was enabled into the PDB file for the binary.  Thus, when you had symbols for the modules, you could recover all the stack information.

FPO was enabled for all Windows binaries in NT 3.51, but was turned off for Windows binaries in Vista because it was no longer necessary – machines got sufficiently faster since 1995 that the performance improvements that were achieved by FPO weren’t sufficient to counter the pain in debugging and analysis that FPO caused.

 

Edit: Clarified what I meant by “FPO was enabled in NT 3.51″ and “was turned off in Vista”, thanks Steve for pointing this out.

[HTTP]所有 HTTP 状态代码及其定义

July 14th, 2012 by bettermanlu

所有 HTTP 状态代码及其定义。
代码 指示
2xx 成功
200 正常;请求已完成。
201 正常;紧接 POST 命令。
202 正常;已接受用于处理,但处理尚未完成。
203 正常;部分信息 — 返回的信息只是一部分。
204 正常;无响应 — 已接收请求,但不存在要回送的信息。
3xx 重定向
301 已移动 — 请求的数据具有新的位置且更改是永久的。
302 已找到 — 请求的数据临时具有不同 URI。
303 请参阅其它 — 可在另一 URI 下找到对请求的响应,且应使用 GET 方法检索此响应。
304 未修改 — 未按预期修改文档。
305 使用代理 — 必须通过位置字段中提供的代理来访问请求的资源。
306 未使用 — 不再使用;保留此代码以便将来使用。
4xx 客户机中出现的错误
400 错误请求 — 请求中有语法问题,或不能满足请求。
401 未授权 — 未授权客户机访问数据。
402 需要付款 — 表示计费系统已有效。
403 禁止 — 即使有授权也不需要访问。
404 找不到 — 服务器找不到给定的资源;文档不存在。
407 代理认证请求 — 客户机首先必须使用代理认证自身。
415 介质类型不受支持 — 服务器拒绝服务请求,因为不支持请求实体的格式。
5xx 服务器中出现的错误
500 内部错误 — 因为意外情况,服务器不能完成请求。
501 未执行 — 服务器不支持请求的工具。
502 错误网关 — 服务器接收到来自上游服务器的无效响应。
503 无法获得服务 — 由于临时过载或维护,服务器无法处理请求。
———————————————————————————————————————–
HTTP 400 – 请求无效
HTTP 401.1 – 未授权:登录失败
HTTP 401.2 – 未授权:服务器配置问题导致登录失败
HTTP 401.3 – ACL 禁止访问资源
HTTP 401.4 – 未授权:授权被筛选器拒绝
HTTP 401.5 – 未授权:ISAPI 或 CGI 授权失败
HTTP 403 – 禁止访问
HTTP 403 – 对 Internet 服务管理器 (HTML) 的访问仅限于 Localhost
HTTP 403.1 禁止访问:禁止可执行访问
HTTP 403.2 – 禁止访问:禁止读访问
HTTP 403.3 – 禁止访问:禁止写访问
HTTP 403.4 – 禁止访问:要求 SSL
HTTP 403.5 – 禁止访问:要求 SSL 128
HTTP 403.6 – 禁止访问:IP 地址被拒绝
HTTP 403.7 – 禁止访问:要求客户证书
HTTP 403.8 – 禁止访问:禁止站点访问
HTTP 403.9 – 禁止访问:连接的用户过多
HTTP 403.10 – 禁止访问:配置无效
HTTP 403.11 – 禁止访问:密码更改
HTTP 403.12 – 禁止访问:映射器拒绝访问
HTTP 403.13 – 禁止访问:客户证书已被吊销
HTTP 403.15 – 禁止访问:客户访问许可过多
HTTP 403.16 – 禁止访问:客户证书不可信或者无效
HTTP 403.17 – 禁止访问:客户证书已经到期或者尚未生效
HTTP 404.1 – 无法找到 Web 站点
HTTP 404 – 无法找到文件
HTTP 405 – 资源被禁止
HTTP 406 – 无法接受
HTTP 407 – 要求代理身份验证
HTTP 410 – 永远不可用
HTTP 412 – 先决条件失败
HTTP 414 – 请求 – URI 太长
HTTP 500 – 内部服务器错误
HTTP 500.100 – 内部服务器错误 – ASP 错误
HTTP 500-11 服务器关闭
HTTP 500-12 应用程序重新启动
HTTP 500-13 – 服务器太忙
HTTP 500-14 – 应用程序无效
HTTP 500-15 – 不允许请求 global.asa
Error 501 – 未实现
HTTP 502 – 网关错误

  • Comments Off
  • Posted in HTTP

[Forward][python]How do I pass a variable by reference?

September 20th, 2011 by bettermanlu

http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference

Question

The Python documentation seems unclear about whether parameters are passed by reference or value, and the following code produces the unchanged value ‘Original’

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.Change(self.variable)
        print self.variable

    def Change(self, var):
        var = 'Changed'

Is there something I can do to pass the variable by actual reference?

Answer

Parameters are passed by value. The reason people are confused by the behaviour is twofold:

  1. the parameter passed in is actually a reference to a variable (but the reference is passed by value)
  2. some data types are mutable, but others aren’t

So, if you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart’s delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you’re done, the outer reference will still point at the original object. If out pass an immutable object to a method, you still can’t rebind the outer reference, and you can’t even mutate the object.

Okay, this is a little confusing. Let’s have some examples.

List – a mutable type

Let’s try to modify the list that was passed to a method:

def try_to_change_list_contents(the_list):
    print 'got', the_list
    the_list.append('four')
    print 'changed to', the_list

outer_list = ['one', 'two', 'three']

print 'before, outer_list =', outer_list
try_to_change_list_contents(outer_list)
print 'after, outer_list =', outer_list

Output:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']

Since the parameter passed in is a reference to outer_list, not a copy of it, we can use the mutating list methods to change it and have the changes reflected in the outer scope.

Now let’s see what happens when we try to change the reference that was passed in as a parameter:

def try_to_change_list_reference(the_list):
    print 'got', the_list
    the_list = ['and', 'we', 'can', 'not', 'lie']
    print 'set to', the_list

outer_list = ['we', 'like', 'proper', 'English']

print 'before, outer_list =', outer_list
try_to_change_list_reference(outer_list)
print 'after, outer_list =', outer_list

Output:

before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']

Since the the_list parameter was passed by value, assigning a new list to it had no effect that the code outside the method could see. The the_list was a copy of the outer_list reference, and we had the_list point to a new list, but there was no way to change where outer_list pointed.

String – an immutable type

It’s immutable, so there’s nothing we can do to change the contents of the string

Now, let’s try to change the reference

def try_to_change_string_reference(the_string):
    print 'got', the_string
    the_string = 'In a kingdom by the sea'
    print 'set to', the_string

outer_string = 'It was many and many a year ago'

print 'before, outer_string =', outer_string
try_to_change_string_reference(outer_string)
print 'after, outer_string =', outer_string

Output:

before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago

Again, since the the_string parameter was passed by value, assigning a new string to it had no effect that the code outside the method could see. The the_string was a copy of theouter_string reference, and we had the_string point to a new list, but there was no way to change where outer_string pointed.

I hope this clears things up a little.

EDIT: It’s been noted that this doesn’t answer the question that @David originally asked, “Is there something I can do to pass the variable by actual reference?”. Let’s work on that.

How do we get around this?

As @Andrea‘s answer shows, you could return the new value. This doesn’t change the way things are passed in, but does let you get the information you want back out:

def return_a_whole_new_string(the_string):
    new_string = something_to_do_with_the_old_string(the_string)
    return new_string

# then you could call it like
my_string = return_a_whole_new_string(my_string)

If you really wanted to avoid using a return value, you could create a class to hold your value and pass it into the function or use an existing class, like a list:

def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
    new_string = something_to_do_with_the_old_string(stuff_to_change[0])
    stuff_to_change[0] = new_string

# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)

do_something_with(wrapper[0])

Although this seems a little cumbersome.

 

Reference

Immutable object

http://en.wikipedia.org/wiki/Immutable_object

In object-oriented and functional programming, an immutable object is an object whose state cannot be modified after it is created.[1] This is in contrast to a mutable object, which can be modified after it is created. In some cases, an object is considered immutable even if some internally used attributes change but the object’s state appears to be unchanging from an external point of view. For example, an object that uses memoization to cache the results of expensive computations could still be considered an immutable object.

Immutable objects are often useful because they are inherently thread safe.[1] Other benefits are that they are simpler to understand and reason about and offer higher security than mutable objects.[1]

However, making an object immutable is usually inappropriate if the object contains a large amount of changeable data. Because of this, many languages allow for both immutable and mutable objects.

Python

In Python some built-in types (numbers, strings, tuples, frozensets) are immutable, but custom classes are generally mutable. To simulate immutability in a class, one should override attribute setting and deletion to raise exceptions:

class Immutable(object):
     """An immutable class with a single attribute 'value'."""
     def __setattr__(self, *args):
         raise TypeError("can't modify immutable instance")
     __delattr__ = __setattr__
     def __init__(self, value):
         # we can no longer use self.value = value to store the instance data
         # so we must explicitly call the superclass
         super(Immutable, self).__setattr__('value', value)
  • Comments Off
  • Posted in python

« Previous Entries