puniverse/pulsar

receiving using the actor's internal representation, (rcv @self) (mailbox-of @self) breaks

andreiursan opened this issue · 2 comments

According to the docs the following should be possible:

(defsfn actor-name []
   (println (rcv @self))
   (recur))
(defsfn actor-name []
  (println (rcv (mailbox-of @self))
  (recur))

In my case it throws an error, here is the repl output:

clojure-actors.core=> (defsfn actor-name []
                 #_=> (println (rcv (mailbox-of @self))))
#'clojure-actors.core/actor-name
clojure-actors.core=> (register! :o (spawn actor-name))
Exception in Fiber "fiber-10000004" If this exception looks strange, perhaps you've forgotten to instrument a blocking method. Run your program with -Dco.paralleluniverse.fibers.verifyInstrumentation to catch the culprit!
java.lang.ClassCastException: co.paralleluniverse.actors.ActorRef cannot be cast to co.paralleluniverse.strands.channels.ReceivePort
    at co.paralleluniverse.pulsar.core$rcv.invoke(core.clj:593)
    at co.paralleluniverse.pulsar.InstrumentedIFn.invoke(InstrumentedIFn.java:36)
    at clojure_actors.core$actor_name.invoke(form-init4486106094382776745.clj:2)
    at co.paralleluniverse.pulsar.InstrumentedIFn.invoke(InstrumentedIFn.java:32)
    at co.paralleluniverse.pulsar.ClojureHelper.suspendableInvoke(ClojureHelper.java:213)
    at co.paralleluniverse.pulsar.ClojureHelper$4.run(ClojureHelper.java:200)
    at co.paralleluniverse.actors.PulsarActor.doRun(PulsarActor.java:92)
    at co.paralleluniverse.actors.Actor.run0(Actor.java:691)
    at co.paralleluniverse.actors.ActorRunner.run(ActorRunner.java:51)
    at co.paralleluniverse.fibers.Fiber.run(Fiber.java:1024)
nil
WARNING: Uninstrumented methods (marked '**') or call-sites (marked '!!') detected on the call stack:
    at co.paralleluniverse.pulsar.core$rcv.invoke(java.lang.Object) (core.clj:593 bci: 3) (optimized) !! (instrumented suspendable calls at: [])
    at co.paralleluniverse.pulsar.InstrumentedIFn.invoke (InstrumentedIFn.java:36 bci: 5)
    at clojure_actors.core$actor_name.invoke (form-init4486106094382776745.clj:2 bci: 294)
    at co.paralleluniverse.pulsar.InstrumentedIFn.invoke (InstrumentedIFn.java:32 bci: 4)
    at co.paralleluniverse.pulsar.ClojureHelper.suspendableInvoke (ClojureHelper.java:213 bci: 1) (optimized)
    at co.paralleluniverse.pulsar.ClojureHelper$4.run (ClojureHelper.java:200 bci: 83)
    at co.paralleluniverse.actors.PulsarActor.doRun (PulsarActor.java:92 bci: 76)
    at co.paralleluniverse.actors.Actor.run0 (Actor.java:691 bci: 222)
    at co.paralleluniverse.actors.ActorRunner.run (ActorRunner.java:51 bci: 148)
    at co.paralleluniverse.fibers.Fiber.run (Fiber.java:1024 bci: 11)
    at co.paralleluniverse.fibers.Fiber.run1 (Fiber.java:1019 bci: 1)
Exception in Fiber "fiber-10000004" If this exception looks strange, perhaps you've forgotten to instrument a blocking method. Run your program with -Dco.paralleluniverse.fibers.verifyInstrumentation to catch the culprit!
java.lang.ClassCastException: co.paralleluniverse.actors.ActorRef cannot be cast to co.paralleluniverse.strands.channels.ReceivePort
    at co.paralleluniverse.pulsar.core$rcv.invoke(core.clj:593)
    at co.paralleluniverse.pulsar.InstrumentedIFn.invoke(InstrumentedIFn.java:36)
    at clojure_actors.core$actor_name.invoke(form-init4486106094382776745.clj:2)
    at co.paralleluniverse.pulsar.InstrumentedIFn.invoke(InstrumentedIFn.java:32)
    at co.paralleluniverse.pulsar.ClojureHelper.suspendableInvoke(ClojureHelper.java:213)
    at co.paralleluniverse.pulsar.ClojureHelper$4.run(ClojureHelper.java:200)
    at co.paralleluniverse.actors.PulsarActor.doRun(PulsarActor.java:92)
    at co.paralleluniverse.actors.Actor.run0(Actor.java:691)
    at co.paralleluniverse.actors.ActorRunner.run(ActorRunner.java:51)
    at co.paralleluniverse.fibers.Fiber.run(Fiber.java:1024)
WARNING: Uninstrumented methods (marked '**') or call-sites (marked '!!') detected on the call stack:
    at co.paralleluniverse.pulsar.core$rcv.invoke(java.lang.Object) (core.clj:593 bci: 3) (optimized) !! (instrumented suspendable calls at: [])
    at co.paralleluniverse.pulsar.InstrumentedIFn.invoke (InstrumentedIFn.java:36 bci: 5)
    at clojure_actors.core$actor_name.invoke (form-init4486106094382776745.clj:2 bci: 294)
    at co.paralleluniverse.pulsar.InstrumentedIFn.invoke (InstrumentedIFn.java:32 bci: 4)
    at co.paralleluniverse.pulsar.ClojureHelper.suspendableInvoke (ClojureHelper.java:213 bci: 1) (optimized)
    at co.paralleluniverse.pulsar.ClojureHelper$4.run (ClojureHelper.java:200 bci: 83)
    at co.paralleluniverse.actors.PulsarActor.doRun (PulsarActor.java:92 bci: 76)
    at co.paralleluniverse.actors.Actor.run0 (Actor.java:691 bci: 222)
    at co.paralleluniverse.actors.ActorRunner.run (ActorRunner.java:51 bci: 148)
    at co.paralleluniverse.fibers.Fiber.run (Fiber.java:1024 bci: 11)
    at co.paralleluniverse.fibers.Fiber.run1 (Fiber.java:1019 bci: 1)

It's an issue with the docs: there isn't a single, full-duplex representation of an actor. A Quasar/Pulsar actor has 2 complementary representations: ActorRef is the public representation and it implements SendPort (so messages can be sent to it) while "Actor" is the internal representation and it implements ReceivePort (so messages can received from it).

Both @self (only inside a running actor) and mailbox-of return the public representation, instead only @mailbox returns the internal one, so the 2 usages you've reported throwing exceptions do rightly so.

Thanks!