From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Giuseppe Scrivano Newsgroups: gmane.emacs.devel Subject: multi-threaded Emacs Date: Sat, 29 Nov 2008 14:32:22 +0100 Message-ID: <87abbiody1.fsf@master.homenet> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1227965574 25375 80.91.229.12 (29 Nov 2008 13:32:54 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 29 Nov 2008 13:32:54 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Nov 29 14:33:57 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1L6PxJ-0001Gw-5c for ged-emacs-devel@m.gmane.org; Sat, 29 Nov 2008 14:33:53 +0100 Original-Received: from localhost ([127.0.0.1]:56515 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L6Pw9-0006Pu-3A for ged-emacs-devel@m.gmane.org; Sat, 29 Nov 2008 08:32:41 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1L6Pw4-0006PB-7e for emacs-devel@gnu.org; Sat, 29 Nov 2008 08:32:36 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1L6Pw2-0006OS-GF for emacs-devel@gnu.org; Sat, 29 Nov 2008 08:32:35 -0500 Original-Received: from [199.232.76.173] (port=45838 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L6Pw2-0006OM-A4 for emacs-devel@gnu.org; Sat, 29 Nov 2008 08:32:34 -0500 Original-Received: from joe.mail.tiscali.it ([213.205.33.54]:52877) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1L6Pvz-0006Is-3F; Sat, 29 Nov 2008 08:32:31 -0500 Original-Received: from master.homenet (84.222.168.192) by joe.mail.tiscali.it (8.0.022) id 48F7490702141B03; Sat, 29 Nov 2008 14:32:29 +0100 Original-Received: from gscrivano by master.homenet with local (Exim 4.69) (envelope-from ) id 1L6Pvq-0003Mz-V8; Sat, 29 Nov 2008 14:32:22 +0100 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:106297 Archived-At: --=-=-= Hello, I attached a small patch that enables basic threads in Emacs; it is just a proof of concept and not usable yet, my goal was the execution of the elisp code I included at the bottom. In the new file thread.c these functions are defined: (create-thread) (with-thread id '(code)) (kill-thread id) The first one creates a suspended thread that is waiting for requests. These requests are done by with-thread that allows the execution of '(code) on the specified thread. `kill-thread' is used to terminate a thread execution by its id. It is a prototype and the code is not very clean, still a lot of work must be done in order to have working threads, but I think that have a multi-threaded Emacs worths this effort. My idea is to share global variables among threads while local bindings are done locally to threads. I haven't well investigated all problems that will raise using threads in Emacs, the first one that come to my attention is the garbage collector and at the moment I simply disable GC while there are running threads. The following elisp code can be used now, it is not safe as the new thread id is not freed after it is used: (progn (setq i 0) (setq j 0) (with-thread (create-thread) '(while (< i 20) (sleep-for 0.2) (print "hello") (setq i (1+ i)))) (while (< j 20) (print "world") (sleep-for 0.25) (setq j (1+ j)))) `with-thread' allows to use the same thread multiple times like: (with-thread foo '(do-something-complex)) (with-thread bar '(do-another-complex-thing)) (with-thread foo '(do-another-complex-thing)) The third call will block the calling thread until `foo' has completed its previous execution. What do you think about? Regards, Giuseppe --=-=-= Content-Type: application/octet-stream Content-Disposition: attachment; filename=emacs_multithread.diff.gz Content-Transfer-Encoding: base64 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 --=-=-=--