Emacs 26的多線程探索

前言

春節(jié)剛過待讳,我在這里給大家拜年了,祝大家在新的一年里學(xué)習(xí)進步仰剿,事業(yè)有成创淡!在剛剛過去的2016年里,Emacs 25版本發(fā)布了南吮。按照每年發(fā)布一個大版本的慣例琳彩,2017年,期待Emacs 26版本早點發(fā)布部凑。那么露乏,你最期待的Emacs 26有哪些特性呢?不瞞你說涂邀,小編最期待的特性是多線程瘟仿。年初的時候,多線程的特性已經(jīng)合入到Master分支比勉。不過劳较,之前多線程在Mac下有一個致命的問題:一旦調(diào)用 make-thread 函數(shù)就會導(dǎo)致CPU飆升至100%,Emacs卡死浩聋。春節(jié)過后兴想,小編又試了下最新的Emacs 26的包,發(fā)現(xiàn)赡勘,那個致命的BUG得到了修復(fù),在Mac下能正常跑多線程代碼捞镰。那么闸与,今天我們簡單聊聊Emacs 26的多線程。

多線程與異步

在Emacs沒提供多線程的特性的時候岸售,如果開發(fā)者想使用異步的包践樱,那可以采用async(鏈接為:https://github.com/jwiegley/emacs-async)。這個異步包采用的是創(chuàng)建一個獨立的子進程進行后臺操作凸丸。這種異步方式最大的缺點是新的子進程遠程與Emacs主進程不共享上下文(如不共享變量),它完全是獨立的拷邢。相反,多線程的方式有一個優(yōu)點就是屎慢,多個線程間共享同一個上下文瞭稼,可修改同一個變量。但有的人認為創(chuàng)建子進程這種異步才是"正常"的異步方式腻惠。因為环肘,如果采用多線程的方式,考慮到會產(chǎn)生多個線程同時修改同個變量(或者Buffer)可能導(dǎo)致Emacs詭異行為集灌。

安裝Emacs 26開發(fā)版

要想在Emacs 26發(fā)布之前使用多線程的功能悔雹,必需升級Emacs到最新的開發(fā)版本。Mac環(huán)境下,下載Daily Build的開發(fā)版本腌零,地址為https://emacsformacosx.com/builds 梯找。我下載的是2017-02-05這天的Daily Build開發(fā)版 (版本號:26.0.50.1)。如果是Linux環(huán)境益涧,可以自己下載源代碼進行源碼編譯安裝锈锤。源碼下載

git clone --depth 1 git://git.sv.gnu.org/emacs.git

嘗鮮Emacs多線程

安裝好最新版本的Emacs后,下面我們嘗試下多線程饰躲。創(chuàng)建新的線程的函數(shù)是make-thread 牙咏,這個函數(shù)的定義如下:

(make-thread FUNCTION &optional NAME)

它的作用是創(chuàng)建一個新的線程,然后在這個線程中執(zhí)行FUNCTION這個函數(shù)嘹裂,當(dāng)函數(shù)執(zhí)行完成后退出時妄壶,這個線程就結(jié)束了。 NAME這個字符串參數(shù)是可選的寄狼,作用是對這個線程進行命名丁寄。

多線程的異步

下面,我們定義一個宏泊愧,將函數(shù)的執(zhí)行在異步線程里:

    (defmacro define-background-function-wrapper (bg-function fn)
      (let ((is-loading-sym (intern (concat "*" (symbol-name bg-function) "-is-loading*"))))
        `(progn
           (defvar ,is-loading-sym nil)
           (defun ,bg-function ()
             (interactive)
             (when ,is-loading-sym
               (message ,(concat (symbol-name fn) " is already loading")))
             (setq ,is-loading-sym t)
             (make-thread (lambda ()
                            (unwind-protect
                                (,fn)
                              (setq ,is-loading-sym nil))))))))

這個宏的作用是將函數(shù) fn 運行在異步線程里伊磺。下面是一個使用的例子

(defun aborn/log-format (origin)
  "Format `ORIGIN' log with timestamp."
  (concat (format-time-string "[%Y-%m-%d %H:%M:%S] " (current-time))
          origin))

(defun threadaction ()
  "Emacs multi-thread example runner."
  (message (aborn/log-format "begin running..."))
  (sleep-for 1)
  (message (aborn/log-format "running at point 1"))
  (sleep-for 5)
  (message (aborn/log-format "running at point 6"))
  (sleep-for 10)
  (message (aborn/log-format "running at point 16"))
  (sleep-for 15)
  (message (aborn/log-format "finished bg-runner.")))

(define-background-function-wrapper bg-threadaction threadaction)

然后我們執(zhí)行 M-x bg-threadaction 會在*Messages*這個Buffer打印出執(zhí)行日志!從日志中我們看出,在執(zhí)行異步線程時删咱,可以同步操作Emacs屑埋。

如果采用async怎么寫

上面的例子,如果采用async進行異步操作痰滋,寫法如下:

(defun async-threadaction ()
  "Emacs async example runner."
  (interactive)
  (async-start
   ;; 異步執(zhí)行更新code操作
   `(lambda ()
      ,(async-inject-variables "\\`load-path\\'")
      (require 'aborn-log)
      (message (aborn/log-format "begin running..."))
      (sleep-for 1)
      (message (aborn/log-format "running at point 1"))
      (sleep-for 5)
      (message (aborn/log-format "running at point 6"))
      (sleep-for 10)
      (message (aborn/log-format "running at point 16"))
      (sleep-for 15)
      (message (aborn/log-format "finished bg-runner."))
      )
   (lambda (result)
     (message "finished"))))

注意這里添加了這兩句:

,(async-inject-variables "\\`load-path\\'")
(require 'aborn-log)

目地是將主進程的aborn-log的上下文引入到子進程中去摘能,如果將這兩句去掉,就會報這樣的錯誤:

error in process sentinel: async-handle-result: Symbol's function definition is void: aborn/log-format

小結(jié)

以上對Emacs 26多線程簡單描述敲街,我們發(fā)現(xiàn)多線程對Emacs帶來了一種全新的編輯體驗团搞。我們在操作Emacs也不再會受后臺任務(wù)的影響。這將是Emacs 26最期待的功能多艇。想嘗鮮的同學(xué)可以下載Daily Build開發(fā)版逻恐。想要Emacs 26 Release版本的同學(xué),那只能希望Emacs 26早日發(fā)布了峻黍!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末复隆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子奸披,更是在濱河造成了極大的恐慌昏名,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阵面,死亡現(xiàn)場離奇詭異轻局,居然都是意外死亡洪鸭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門仑扑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來览爵,“玉大人,你說我怎么就攤上這事镇饮◎阎瘢” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵储藐,是天一觀的道長俱济。 經(jīng)常有香客問我,道長钙勃,這世上最難降的妖魔是什么蛛碌? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮辖源,結(jié)果婚禮上蔚携,老公的妹妹穿的比我還像新娘。我一直安慰自己克饶,他們只是感情好酝蜒,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矾湃,像睡著了一般亡脑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上邀跃,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天远豺,我揣著相機與錄音,去河邊找鬼坞嘀。 笑死,一個胖子當(dāng)著我的面吹牛惊来,可吹牛的內(nèi)容都是我干的丽涩。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼裁蚁,長吁一口氣:“原來是場噩夢啊……” “哼矢渊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起枉证,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤矮男,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后室谚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毡鉴,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡崔泵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了猪瞬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憎瘸。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖陈瘦,靈堂內(nèi)的尸體忽然破棺而出幌甘,到底是詐尸還是另有隱情,我是刑警寧澤痊项,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布锅风,位于F島的核電站,受9級特大地震影響鞍泉,放射性物質(zhì)發(fā)生泄漏皱埠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一塞弊、第九天 我趴在偏房一處隱蔽的房頂上張望漱逸。 院中可真熱鬧,春花似錦游沿、人聲如沸饰抒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽袋坑。三九已至,卻和暖如春眯勾,著一層夾襖步出監(jiān)牢的瞬間枣宫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工吃环, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留也颤,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓郁轻,卻偏偏與公主長得像翅娶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子好唯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容