(
SynthDef(\testEvt,{
arg out, gate = 1;
var sint = Blip.ar(440) * Linen.kr(gate,doneAction:2,releaseTime:0.8);
Out.ar(out, Pan2.ar(sint, 0));
}).add();
Synth(\testEvt)
(instrument: \testEvt, freq:220, sustain: inf).play;
(instrument: \testEvt,freq:220).play;
)
Executing the first and the second line after the SynthDef would create a synth which playes forever, whereas the third line's synth plays for 0.8 seconds as per default value the generated event.
The problem is that I don't use 'sustain' anywhere in my SynthDef and it uses automatically just because there is a Linen.
The same this doesn't happen for freq: both the events play at 440 and not at 220, and that's just because the SynthDef doesn't use 'freq' as an argument. So why sustain doesn't follow the same rule ?
Also, is there a way to reference synths created by an event ? So that, when they have sustain: inf as argument, I can free them on a later time.
(instrument: \testEvt, freq:220, sustain: inf).play;
and
(instrument: \testEvt,freq:220).play;
are events. Events handle a lot of things for you. One thing they do is calculate when to set a gate to 0. (Remember that gate is one of the arguments in your SynthDef.) In the first example, because you sustain for infinite duration, the gate never goes to zero. In the second example, it uses the default duration and sets the gate to zero after that duration has passed. You can find out what key words are used in event environment variables by looking at the Event.sc source file. If you search for sustain, you'll find out the other keywords it uses for timing. One of these is dur. Try this:
(instrument: \testEvt, dur:3).play
Freq is also a keyword for events, but since you have no freq argument, it can't effect your synthDef. If you want to set the freq, you'll need to make a change:
SynthDef(\testEvt,{
arg out, gate = 1, freq = 440;
var sint = Blip.ar(freq) * Linen.kr(gate,doneAction:2,releaseTime:0.8);
Out.ar(out, Pan2.ar(sint, 0));
}).add();
For contrast between events and controlling a synth directly, try:
a = Synth.new(\testEvt, [\out, 0, \gate, 1])
You can add in any other arguments you want, like freq or sustain, but they have no effect because those aren't arguments to your synthdef. And, unlike Event, synth doesn't do any calculations on your behalf. When you want the note to end, set the gate to 0 yourself:
a.set(\gate, 0)
It's good to be aware of event environment variables because they're also used by Pbinds and by using them, you can effect other things. If you had a synthdef that used sustain as an argument for something else, you could be surprised by it changing your durations.
Regarding your last sub-question,
Also, is there a way to reference synths created by an event ? So that, when they have sustain: inf as argument, I can free them on a later time.
Yes, by "indexing" the Event by \id key. This actually returns an array of node ids because an Event with \strum can fire up more than one node/synth. Also, the \id value is nil while the event is not playing. But this indexing method is fairly unnecessary for what you want, because...
You can end the (associated) synth by ending the Event early with release, just like for the Synth itself. What this does is basically gate-out its internal synth. (In your example, this release call transitions to the release point of the ASR envelope generated by Linen, by lowering gate to 0.). And, of course, use a variable to save the "reference" to the synth and/or event, if don't plan to release it right away in a program (which would produce no sound with a gated envelope).
Basically
fork { var x = Synth(\testEvt); 2.wait; x.release }
does the same as
fork { var e = (instrument: \testEvt, sustain: inf).play; 2.wait; e.release }
except there's one layer of indirection in the latter case for the release. The first example is also equivalent to
fork { var x = Synth(\testEvt); 2.wait; x.set(\gate, 0); }
which does the work of release explicitly. Event also supports set and it passes the value to the corresponding Synth control (if the latter was properly added on the server.)
Now the complicated method you asked about (retrieving node ids for the event and sending them messages) is possible too... although hardly necessary:
fork { var e = (instrument: \testEvt, sustain: inf).play; 2.wait;
e[\id].do({ arg n; s.sendMsg("/n_set", n, "gate", 0); }) }
By the way, you can't use wait outside of a Routine, that's why fork was needed in the above examples. Interactively, in the editor, you can "wait manually", of course, before calling release on either the Synth or the Event.
As a somewhat subtle point of how envelope gating works, it doesn't actually start playing (technically begin transitioning to the endpoint of the first [attack] envelope segment) until you set gate to 1. I.e. you can delay the (envelope) start as in:
fork { x = Synth(\testEvt, [\gate, 0]); 3.wait; x.set(\gate, 1); 2.wait; x.release }
Beware that the default Event.play doesn't generate this 0 to 1 gate transition though, i.e. you can't rely on it to fire your synth's envelope if you set the initial gate value to zero in your SynthDef.
Also, I'm assuming that by "free" you mean "stop playing" rather than "free their memory on the server". There's no need to manually free those (event) synths in the latter sense since they have doneAction:2 in the envelope, which does that for you once they are released and the final segment of the envelope finishes playing. If you somehow want to kill the synth right away (like Ctrl+. does) instead of triggering its fade-out you can replace the message sent in the inner function of the "complicated" example (above) with s.sendMsg("/n_free", n). Or much more simply
fork { var e = (instrument: \testEvt, sustain: inf).play; 2.wait; e.free }
Also, if you wonder about \strum, an example is:
e = (instrument: \testEvt, sustain: inf, strum: 1, out: #[0, 0]).play
Now e[\id] is an array of two nodes. Event is a bit cheeky in that it will only create multiple nodes for arrays passed to actual Synth controls rather than random fields, so "strumming" \freq (or its precursors like \degree etc.) only creates multiple nodes if your SynthDesc has a freq control.
Alas the "complicated" method is almost useless when it comes to playing Pbinds (patterns). This is because Pbind.play returns and EventStreamPlayer... that alas makes a private copy of the prototype event being played and plays that private copy, which is inaccessible to the caller context (unless you hack EventStreamPlayer.prNext). Confusingly EventStreamPlayer has an accessible event variable, but that's only the "prototype", not the private copy event being played... So if p is an instance of an EventStreamPlayer then p.event[\id] is always nil (or whatever you set it to beforehand) even while playing. Since one seldom plays Events individually and much more often patterns...
Simply as a hacking exercise tough, it turns out there is an even more convoluted way to access the ids of nodes that EventStreamPlayer fires... This relies on overriding the default Event play which thankfully can be extended outside class inheritance because the default is conveniently saved in a class dictionary...
(p = Pbind(\instrument, \testEvt, \sustain, Pseq([1, 2]), \play, {
arg tempo, srv;
var rv;
"playhack".postln;
rv = Event.parentEvents[\default][\play].value(tempo, srv);
~id.postln;
rv;
}).play)
In general however, patterns are clearly not designed to be used this way, i.e. by hacking "a layer below" to get to the node ids. As "proof", while the above works well enough with Pbind (which uses the default Event type \note) it doesn't work reliably with Pmono which doesn't set the Event \id on its first note (Event type \monoNote) but only on subsequent notes (which generate a different Event type, \monoSet). Pmono keeps an internal copy of the node id, but this is completely inaccessible on the first mono note; it only copies it to the Events on the subsequent notes for some reason (bug perhaps, but could be "by design"). Also, if you use Pdef which extends Event with type \phrase... the above hack doesn't work all, i.e. \id is never set by type \phrase; perhaps you can get to the underlying sub-events generated somehow... I haven't bothered to investigate further.
The SC documentation (in the pattern guide) even says at one point
Remember that streams made from patterns don't expose their internals. That means you can't adjust the parameters of an effect synth directly, because you have no way to find out what its node ID is.
That's not entirely correct given the above hack, but it is true in some contexts.
Related
Basically I want an Aktor to change a scalafx-GUI safely.
I've read many posts describing this, but there where sometimes contradictory and some years old, so some of them might be outdated.
I have a working example code and I basically want to know if this kind of programming is thread-save.
The other question is if I can configure sbt or the compiler or something in a way, that all threads (from the gui, the actors and the futures) are started by the same dispatcher.
I've found some example code "scalafx-akka-demo" on GitHub, which is 4 years old. What I did in the following example is basically the same, just a little simplified to keep things easy.
Then there is the scalatrix-example approximately with the same age. This example really worries me.
In there is a self-written dispatcher from Viktor Klang from 2012, and I have no idea how to make this work or if I really need it. The question is: Is this dispatcher only an optimisation or do I have to use something like it to be thread save?
But even if I don't absolutely need the dispatcher like in scalatrix, it is not optimal to have a dispatcher for the aktor-threads and one for the scalafx-event-threads. (And maybe one for the Futures-threads as well?)
In my actual project, I have some measurement values coming from a device over TCP-IP, going to an TCP-IP actor and are to be displayed in a scalafx-GUI. But this is much to long.
So here is my example code:
import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scalafx.Includes._
import scalafx.application.{JFXApp, Platform}
import scalafx.application.JFXApp.PrimaryStage
import scalafx.event.ActionEvent
import scalafx.scene.Scene
import scalafx.scene.control.Button
import scalafx.stage.WindowEvent
import scala.concurrent.ExecutionContext.Implicits.global
object Main extends JFXApp {
case object Count
case object StopCounter
case object CounterReset
val aktorSystem: ActorSystem = ActorSystem("My-Aktor-system") // Create actor context
val guiActor: ActorRef = aktorSystem.actorOf(Props(new GUIActor), "guiActor") // Create GUI actor
val button: Button = new Button(text = "0") {
onAction = (_: ActionEvent) => guiActor ! Count
}
val someComputation = Future {
Thread.sleep(10000)
println("Doing counter reset")
guiActor ! CounterReset
Platform.runLater(button.text = "0")
}
class GUIActor extends Actor {
def receive: Receive = counter(1)
def counter(n: Int): Receive = {
case Count =>
Platform.runLater(button.text = n.toString)
println("The count is: " + n)
context.become(counter(n + 1))
case CounterReset => context.become(counter(1))
case StopCounter => context.system.terminate()
}
}
stage = new PrimaryStage {
scene = new Scene {
root = button
}
onCloseRequest = (_: WindowEvent) => {
guiActor ! StopCounter
Await.ready(aktorSystem.whenTerminated, 5.seconds)
Platform.exit()
}
}
}
So this code brings up a button, and every time it is clicked the number of the button increases. After some time the number on the button is reset once.
In this example-code I tried to bring the scalafx-GUI, the actor and the Future to influence each other. So the button click sends a message to the actor, and then the actor changes the gui - which is what I am testing here.
The Future also sends to the actor and changes the gui.
So far, this example works and I haven't found everything wrong with it.
But unfortunately, when it comes to thread-safety this doesn't mean much
My concrete questions are:
Is the method to change the gui in the example code thread save?
Is there may be a better way to do it?
Can the different threads be started from the same dispatcher?
(if yes, then how?)
To address your questions:
1) Is the method to change the gui in the example code thread save?
Yes.
JavaFX, which ScalaFX sits upon, implements thread safety by insisting that all GUI interactions take place upon the JavaFX Application Thread (JAT), which is created during JavaFX initialization (ScalaFX takes care of this for you). Any code running on a different thread that interacts with JavaFX/ScalaFX will result in an error.
You are ensuring that your GUI code executes on the JAT by passing interacting code via the Platform.runLater method, which evaluates its arguments on the JAT. Because arguments are passed by name, they are not evaluated on the calling thread.
So, as far as JavaFX is concerned, your code is thread safe.
However, potential issues can still arise if the code you pass to Platform.runLater contains any references to mutable state maintained on other threads.
You have two calls to Platform.runLater. In the first of these (button.text = "0"), the only mutable state (button.text) belongs to JavaFX, which will be examined and modified on the JAT, so you're good.
In the second call (button.text = n.toString), you're passing the same JavaFX mutable state (button.text). But you're also passing a reference to n, which belongs to the GUIActor thread. However, this value is immutable, and so there are no threading issues from looking at its value. (The count is maintained by the Akka GUIActor class's context, and the only interactions that change the count come through Akka's message handling mechanism, which is guaranteed to be thread safe.)
That said, there is one potential issue here: the Future both resets the count (which will occur on the GUIActor thread) as well as setting the text to "0" (which will occur on the JAT). Consequently, it's possible that these two actions will occur in an unexpected order, such as button's text being changed to "0" before the count is actually reset. If this occurs simultaneously with the user clicking the button, you'll get a race condition and it's conceivable that the displayed value may end up not matching the current count.
2) Is there may be a better way to do it?
There's always a better way! ;-)
To be honest, given this small example, there's not a lot of further improvement to be made.
I would try to keep all of the interaction with the GUI inside either GUIActor, or the Main object to simplify the threading and synchronization issues.
For example, going back to the last point in the previous answer, rather than have the Future update button.text, it would be better if that was done as part of the CounterReset message handler in GUIActor, which then guarantees that the counter and button appearance are synchronized correctly (or, at least, that they're always updated in the same order), with the displayed value guaranteed to match the count.
If your GUIActor class is handling a lot of interaction with the GUI, then you could have it execute all of its code on the JAT (I think this was the purpose of Viktor Klang's example), which would simplify a lot of its code. For example, you would not have to call Platform.runLater to interact with the GUI. The downside is that you then cannot perform processing in parallel with the GUI, which might slow down its performance and responsiveness as a result.
3) Can the different threads be started from the same dispatcher? (if yes, then how?)
You can specify custom execution contexts for both futures and Akka actors to get better control of their threads and dispatching. However, given Donald Knuth's observation that "premature optimization is the root of all evil", there's no evidence that this would provide you with any benefits whatsoever, and your code would become significantly more complicated as a result.
As far as I'm aware, you can't change the execution context for JavaFX/ScalaFX, since JAT creation must be finely controlled in order to guarantee thread safety. But I could be wrong.
In any case, the overhead of having different dispatchers is not going to be high. One of the reasons for using futures and actors is that they will take care of these issues for you by default. Unless you have a good reason to do otherwise, I would use the defaults.
I have a FlexRay PDU called TEMP in our case, which is getting filled in every cycle, and i would like to simulate a timeout on this PDU, but it has no updatebit.
I have a panel where i check the enable button to decide if it should be sent out or not.
frPdu FR::TEMP_Pdu;
on preStart {
if (#FR_namespace::TEMP_Enablebutton)
{
FRSetSendPDU(TEMP_Pdu);
}
}
on frStartCycle * {
if (#FR_namespace::TEMP_Enablebutton)
FrUpdatePDU(TEMP_Pdu, 1, 1));
}
Whatever I set my button to, the PDU gets transmitted every loop.
FRUpdatePDU() is not sending another instance of PDU, it is just updating the next iteration with data from the frPDU object, since we are talking about PDU of a static frame, once the VN starts sending it, you cannot stop it individually by PDU control.
Frame vs. PDU
A frame is physical Flexray Frame on the network. a PDU, is a virtualization of a part (or of the entire) of the frame payload.
Analogy: The postal truck is the FlexRay Frame, and the boxes in it are PDUs. For the Postal service (Flexray Protocol - OSI layer 1) the important unit is the truck itself, and for you (the client), the boxes in it. You will never be interested in what kind of truck delivered your goodies in a box, you are interested only in the content itself.
When you call the FrUpdatePDU(), you not only start sending the PDU, but you activate (send non-null frames) its slot also.
By setting the frame underneath to non-null frame, you ensured (in a case of static frame) that it will be sent cyclically from that point, automatically, regardless what you want to do with the PDU (the trucks are going anyway, even if you don't want to send boxes in them).
Solution:
I presume you do not have IL DLLs to aid you, therefore you are limited to the functions CANoe environment provides as General FlexRay IL functions.
You need to identify the frame carrying the PDU.
You need to manipulate the frame also with frUpdateStatFrame().
frframe FramefromDBCofTEMPPDU InstanceofFrameTemp;
on frStartCycle *
{
if (#FR_namespace::TEMP_Enablebutton==1)
{
mframe.fr_flags=0x0;
frUpdateStatFrame(mframe);
TEMP_Pdu.byte(0xAA);
FrUpdatePDU(TEMP_Pdu, 1, 1));
}
else
{
mframe.fr_flags=0x80;
frUpdateStatFrame(mframe);
}
}
So, in fact you need to modify the frame also. About the frame flags, check out the definition of the frframe in Help.
I don't use Vector CANoe or CANalyzer myself and there is almost no public documentation, so I can only offer some general debugging hints:
Have you checked that #FR_namespace::TEMP_Enablebutton has the expected value, i.e. that it is really false when you turn the button off? You could add a write() before the if() inside "on frStartCycle" to check this.
This question looks similar: Sending Periodic CAN signals on button press using CAPL and CANalyzer - they use "on sysvar" to react to the button press, maybe you have to do something similar. Namely: React to the button press, set an environment variable, check that variable in "on frStartCycle"
Since there is not a lot of public documentation, you can also try asking around inside your company, there might be some people around you who can help you.
I want to link two different WoW events together. I need some information from both events and store them together in a simple table. Also it is important that the data of the second event is stored only if the first event even fired!
In my case its the name of a creature from COMBAT_LOG_EVENT_UNFILTERED and the reputation gained from COMBAT_TEXT_UPDATE. The reputation should only be stored, if it is gained from killing a creature. I am currently doing that with a temporary table to link those. It stores the name from the first event and will be readable in the second event. Here's the simplified code for that:
nehFragger_ReputationDB = {} -- The actual database for my AddOn.
local tempKillLog = {} -- A table that I use to link the different events.
function nehFraggerFrame_OnLoad(frame)
frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
frame:RegisterEvent("COMBAT_TEXT_UPDATE")
end
function nehFraggerFrame_OnEvent(frame, event, ...)
local arg1, eventType, arg3, arg4, sourceName, arg6, arg7, destGUID, destName = select(1, ...)
if (event == "COMBAT_LOG_EVENT_UNFILTERED") then
if (eventType == "PARTY_KILL") then
tempKillLog.creatureGUID = destGUID -- The unique identifier of the creature.
tempKillLog.creatureName = destName -- The creature name that I need.
end
end
local eventType, faction, reputation = select(1, ...)
if (event == "COMBAT_TEXT_UPDATE") then
if (eventType == "FACTION") then
local GUID = TempKillLog.creatureGUID
if (string.upper(string.sub(GUID, 1 , 8)) == "CREATURE") then -- Make sure the link-table data really is a creature.
local creatureName = tempKillLog.creatureName -- The name from my link-table.
local reputationGain = reputation -- The reputation that I need.
-- Simply store the stuff to the database table for this faction:
nehFragger_ReputationDB[faction] = {}
nehFragger_ReputationDB[faction].creatureName = creatureName
nehFragger_ReputationDB[faction].reputationGain = reputationGain
end
end
end
end
This works...sort of. There are several problems with that (see below).
My question here is:
Is there a possibility to either
- get some unique identifier for the source of different events in general (like the destGUID of COMBAT_LOG_EVENT) to connect those
- or is there an even simpler way to get the reputation of a kill (including creature and reputation information) like in the case of my AddOn?
Some more things to consider:
I have also tried to use the current time in both events to check if these are fired within say 0.01 seconds. That erases loads of problems I have encountered, but will still fail in certain circumstances. If, for example, you finish one of these new Legion world-quests by killing a creature and then gain the reputation for the quest itself. That's still within the timeframe, regardless of how small it is.
Another problem is, if you kill more than one (say 5) creature at a time, then the first event COMBAT_LOG_EVENT_UNFILTERED first fires 5 times in a row, and THEN the second event COMBAT_TEXT_UPDATE fires 5 times. In this case, all the 5 logs in my nehFragger_ReputationDB have the correct amount of reputation gained but all of them with the name of the last creature killed/processed...
I would really like to use the GUID for both events to link them, but I cannot get the one of the second event - if there even exists one. That would be the cleanest and safest way in my opinion.
Or, like already mentioned, a dedicated WoW event for this. But I didn't find one.
I hope somebody can help me here or provide some food for thought.
At the beginning of my scene I'm running a bunch of different actions as a sort of intro to the level. I would like to make it skippable by the user. Is there a way to handle this with SKAction? SKAction is my bet, but perhaps there's a better way to do this. Any ideas?
This assumes you want tap to stop the actions:
A very easy but possibly unstable approach would be to just crank the speed of the Node the action is running on to an insanely high number, just remember to reset it if you need the node.
An easy approach that is more stable would be to save your actions and reapply them with a duration of zero.
The best way to do this is to create a Dictionary for your SKActions like so:
var actionDict = [String,SKAction]()
Then just save all your actions with keys so that you can access it in the future:
actionDict["moveUp"] = SKAction.moveToY(100,duration:100)
Now that you have keys for it, when running your actions, just assign the same key:
node.runAction(actionDict["moveUp"],withKey:"moveUp")
Then when you need to end it, just remove the desired actions:
node.removeActionForKey("moveUp")
And reapply with a duration of 0:
//if we want to retain the old duration, use copy
let action = actionDict["moveUp"].copy()
action.duration = 0
node.runAction(action,withKey:"moveUp")
Note, this method only works where the action is doing a To event, if it is doing a By event, you need to figure out the final destination point, and make it a moveTo a with duration of 0
I've an actor where I want to store my mutable state inside a map.
Clients can send Get(key:String) and Put(key:String,value:String) messages to this actor.
I'm considering the following options.
Don't use futures inside the Actor's receive method. In this may have a negative impact on both latency as well as throughput in case I've a large number of gets/puts because all operations will be performed in order.
Use java.util.concurrent.ConcurrentHashMap and then invoke the gets and puts inside a Future.
Given that java.util.concurrent.ConcurrentHashMap is thread-safe and providers finer level of granularity, I was wondering if it is still a problem to close over the concurrentHashMap inside a Future created for each put and get.
I'm aware of the fact that it's a really bad idea to close over mutable state inside a Future inside an Actor but I'm still interested to know if in this particular case it is correct or not?
In general, java.util.concurrent.ConcurrentHashMap is made for concurrent use. As long as you don't try to transport the closure to another machine, and you think through the implications of it being used concurrently (e.g. if you read a value, use a function to modify it, and then put it back, do you want to use the replace(key, oldValue, newValue) method to make sure it hasn't changed while you were doing the processing?), it should be fine in Futures.
May be a little late, but still, in the book Reactive Web Applications, the author has indicated an indirection to this specific problem, using pipeTo as below.
def receive = {
case ComputeReach(tweetId) =>
fetchRetweets(tweetId, sender()) pipeTo self
case fetchedRetweets: FetchedRetweets =>
followerCountsByRetweet += fetchedRetweets -> List.empty
fetchedRetweets.retweets.foreach { rt =>
userFollowersCounter ! FetchFollowerCount(
fetchedRetweets.tweetId, rt.user
)
}
...
}
where followerCountsByRetweet is a mutable state of the actor. The result of fetchRetweets() which is a Future is piped to the same actor as a FetchedRetweets message, which then acts on the message on to modify the state of the acto., this will mitigate any concurrent operation on the state