2008年11月9日星期日

Ubuntu 8.10 at Thinkpad T61

http://racklin.blogspot.com/2008/11/ubuntu-810-at-thinkpad-t61.html
http://racklin.blogspot.com/2008/11/ubuntu-810-at-thinkpad-t61.html

前幾天把 Ubuntu 8.10 Desktop Edition 64Bit 版本昇級.
昇級方法可以參考官方的這篇說明: http://www.ubuntu.com/getubuntu/upgrading

基本上所有 T61 上的硬體都能正確抓到, 包含先前提到的 Intel 4965AGN wireless LED 也一併改善解決.

然而 nvidia driver 由於 restricted driver 內建是 177.80 , 所以踩到了一個雷.


無法登出或 Ctrl+Alt+Backspace:

[G86GL] Latest NVIDIA drivers: X hangs with blank screen after logout.
阿土伯採用的是延長 GDM 等待 nvidia driver 回應的時間.
也就是請修改 /etc/gdm/gdm.conf 中的 GdmXserverTimeout 將它加大到 30 以上, 阿土伯目前使用 40.
沒有太大問題再發生.


2D performance 太慢:
nvidia driver 在 linux 上 2D 效能一直不怎麼樣, 當然官方也一直在改進, 由於 8.10 直接跳到了 177.80 版, 所以可以
使用一些新的設定, 可以參考:  http://www.nvnews.net/vbulletin/showthread.php?t=115916 討論串.
或直接在 /etc/X11/xorg.conf 加入
Option "PixmapCacheSize" "1000000"
Option "AllowSHMPixmaps" "0"

並在 ~/.gnomerc 加入
nvidia-settings -a InitialPixmapPlacement=2 -a GlyphCache=1

可以獲得很大的改善.
可以利用 firefox 打開 addons 管理視窗, 然後利用 mouse wheel scroll 看看差別有多大...




2008年9月16日星期二

iGoogle Tab RSS 小工具 Bug Fixed

http://racklin.blogspot.com/2008/09/igoogle-tab-rss-bug-fixed.html
http://racklin.blogspot.com/2008/09/igoogle-tab-rss-bug-fixed.html

感謝幾位網友的提醒, 阿土伯忘了現在 iGoogle 已不建議並(禁用?) html-inline 的 content 了..
所以造成了幾個小工具已不能使用.. 已修復完異.. 謝謝大家愛用..

什麼是 Tab RSS 請見下圖及參考說明:


使用說明及介紹:
iGoogle Tab RSS 小工具


2008年9月1日星期一

李斯諫逐客書

http://racklin.blogspot.com/2008/09/blog-post.html
http://racklin.blogspot.com/2008/09/blog-post.html

學生時唸到的古文, 沒想到在現在會這麼有感覺.
本土/外來/挺誰/嗆誰/反誰/護誰 一再操作這樣議題昇高人民對立是否得宜...
政治也是一種專業, 程式設計亦然.
當批評別人的設計有問題時, 能謙虛的自省自己的專業, 是否也出現了相同的問題, 並容納多元的意見以及不同團隊間的合作...
共勉之~

##CONTINUE##

李斯諫逐客書    李 斯
  秦宗室大臣皆言秦王曰:「諸侯人來事秦者,祇為其主遊間秦耳,請一切逐客。」李斯
議亦在逐中。斯乃上書曰:「臣聞吏議逐客,竊以為過矣。」
  「昔穆公求士,西取由余於戎,東得百里奚於宛,迎蹇叔於宋,求丕豹,公孫支於晉。
此五子者,不產於秦,而穆公用之,井國二十,遂霸西戎。孝公用商鞅之法,移風易俗,民
以殷盛,國以富彊,百姓樂用,諸侯親服獲楚,魏之師,舉地千里,至今治強。惠王用張儀
之計,拔三川之地,西井巴蜀,北收上郡,南取漢中。包九夷,制鄢郢,東據成皋之險,割
膏腴之壤,遂散六國之從,使之西面事秦,功施到今。昭王得范雎,廢穰侯,逐華陽,強公
室,杜私門,蠶食諸侯,使秦成帝業。此四君者,皆以客之功。由此觀之,客何負於秦哉!
向使四君卻客而不內,疏士而不與,是使國無富利之實,而秦無強大之名也。」
  「今陛下致昆山之玉,有隨和之寶,垂明月之珠,服太阿之劍,乘纖離之馬,建翠鳳之
旗,樹靈鼉之鼓:此數寶者,秦不生一焉,而陛下說之,何也?必秦國之所生然後可,則是
夜光之璧,不飾朝廷;犀象之器,不為玩好;鄭衛之女,不充後官;而駿馬駃騠,不實外廄
;江南金錫不為用;西蜀丹青不為采。所以飾後官,充下陳,娛心意,說耳目者,必出於秦
然後可,則是宛珠之簪,傅璣之珥,阿縞之衣?錦繡之飾,不進於前;而隨俗雅化,佳冶窈
窕,趙女不立於側也。夫擊甕叩缶,彈箏搏髀,而歌呼嗚嗚快耳者,真秦之聲也;鄭衛桑間
,韶虞武象者,異國之樂也。今棄擊甕而就鄭衛,退彈箏而取韶虞,若是者何也?快意當前
,適觀而已矣。今取人則不然,不問可否,不論曲直,非秦者去,為客者逐,然則是所重者
在乎笆樂珠玉,而所輕者在乎人民也。此非所以跨海內,致諸侯之術也。」
  「臣聞地廣者粟多,國大者人眾,兵強者士勇。是以泰山不讓士壤,故能成其大;河海
不擇細流,故能就其深;王者不卻眾庶,故能明其德。是以地無四,方民無異國,四時充美
,鬼神降福
。此五帝,三王之所以無敵也。今乃棄黔首以資敵國,卻賓客以業諸侯,使天下
之士退而不敢西向,裹足不入秦,此所謂『藉寇兵而齎盜糧』者也。」
  「夫物不產於秦,可寶者多;士不產於秦,而願忠者眾。今逐客以資敵國,損民以益讎
,內自虛而外樹怨於諸侯,求國無危,不可得也
。」
  秦王乃除逐客之令,復李斯官。
大意:
   (一)自「秦宗室大臣皆言秦王曰」至「竊以為過矣」
     說明逐客為過。
   (二)自「昔穆公求士」至「而秦無強大之名也」
     (舉繆公、孝公、惠王、昭王例)說明客有功於秦(暗示逐客為不智)。
   (三)自「今陛下致昆山之玉」至「致諸侯之術也」
     說明逐其民人而取其色樂珠玉,非王霸者之所為(以色樂珠玉之取襯客之去為不
     合理)。
   (四)自「臣聞地廣者粟多」至「此所謂藉寇兵而齎盜糧者也」
     說明卻客而為他國所用,非秦之福(以逐客資敵業諸侯說明爭取人才的重要性)
     。
   (五)自「夫物不產於秦」至「不可得也」
     說明逐客則國危。
   (六)自「秦王乃除逐客之令」至「復李斯官」
     記敘李斯復官。

2008年8月18日星期一

GREUtils 1.1 in trunk

http://racklin.blogspot.com/2008/08/greutils-11-in-trunk.html
http://racklin.blogspot.com/2008/08/greutils-11-in-trunk.html

GREUtils 1.1 已經 update 到 http://greutils.googlecode.com/svn/trunk 中, 有興趣參考 Source Code 或使用, 請利用 svn checkout .

GREUtils 是一個 XULRunner / Firefox extensions Javascript Utilities Libraries.
1.0 到 1.1 基本上是全面改寫, GREUtils 1.1 提供以下功能:
  • Object extend function
  • include / include_once specified URL script.
  • XPCOM utilities
  • Charset Convert
  • Preferences Services
  • File IO
  • Dialog utilities (all XPCOM implemented, can use in javascript code modules)
  • Controller and CommandDispatcher? Helper
  • Cryphto Hash Utilities – md5 / sha1 /sha256
  • JSON encode / decode use XPCOM implemented (VERY FASTer then json.org's javascript version)
  • Threading – Native Multi-Threading support
  • JavaScript code modules support

其它改變:
  • GREUtils 1.1 全部改寫了 1.0 的 inline document , 由 ScriptDoc 改成了 jsdoc 格式, 以方便產生出 API Reference.
  • Makefile for linux user , 以方便產生 minified / packed / jsmodues / jsdoc 等 distribution files.
  • singleton support
  • inherits / namespace support (many idea and source from goog javascript libraries).
Project URL: http://code.google.com/p/greutils/

API References: http://greutils.googlecode.com/svn/trunk/jsdoc/index.html

2008年7月4日星期五

Threading in Firefox 3

http://racklin.blogspot.com/2008/07/threading-in-firefox-3.html
http://racklin.blogspot.com/2008/07/threading-in-firefox-3.html

Firefox 3 (Gecko 1.9) 新增了許多特色 (詳見 ), 其中一項重要的特色, 便是導入了 Thread Manager 機制.

##CONTINUE##

在 Firefox 3 以前, 我們要讓 Javascript 程式在背景執行, 最簡單的方式便是利用 setTimeout / setInterval 方式:


function backgroundTask() {
// Perform a small amount of work

window.setTimeout(arguments.callee, 100);
}

window.setTimeout(backgroundTask, 100);

以上的方式雖然可以把程式丟到背景執行, 然而, 它依然只是在主執行緒(mainThread)中, 以非同步的方式執行.

Firefox 3 後, 導入了 Thread Manager , 讓我們可以撰寫平台相關的真正多執行緒程式.

要實作多執行緒 Javascript 程式,本身必須是 XPCOM Object, 且實作 nsIRunnable 介面(和 Java Thread 很像不是嗎?).
詳細範例可參考 Thread Manager nsIThreadManager .

Thread Utils:
雖然 Firefox 3 已經大大簡化了多執行緒程式的寫作方式(且很有 Java 風格), 但就 Javascript 來說, 就顯的有些麻煩, 我們要為每一個要執行的程式, 一一實作成 XPCOM Object 也是一件很煩人的事..
阿土伯在 GREUtils Rewriting 計劃中, 為 Threading 做了一些封裝, 讓您可以比較容易且直覺的使用 Firefox 3 所帶來的 Multi-Threading 這份大禮.

有關 Thread 部份的 Code 如下, 已修改過可以獨立運作於 GREUtils 整個專案之外:

/**
* Thread - is simple and easy use Thread Manager APIs libraries for GRE (Gecko Runtime Environment).
* ONLY Work with Firefox 3 or XULRunner 1.9
*
* @public
* @name GREUtils.Thread
* @namespace GREUtils.Thread
*/
var GREUtils = GREUtils || {};

GREUtils.Thread = {

_threadManager: Components.classes["@mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager),

_mainThread: null,

_workerThread: null,

reportError: function(err){
Components.utils.reportError(err);
}
};


/**
* getThreadManager
*
* @public
* @static
* @function
* @return {Object} nsIThreadManager
*/
GREUtils.Thread.getThreadManager = function(){
return this._threadManager;
};


/**
* getMainThread
*
* @public
* @static
* @function
* @return {Object} nsIThread main thread
*/
GREUtils.Thread.getMainThread = function(){
if (this._mainThread == null) {
this._mainThread = GREUtils.Thread.getThreadManager().mainThread;

// extends magical method to worker thread
// this._workerThread.dispatchMainThread = GREUtils.Thread.dispatchMainThread;
}
return this._mainThread;
};


/**
* dispatchMainThread
*
* @public
* @static
* @function
* @return {Object} nsIThreadManager
* @param {Object} aRunnable
* @param {Object} aType
*/
GREUtils.Thread.dispatchMainThread = function(aRunnable, aType) {
var mainThread = GREUtils.Thread.getMainThread();
var aType = aType || mainThread.DISPATCH_NORMAL;
try {
mainThread.dispatch(aRunnable, aType);
}catch (err) {
GREUtils.Thread.reportError(err);
}
};


/**
* dispatchWorkerThread
*
* @public
* @static
* @function
* @return {Object} nsIThreadManager
* @param {Object} workerThread
* @param {Object} aRunnable
* @param {Object} aType
*/
GREUtils.Thread.dispatchWorkerThread = function(workerThread, aRunnable, aType) {
var aType = aType || workerThread.DISPATCH_NORMAL;
try {
workerThread.dispatch(aRunnable, aType);
}catch (err) {
GREUtils.Thread.reportError(err);
}
};

/**
* getWorkerThread in pool
*
* @public
* @static
* @function
* @return {Object} nsIThread worker thread
*/
GREUtils.Thread.getWorkerThread = function(){
// get presist work thread
// will not create new worker thread
if (this._workerThread == null) {
this._workerThread = GREUtils.Thread.getThreadManager().newThread(0);

// extends magical method to worker thread
// this._workerThread.dispatchMainThread = GREUtils.Thread.dispatchMainThread;
}
return this._workerThread;
};


/**
* createWorkerThread - create new worker thread.
*
* @public
* @static
* @function
* @return {Object} nsIThread worker thread
*/
GREUtils.Thread.createWorkerThread = function(){
// create new worker thread
var worker = GREUtils.Thread.getThreadManager().newThread(0);

// extends magical method to worker thread
//worker.dispatchMainThread = GREUtils.Thread.dispatchMainThread;

return worker;
};


/**
* CallbackRunnableAdapter
*
* @public
* @class
* @param {Object} func
* @param {Object} data
*/
GREUtils.Thread.CallbackRunnableAdapter = function(func, data) {
this._func = func;
this._data = data;
};

GREUtils.Thread.CallbackRunnableAdapter.prototype = {

get func() {
return this._func;
},

set func(func){
this._func = func || null;
},

get data() {
return this._data;
},

set data(data){
this._data = data || null;
},

run: function() {
try {
if (this.func) {
if(this.data) this.func(this.data);
else this.func();
}
} catch (err) {
Components.utils.reportError(err);
}
},

QueryInterface: function(iid) {
if (iid.equals(Components.Interfaces.nsIRunnable) || iid.equals(Components.Interfaces.nsISupports)) {
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};


/**
* WorkerRunnableAdapter
*
* @public
* @class
* @param {Object} func
* @param {Object} callback
* @param {Object} data
*/
GREUtils.Thread.WorkerRunnableAdapter = function(func, callback, data) {
this._func = func;
this._callback = callback;
this._data = data;

if(arguments.length == 2 ) {
this._data = callback;
this._callback = null;
}
};

GREUtils.Thread.WorkerRunnableAdapter.prototype = {

get func() {
return this._func;
},

set func(func){
this._func = func || null;
},

get callback() {
return this._callback;
},

set callback(callback){
this._callback = callback || null;
},

get data() {
return this._data;
},

set data(data){
this._data = data || null;
},

run: function() {
try {
var result = null;
if (this.func) {
if(this.data) result = this.func(this.data);
else result = this.func();
}

if (this.callback) {
GREUtils.Thread.dispatchMainThread(new GREUtils.Thread.CallbackRunnableAdapter(this.callback, result));
}
} catch (err) {
Components.utils.reportError(err);
}

},

QueryInterface: function(iid) {
if (iid.equals(Components.Interfaces.nsIRunnable) || iid.equals(Components.Interfaces.nsISupports)) {
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};


/**
* createWorkerThreadAdapter
*
* @public
* @static
* @function
* @param {Object} workerFunc
* @param {Object} callbackFunc
* @param {Object} data
*/
GREUtils.Thread.createWorkerThreadAdapter = function(workerFunc, callbackFunc, data) {

return new GREUtils.Thread.WorkerRunnableAdapter(workerFunc, callbackFunc, data);
};


使用方式:
利用 GREUtils.Thread.getMainThread() 可以取得主執行緒.
利用 GREUtils.Thread.createWorkerThread() 產生一個新的執行緒.

WorkerThreadAdapter:
則是用以簡化自行撰寫 worker / callback 二個 XPCOM Object, 取而代之的是二個 Function handle 以及要傳入 worker thread 的資料.


var worker = GREUtils.Thread.createWorkerThread();
var execute = GREUtils.Thread.createWorkerThreadAdapter(
/* worker function */
function(data) {
var result = 0;
var i = 0;

while(i <= data) {
result += i;
i++;
}
return result;
},
/* callback function */
function(result) {
alert('sum = ' + result);
},
/* data to worker function */
10000
);

GREUtils.Thread.dispatchWorkerThread(worker, execute);



註1:
Firefox3 的 Thread 由於是以 XPCOM 實作, 所以您只能用於 extension addons 寫作或是 XULRunner 專案中, 如果您需要在一般 Web Application 中使用多執行緒, 可以參考 Google Gears 的 WorkerPool 實作.

註2:
請特別注意 The Thread Manager 那篇的這句重要的警告.
Note: The DOM is not thread safe. You must not access the DOM or user interface from background threads. Doing so will likely crash.
其中要再注意的是, alert() 也是 DOM global scope 哦, 如果您在 background threads 用了 alert(), Firefox 3 也是會當給你看地.


忙裡偷閒寫下本篇, 內容有點雜亂簡單, 但還是希望對大家有幫助.