Code Monkey home page Code Monkey logo

Comments (9)

t0yv0 avatar t0yv0 commented on June 14, 2024

I have no idea where SC is useful, but I keep hearing about it from almost everyone I talk to about Hopac. So I guess thumbs up!

Would it be practical to reduce the cost somehow via polymorphism or some such?

Even if Hopac ran slowly, the flexibility of the combinators is a big selling point. In line-of-business GUI apps, the speed often is not critical at all, but flexibility is a factor. I think having an option to run with SC support, even if slow, will appeal to a group of users.

from hopac.

polytypic avatar polytypic commented on June 14, 2024

The main motivation for SC support is to be able to say that some code will be executed on the UI thread, because most UI frameworks require UI code to run on a single specific thread.

I think that the performance difference will be insignificant for most users. It will increase memory usage a little bit (probably unnoticeable unless you really have very large amounts of jobs) and a few extra pointer comparisons will be needed here and there. However, spawning stuff to run on the UI thread will be much slower than spawning stuff to run on the worker threads managed by Hopac.

I'm already working on this and hope to have a first working version well before FP days.

from hopac.

eulerfx avatar eulerfx commented on June 14, 2024

Another use case for SC would be integration with ZMQ where contexts (or sockets?) are bound to a thread.

from hopac.

polytypic avatar polytypic commented on June 14, 2024

I'm having second thoughts about going through with adding support for synchronization contexts. I've recently "ported" an iOS application that I originally wrote in Swift (big mistake) to F# using Xamarin UIKit bindings, Hopac, choice streams and async. I had to work around a few Xamarin bugs (like the broken = operator and broken sprintf), but overall it was much more pleasant than working with Swift. Based on that experience, it doesn't seem like intrinsic synchronization context support would really bring benefits for GUI work. Here is a simple example code snippet:

StreamSrc.tap activity
|> Streams.scanFromFun 0 (fun n on -> if on then n+1 else n-1)
|> Streams.mapFun (fun n -> n > 0)
|> Streams.distinctUntilChangedByFun id
|> Streams.iterJob (fun on -> onMain {
   do if on then spinner.StartAnimating () else spinner.StopAnimating () })
|> queue

What the above does is that it implements the logic for showing (and hiding) an activity indicator. When some activity is started, true value is added to the activity stream and false when the activity finishes.

The interesting part about the above snippet is that it updates the GUI. All the stream processing is done using Hopac worker threads, except for the part that is explicitly transferred to the main thread as an async workflow. The onMain workflow builder builds an async computation, wraps it as a job, and makes it so that the async computation is started, and remains, on the main thread (unless explicitly switched to some other context). The onMain builder is initialized at the beginning of the app like this:

[<AutoOpen>]
module Util =
  let mutable onMain : Async.OnWithSchedulerBuilder = Unchecked.defaultof<_>

Util.onMain <-
  Async.OnWithSchedulerBuilder (
    SynchronizationContext.Current, run (Job.scheduler ()))

There are some more things, like how one can bind Hopac to GUI events, that are probably worth writing about, but it is not really rocket science. I'll probably write a document on that at some point.

from hopac.

vasily-kirichenko avatar vasily-kirichenko commented on June 14, 2024

@eulerfx 0MQ context is usually one for application (process) and it's thread safe. Sockets are safe for access by multiple threads, but such access must be serialized (I used to use MailboxProcessor for it). So it seems very easy to wrap sockets in a class, sends messages via a channel and receive them via a different channel (however, it seems impossible to wrap receiving messages with Alt.withNack since we cannot return received messages back to server or even back to 0MQ client message cache in case client abort the Alt).

Anyway, I don't see where synchronization context would be needed here.

from hopac.

polytypic avatar polytypic commented on June 14, 2024

FYI, there is now some experimental ("for convenience") support for doing stuff on the main synchronization context. See onMain and IObservable<'x>.onceAltOnMain. Using onMain one can easily run code on the main synchronization context in the middle of concurrent jobs. onceAltOnMain can be useful for responding to GUI events. (It is not appropriate for working with observables where waiting for singular events does not lead to useful semantics, but the approach works just fine for most purposes in a GUI.) For example, you could use it in a similar manner to what is described in Neil Danson's blog Simplifying State with Async (with XNA/WPF examples). (This technique of wrapping events as alternatives is basically what I already used previously in the iOS app I wrote.) In addition to waiting for single events, you can, of course, combine onceAltOnMain alternatives with other alternatives such as timeouts.

from hopac.

eulerfx avatar eulerfx commented on June 14, 2024

Cool.

WRT zeromq, what @vasily-kirichenko suggested is a better approach. Access to sockets must be serialized AND may require a memory barrier. With Hopac would be even better since no need to use MBP.

from hopac.

polytypic avatar polytypic commented on June 14, 2024

Note that basic operations in Hopac such as fill, send, give and take already include a memory barrier. As long as one makes it so that a particular zeromq socket may only be manipulated by one Hopac job at a time then that should already have the required barriers. However, one should not block in a Hopac job and basic ops on zeromq sockets appear to be blocking. So, to process zeromq sockets it would likely be better to have a dedicated native thread calling zeromq poll, so that only the dedicated thread is blocked. I'll look into this after a week or two.

from hopac.

eulerfx avatar eulerfx commented on June 14, 2024

Yeah poll seems like a way to go. Once the Hopac layer is there though, the zeromq patterns can become quite a bit more intelligible.

from hopac.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.