Comments (10)
Have you considered not using eval but rather first compile the input, then load it in memory (as a thunk) and lastly invoke the thunk?
IIUC, the first step is interruptible because it is fully implemented in Scheme.
The third step also only involves Scheme so it should be fine too. The second step doesn't benefit from interruption I'd think.
I think that's what the standard Guile REPL does already (maybe 'eval' too)?
If you do all that, Fibers should be able to do the context switching (if that's what you meant by blocking).
That said, a glaring omission is that you don't appear to have implemented interruption anywhere -- I don't see thread-terminate! anywhere, so no control-C equivalent.
Also later more about the operation itself
from fibers.
(define (block-fn flag sched resume)
(define (commit)
(match (atomic-box-compare-and-swap! flag 'W 'S)
('W (resume values))
('C (commit))
('S #f)))
(when sched
(schedule-task
sched
(lambda ()
(perform-operation (thread-operation th))
(commit)))))
To my understanding, what 'block-fn' needs to do is to ‘asynchronuously’ wait for ‘try-fn’ to potentially succeed (i.e., it needs to in some way do something like join-thread).
However, I don't see join-thread anywhere.
IIUC, in practical terms, that means Fibers might wait forever as it is never notified that the thread-operation might succeed.
from fibers.
Also, 'thread-operation' -> 'thread-join-operation' is a clearer name.
from fibers.
(when sched
(schedule-task
sched
(lambda ()
(perform-operation (thread-operation th))
(commit)))))
You are busy-looping here, which is bad for efficiency (CPU time/energy).
You are also forgetting to implement the (not sched) case (i.e., just join-thread, I suppose).
I think I see what causes high-memory usage: you are implementing a (busy) loop by a non-tail recursion!
I think most problems will go away by, for both sched and (not sched), doing something like 'join-thread'.
But important: make sure it's ‘asynchronous’, because another operation (when using choice-operation) might complete earlier! I don't know any ‘concurrent thread waiting’ procedures, though.
from fibers.
Have you considered not implementing thread-operation and instead make a condition variable and wrap the thunk of the new thread to signal the condition variable (upon success or otherwise, you can use dynamic-wind's out guard for this)?
Less satisfying and less general perhaps, but much more simple and seems to suit your needs.
from fibers.
and stumbled upon an issue: we can't do [interruptable] eval inside fiber
I don't see any fundamental problems with implementing interruption of individual fibers -- it seems a matter of $LOTS_OF_WORK. Needs modifications to Fibers itself though.
from fibers.
(wrap-operation
(wait-operation cnd)
(lambda ()
(format #t "condition signal recieved\n")
'recieved-cnd-signal))
(spawn-fiber
(lambda ()
(sleep 5)
(format #t "sending signal\n")
(signal-condition! cnd)))
You are reimplementing 'sleep-operation' + '(wrap-operation ... (lambda () log stuff))' here.
from fibers.
Have you considered not implementing thread-operation and instead make a condition variable and wrap the > thunk of the new thread to signal the condition variable (upon success or otherwise, you can use dynamic-> wind's out guard for this)?
Less satisfying and less general perhaps, but much more simple and seems to suit your needs.
@emixa-d I didn't think about using condition variables outside of the fibers, that's actually a very good idea, thank you!
Will make something like this:
(use-modules (fibers))
(use-modules (fibers channels))
(use-modules (fibers operations))
(use-modules (fibers timers))
(use-modules (fibers conditions))
(use-modules (fibers scheduler))
(use-modules (ice-9 threads))
(use-modules (ice-9 match))
(use-modules (ice-9 atomic))
(use-modules (ice-9 exceptions))
(define (eval-thread code finished-cnd)
(call-with-new-thread
(lambda ()
(dynamic-wind
(lambda () 'hi)
(lambda ()
(let ((res (with-exception-handler
(lambda (exception)
`(exception-value ,exception))
(lambda ()
`(eval-value . ,(primitive-eval code)) )
#:unwind? #t)))
res))
(lambda () (signal-condition! finished-cnd))))))
(define (async-program)
(let ((ch (make-channel))
(cnd (make-condition)))
(spawn-fiber
(lambda ()
(let* ((eval-cnd (make-condition))
(eval-th (eval-thread '(begin (sleep 4) 'some-value) eval-cnd)))
(put-message
ch
(perform-operation
(choice-operation
(wrap-operation
(wait-operation cnd)
(lambda ()
(cancel-thread eval-th)
`(inerrupted . #t)))
(wrap-operation
(wait-operation eval-cnd)
(lambda (. v)
`(thread-value . ,(join-thread eval-th))))))))))
;; sending eval interrupt
(spawn-fiber
(lambda ()
(sleep 5)
(format #t "sending signal\n")
(signal-condition! cnd)))
(get-message ch)))
(format #t "return value: ~a\n"
(run-fibers async-program))
And thank you for other comments too, I found them valuable. I have enough to keep working, will share the results later, probably on guile-users mailing list.
from fibers.
(let ((res (with-exception-handler
(lambda (exception)
`(exception-value ,exception))
(lambda ()
`(eval-value . ,(primitive-eval code)) )
#:unwind? #t)))
In a REPL, it would be useful to include a backtrace and not only the exception. display-backtrace / backtrace + call-with-output-string may be useful.
from fibers.
from fibers.
Related Issues (20)
- Something like promises HOT 5
- Test failures with "wrong state" on aarch64 HOT 1
- Expensive tests should be skipped by default
- Failing to create a non-blocking socket inside fiber HOT 2
- Configure dosnt't look up for libgc headers
- Q: Does it support racket? or how to use it in racket HOT 1
- Unbound variable: SOCK_NONBLOCK on MacOS 14.5
- `race-until` test runs forever (1.2.0 + affinity patch, NetBSD 9 amd64) HOT 1
- Cannot print backtraces within a fiber HOT 13
- [doc] clarify the use of dynamic-wind, probably in the Barriers chapter HOT 1
- Guile deprecation warning due to bit-count HOT 9
- Fibers wait can forever on a file descriptor once it has been closed HOT 1
- 'get-message' continuation fired more than once? HOT 13
- On GNU/Hurd, 'time_units_per_microsec' is zero HOT 1
- High CPU usage on system time change HOT 7
- Documentation refers to `send-operation` instead of `put-operation`
- concurrent-web-server doesn't wait for the server to be started HOT 1
- Missing basic combinators `guard-operation` and `nack-guard-operation`
- fibers does not support wait-operation being interrupted, even when on a non-fibers thread HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fibers.