Emacs 26的多线程探索

前言

春节刚过,我在这里给大家拜年了,祝大家在新的一年里学习进步,事业有成!在刚刚过去的2016年里,Emacs 25版本发布了。按照每年发布一个大版本的惯例,2017年,期待Emacs 26版本早点发布。那么,你最期待的Emacs 26有哪些特性呢?不瞒你说,小编最期待的特性是多线程。年初的时候,多线程的特性已经合入到Master分支。不过,之前多线程在Mac下有一个致命的问题:一旦调用 make-thread 函数就会导致CPU飙升至100%,Emacs卡死。春节过后,小编又试了下最新的Emacs 26的包,发现,那个致命的BUG得到了修复,在Mac下能正常跑多线程代码。那么,今天我们简单聊聊Emacs 26的多线程。

多线程与异步

在Emacs没提供多线程的特性的时候,如果开发者想使用异步的包,那可以采用async(链接为:https://github.com/jwiegley/emacs-async)。这个异步包采用的是创建一个独立的子进程进行后台操作。这种异步方式最大的缺点是新的子进程远程与Emacs主进程不共享上下文(如不共享变量),它完全是独立的。相反,多线程的方式有一个优点就是,多个线程间共享同一个上下文,可修改同一个变量。但有的人认为创建子进程这种异步才是"正常"的异步方式。因为,如果采用多线程的方式,考虑到会产生多个线程同时修改同个变量(或者Buffer)可能导致Emacs诡异行为。

安装Emacs 26开发版

要想在Emacs 26发布之前使用多线程的功能,必需升级Emacs到最新的开发版本。Mac环境下,下载Daily Build的开发版本,地址为https://emacsformacosx.com/builds 。我下载的是2017-02-05这天的Daily Build开发版 (版本号:26.0.50.1)。如果是Linux环境,可以自己下载源代码进行源码编译安装。源码下载

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

尝鲜Emacs多线程

安装好最新版本的Emacs后,下面我们尝试下多线程。创建新的线程的函数是make-thread ,这个函数的定义如下:

(make-thread FUNCTION &optional NAME)

它的作用是创建一个新的线程,然后在这个线程中执行FUNCTION这个函数,当函数执行完成后退出时,这个线程就结束了。 NAME这个字符串参数是可选的,作用是对这个线程进行命名。

多线程的异步

下面,我们定义一个宏,将函数的执行在异步线程里:

    (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))))))))

这个宏的作用是将函数 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)

然后我们执行 M-x bg-threadaction 会在*Messages*这个Buffer打印出执行日志!从日志中我们看出,在执行异步线程时,可以同步操作Emacs。

如果采用async怎么写

上面的例子,如果采用async进行异步操作,写法如下:

(defun async-threadaction ()
  "Emacs async example runner."
  (interactive)
  (async-start
   ;; 异步执行更新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

小结

以上对Emacs 26多线程简单描述,我们发现多线程对Emacs带来了一种全新的编辑体验。我们在操作Emacs也不再会受后台任务的影响。这将是Emacs 26最期待的功能。想尝鲜的同学可以下载Daily Build开发版。想要Emacs 26 Release版本的同学,那只能希望Emacs 26早日发布了!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容