From mboxrd@z Thu Jan 1 00:00:00 1970 From: ludo@gnu.org (Ludovic =?utf-8?Q?Court=C3=A8s?=) Subject: Re: packaging Bootstrap for Cuirass' web interface Date: Fri, 27 Jul 2018 10:50:47 +0200 Message-ID: <87k1phkqoo.fsf@gnu.org> References: <87zhyitmtc.fsf@lassieur.org> <87pnzetjal.fsf@gnu.org> <87wotmtcks.fsf@lassieur.org> <5b578c0f.1c69fb81.4a8d1.0342@mx.google.com> <87bmawqk4m.fsf@lassieur.org> <87in53ka5r.fsf@lassieur.org> <87fu07k8iv.fsf@lassieur.org> <878t5yqsan.fsf@lassieur.org> <8736w6yv04.fsf@gnu.org> <877elhqwqf.fsf@lassieur.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:45807) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fiySe-0000sN-93 for guix-devel@gnu.org; Fri, 27 Jul 2018 04:50:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fiySd-0002am-6C for guix-devel@gnu.org; Fri, 27 Jul 2018 04:50:56 -0400 In-Reply-To: <877elhqwqf.fsf@lassieur.org> (=?utf-8?Q?=22Cl=C3=A9ment?= Lassieur"'s message of "Fri, 27 Jul 2018 03:43:36 +0200") List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: =?utf-8?Q?Cl=C3=A9ment?= Lassieur Cc: Guix-devel , Tatiana Sholokhova Hi Cl=C3=A9ment! Cl=C3=A9ment Lassieur skribis: > The bug is here: > > (define (make-critical-section . args) > "Return a channel used to implement a critical section. That channel c= an > then be passed to 'join-critical-section', which will ensure sequential > ordering. ARGS are the arguments of the critical section. > > Critical sections are implemented by passing the procedure to execute to a > dedicated fiber." > (let ((channel (make-channel))) > (spawn-fiber > (lambda () > (let loop () > (match (get-message channel) > ((? procedure? proc) > (put-message channel (apply proc args)))) > (loop)))) > channel)) > > (define (call-with-critical-section channel proc) > "Call PROC in the critical section corresponding to CHANNEL. Return the > result of PROC." > (put-message channel proc) > (get-message channel)) > > > Say I have 2 concurrent fibers (F1 and F2) wanting to serialize > messages through the critical section. > > - F1-PUT-MESSAGE puts F1-MESSAGE to CRITICAL-SECTION > - CRITICAL-SECTION gets F1-MESSAGE, which unblocks F1-PUT-MESSAGE > - F1-GET-MESSAGE is called and blocks > > - F2-PUT-MESSAGE puts F2-MESSAGE, and the only receiver available > is... F1-GET-MESSAGE, because CRITICAL-SECTION is busy > - F2-GET-MESSAGE is called and block > > - CRITICAL-SECTION is done handling F1-MESSAGE, and put > F1-MESSAGE-MODIFIED to... F2-GET-MESSAGE. > > F2-MESSAGE is a procedure, whereas F1-MESSAGE-MODIFIED is a list, which > causes the (map f F2-MESSAGE) error. D=E2=80=99oh! Good catch! > A solution could be to use two channels, in and out: > > (define (make-critical-section . args) > "Return a pair of channels used to implement a critical section. It can > then be passed to 'with-critical-section', which will ensure sequential > ordering. ARGS are the arguments of the critical section. > > Critical sections are implemented by passing the procedure to execute to a > dedicated fiber." > (let ((channel-in (make-channel)) > (channel-out (make-channel))) > (spawn-fiber > (lambda () > (let loop () > (match (get-message channel-in) > ((? procedure? proc) > (put-message channel-out (apply proc args)))) > (loop)))) > (cons channel-in channel-out))) > > (define (call-with-critical-section channel proc) > "Call PROC in the critical section corresponding to CHANNEL. Return the > result of PROC." > (match channel > ((channel-out . channel-in) > (begin > (put-message channel-out proc) > (get-message channel-in))))) > > WDYT? Or maybe like this: (define (make-critical-section . args) "Return a channel used to implement a critical section. That channel can then be passed to 'join-critical-section', which will ensure sequential ordering. ARGS are the arguments of the critical section. Critical sections are implemented by passing the procedure to execute to a dedicated fiber." (let ((channel (make-channel))) (spawn-fiber (lambda () (let loop () (match (get-message channel) (((? channel? reply) . (? procedure? proc)) (put-message reply (apply proc args)))) (loop)))) channel)) (define (call-with-critical-section channel proc) "Call PROC in the critical section corresponding to CHANNEL. Return the result of PROC." (let ((reply (make-channel))) (put-message channel (cons reply proc)) (get-message reply))) That makes it clear that the reply channel is used only by the calling fiber. WDYT? Thanks for debugging this! Ludo=E2=80=99.