Re: guile fibers - looking for adivce
Hello, Dnia 2020-09-07, o godz. 17:25:38 Aleix Conchillo Flaqué napisał(a): > Hi Jan, > > To be honest, I've never used GOOPS so things might be a bit more > complicated there, I don't know. But it sounds like you have two > options: > > - Create a fiber with the object and pass data from the object using > channels to other fibers. Then return data to the main fiber (or the > fiber that has the object) through a channel and update your object. > - Make the object global and have fibers that update the object. In > this case you would need to use mutexes. > > Or maybe you find another way? > > > That said, I might be wrong though. > > > > > > Hope this helps, > > > > > > Aleix > > > > Thanks for explanation, this made my thinking much cleaner. I can > > get back to experimenting now! > > > > > Cool, let us know! > Aleix I actually made a working prototype. Basically I created a new allocation option for GOOPS slots - #:message. The default allocation type is #:instance, as explained here: https://www.gnu.org/software/guile/manual/html_node/Slot-Options.html The #:message allocation type I introduced treats setting a slot like sending a message and reading the slot like receiving a message. I used the example from GOOPS manual as inspiration: https://www.gnu.org/software/guile/manual/html_node/Customizing-Class-Definition.html Here's the code. It introduces a new metaclass to modify the default behavior and introduces the #:message allocation type. (define-class ()) (define-method (compute-get-n-set (class ) s) (define set-channel (make-channel)) (define get-channel (make-channel)) (define stored-value '()) (define initialized? #f) (define (value-updater ch) (spawn-fiber (lambda () (let loop () (set! stored-value (get-message ch)) (loop) (case (slot-definition-allocation s) ((#:message) (begin (list (lambda (o) (if initialized? (begin (spawn-fiber (lambda () (put-message get-channel stored-value))) (get-message get-channel (lambda (o v) (spawn-fiber (lambda () (if (not initialized?) (begin (set! initialized? #t) (value-updater set-channel))) (put-message set-channel v))) (else (next-method Using this in practice looks something like this: (define-class () (number-of-legs #:setter set-number-of-legs #:getter get-number-of-legs #:allocation #:message) (toys #:setter set-toys #:getter get-toys #:allocation #:message) #:metaclass ) (define (main) (run-fibers (lambda () (define dog1 (make )) (spawn-fiber (lambda () (set-number-of-legs dog1 4) (display "number of legs:\n") (display (get-number-of-legs dog1 4)) (set-toys dog1 (list 'bone 'dead-rat 'something) #:drain? #t)) (main) This solution allows setting and getting values safely over fibers through messages, eliminating the problem of parallely editing the same slot of an object (thanks to just one fiber being able to edit the real value (value-updater)). If I'm not missing something important, this is a real solution for a real problem. I've already tested it with my toy program. If you have any suggestions, feel free to tell me, also feel free to use my code, if you find it useful. I could push this a bit further by making the allocate all slots by default as #:message - this way every object would work safely on fibers, without the boilerplate code. Thanks for help, everyone. Jan Wielkiewicz
Re: guile fibers - looking for adivce
Hi! Dnia 2020-09-05, o godz. 18:19:49 Aleix Conchillo Flaqué napisał(a): > Hi! > > On Sat, Sep 5, 2020 at 3:48 PM Jan Wielkiewicz < > tona_kosmicznego_smie...@interia.pl> wrote: > > I believe sharing the same object by the two fibers defeats the > purpose of message passing, because with the way you are doing it you > find exactly the problem you are having and the only way to fix this > is by using mutexes. That is, you are trying to use fibers as you > would use regular threads sharing a resource. Instead, there should > probably be a main fiber (that holds the object) and send messages > (with the data needed from the object) to 2 other fibers (those would > be your methods A and B). I see, thank you for explanation. This allowed me to understand the problem doesn't lie in the way I was trying to implement my messaging through fibers, but rather in the way I was using GOOPS - my custom method for initializing slots called next-method after doing everything what caused some weird problems with allocation. Are threads and mutexes worth using, if there are fibers already? I know I'll have to learn this eventually, to fully master programming, but I'm not sure if there's a great advantage over fibers. > > I haven't used fibers extensively, but I've used Go quite a bit which > follows the same pattern of channels and message passing and this is > how you would do it. > > Also, the fibers manual also suggests this approach: > https://github.com/wingo/fibers/wiki/Manual#33-mutation Yeah, I've read the manual like three times already, but Andy is somethimes writing sentences from outer space, including the GOOPS manual. This isn't the level of English I'm currently on. I guess I'll write some self-explaining examples of GOOPS after I fully understand it. > That said, I might be wrong though. > > Hope this helps, > > Aleix Thanks for explanation, this made my thinking much cleaner. I can get back to experimenting now! Jan Wielkiewicz
Re: guile fibers - looking for adivce
Hi! Dnia 2020-09-06, o godz. 02:42:20 Zelphir Kaltstahl napisał(a): > Hi Jan! > > Call me uneducated, but I believe, if you are accessing shared memory, > in this case the shared member vector of the object, you will have to > resort to things like locking mechanisms. I don't know of any other > way, except for not using shared memory and keeping one copy per > fiber or per concurrently running execution unit. I'll probably go with some locking mechanism then. > Is there a way you could avoid sharing the object? Perhaps copying it > for each fiber? Fortunately, at least for now, one procedure updates the array and the other only reads it. We'll see how scalable is my idea when the project grows. > If not, then perhaps there is yet another way. A while ago I read some > article, which had the heading "pull not push" or something. So > instead of having multiple concurrent execution units trying to > update the vector, perhaps you could have multiple concurrent > execution units, which are each responsible for some exclusive part > of the state of a data structure and working on their own parts of > the memory of it and update it by retrieving information from the > system. Perhaps this is clearer, if I link to the article I read: Sounds interesting, thanks. Maybe I'll find use for this later. > https://nullprogram.com/blog/2020/04/30/ > > This might only work in cases, where the data lends itself to such > "other way around" of updating state. > > > Thanks in advance > > Jan Wielkiewicz > > Out of ideas for now. > > Regards, > Zelphir > > Anyway, thanks for ideas. Jan Wielkiewicz
guile fibers - looking for adivce
Hello, I'm still on my way of integrating Guile Fibers and GOOPS, but I encountered some weird behavior. Say I have an object with with one slot being a vector and two methods accessing the vector concurrently/parallelly. The methods accessing/editing the vector are time consuming and are meant to be ran frequently. Assuming I would like to run the methods on separate fibers, how do I make sure the state of the object doesn't suddenly change during execution of a method? I would like the methods to be able to edit the state of the object, but in a cooperative manner. The weird behavior I've encountered is that sometimes when running the first method (A) and right after starting the second method (B), the method B tries to access the vector before the method A finishes its job. What should I do to make accessing the vector cooperatively, yet to run the time consuming on separate fibers for concurrency? I was thinking about implementing slots in objects as sending and receiving messages instead of regular variables, but still there were some problems with the object state. Could someone explain me what should I do? Thanks in advance Jan Wielkiewicz
Re: No Guile on Windows?
Hello, Dnia 2020-07-24, o godz. 16:00:56 Ludovic Courtès napisał(a): > However, my understanding is that Windows Subsystem for Linux (WSL) > has the potential to make all of us happy. This is fine as far as we're talking about proprietary Windows, but this isn't good for software freedom generally - there's ReactOS (https://reactos.org/) - a free Windows clone that is about to reach beta stage. It is unlikely they're going to implement WSL there and therefore Guile will be not usable on this platform. This could potentially stop Guile users on Windows from switching to ReactOS. If Guile were running natively on Windows, it would only benefit free software - more Guile users, more people being interested in Guix and more people switching to free alternatives. If no current Guile maintainer is interested in porting it to Windows, we could at least let people know we're looking for someone who does. It could be a GSoC proposal, Outreachy something, etc. Jan Wielkiewicz
Re: GOOPS and fibers - need help understanding what's wrong, bug in fibers/guile?
Hello, Dnia 2020-07-22, o godz. 13:28:14 Chris Vine napisał(a): > On further reflection I am not sure if it did used to work with > guile-2.2. I think it may be a bug in the manual after all. This > works OK: > > (display (run-fibers > (lambda () > (let ((channel (make-channel))) > (spawn-fiber > (lambda () >(sleep 1) ;; do some work >(put-message channel "hello world"))) > (simple-format #t "~a~%" (get-message channel)) > "finished\n" > This one just worked, I don't know why, even without "display". Something is buggy it seems. > The point about: > > (run-fibers >(lambda () (spawn-fiber >(lambda () > (set! v "Set") > (display "hey!\n") > > is that spawn-fiber, and so init-thunk, will return straigntaway with > a new fiber object. > > So I suspect setting #:drain? to #t will resolve your problem. #:drain solved the problem and I also managed to make my code work. > It might be worth reporting the bug in the manual as an issue on the > github repository (assuming the above is correct). > Yes, I'll report it. Thanks for helping me! Posting my working code, so someone wanting to mix GOOPS with fibers will have a working example: (define-module (blocks block) #:use-module (fibers) #:use-module (fibers channels) #:use-module (oop goops) #:use-module (ice-9 match) #:use-module (srfi srfi-9) ;; records #:export ( connect-peers send-message handle-message main p1 p2 get-buffer)) (define-class () (input #:init-form '() #:getter get-input #:setter set-input #:init-keyword #:input) (output #:init-form '() #:getter get-output #:setter set-output #:init-keyword #:output) (buffer #:init-value '() #:setter set-buffer #:getter get-buffer)) ;; Only connection, no messaging started. (define-method (connect-peers (p1 ) (p2 )) (let ((p1-p2 (make-channel)) ;; p1 to p2 (p2-p1 (make-channel))) ;; p2 to p1 (set-input p1 p2-p1) (set-output p1 p1-p2) (set-input p2 p1-p2) (set-output p2 p2-p1))) (define-method (send-message (p ) msg) (spawn-fiber (lambda () (put-message (get-output p) msg (define-method (handle-message (p )) (spawn-fiber (lambda () (let loop () (define msg (get-message (get-input p))) (match (pk msg) ('ping (send-message p 'pong)) ('pong (send-message p 'ping))) (loop) (define (main) (define p1 (make )) (define p2 (make )) (connect-peers p1 p2) (run-fibers (lambda () (handle-message p1) (handle-message p2) (send-message p1 'ping)) #:drain? #t)) (main) --- Jan Wielkiewicz
GOOPS and fibers - need help understanding what's wrong, bug in fibers/guile?
Hello, I started writing my project in Guile with GOOPS and fibers (I'll release it once it stops being a shame and starts working!), but I encountered a problem: The example from fibers' manual doesn't work: (lambda () (spawn-fiber (lambda () (display "hey!\n") It doesn't print "hey" as documented in the manual. I use guile 3.0.4 and fibers 1.0.0 (from Guix). I also tried making a simple proof of concept, but it doesn't seem to do anything. I would like to understand what's wrong with my code or report a bug, if this is the case. No errors, warnings, syntax errors, just silence. My code: (define-module (blocks block) #:use-module (fibers) #:use-module (fibers channels) #:use-module (oop goops) #:use-module (srfi srfi-9) ;; records #:export ( connect-peers send-message handle-message start-listening)) (define-class () (input #:init-form '() #:getter get-input #:setter set-input #:init-keyword #:input) (output #:init-form '() #:getter get-output #:setter set-output #:init-keyword #:output)) ;; Only connection, no messaging started. (define-method (connect-peers (p1 ) (p2 )) (let ((p1-p2 (make-channel)) ;; p1 to p2 (p2-p1 (make-channel))) ;; p2 to p1 (set-input p1 p2-p1) (set-output p1 p1-p2) (set-input p2 p1-p2) (set-output p2 p2-p1))) (define-method (send-message (p ) msg) (put-message (get-output p) msg)) (define-method (handle-message (p )) (let loop () (define msg (get-message (get-input p))) (match (pk msg) ('ping (send-message p 'pong))) (loop))) (define-method (start-listening (p1 ) (p2 )) (run-fibers (lambda () (spawn-fiber (lambda () (connect-peers p1 p2) (handle-message p1) (send-message p1 'ping) (handle-message p2)) I run this in repl: (define p1 (make )) (define p2 (make )) (start-listening p1 p2) - Thanks in advance, Jan Wielkiewicz
Re: Handling object communication in GOOPS
Hello, Dnia 2020-07-19, o godz. 18:22:17 "Dr. Arne Babenhauserheide" napisał(a): > > Did you have a look at fibers and channels for this? > > https://github.com/wingo/fibers Looks like exactly what I need, thanks! > Best wishes, > Arne Jan Wielkiewicz
Re: Handling object communication in GOOPS
Dnia 2020-07-17, o godz. 13:26:31 Zelphir Kaltstahl napisał(a): > Hello Jan, > > to me this sounds like you need to implement perhaps 2 things: > > 1. a setter for the , which takes care of updating > things, when a completely new is added. > > 2. some kind of observer pattern, where the registers > itself as a listener to changes in the . Probably a > method at the , something like > `register-change-listener`, which adds the argument it takes to a > list or a set of listeners. Then you need to take care, that on > relevant updates all registered listeners are notified of the change. > > Furthermore you can register the as a listener at the > when the is set using the setter and > unregister as listener at the previously set (which is > now replaced by the new one). I'm implementing something like this right now. I'm adding a object to every object needing to do messaging. Once a message is received, the object will run message handler provided by the parent object. I'm surprised Guile isn't providing anything like this right now. If my knowledge is correct, the original idea of OOP was about sending messages. > I have not worked with GOOPS yet, so my answer is not GOOPS specific > and perhaps there are better ways, but I think this is the classic > approach to the problem. It seems GOOPS is pretty minimalistic, I couldn't find anything there, but I didn't yet study the MetaObject Protocol entirely. > Regards, > Zelphir Thanks Jan Wielkiewicz
Handling object communication in GOOPS
Hello, I would like make objects of two different classes communicate, but I'm not sure how to implement it or if there already exists something for the purpose. Say I have two classes: and . During initialization of an object, it creates a slot containing object. I would like to make the object to know when address in the address bar is changed, for example (set-address address-bar1 "/home/user"). Any suggestions? Thanks in advance. Jan Wielkiewicz