ISynchronizable and IFlushable

July 25, 2012 posted by: Elias

ever wanted to write a sample and hold node as a plugin? well you couldn’t, until now :)

the ISpread interface now implements two new interfaces, ISynchronizable and IFlushable. ISynchronizable exposes the method Sync and IFlushable exposes the method Flush. what they do is simple: calling the method Sync on a spread triggers the evaluation of the upstream pin and copies the raw pin data to the spread. calling the method Flush on a spread will copy the data of the spread back to the pin.

by default those two methods will be called automatically by the plugin hosting code: Sync will be called before the Evaluate method of the plugin and Flush will be called after the call to Evaluate. now the interesting part is that you can disable the implicit call to Sync and call it manually in your Evaluate method. this means that as long as you don’t call Sync on your input spread all the nodes connected upstream of the corresponding pin are not evaluated. that’s exactly the behaviour how the well known sample and hold node works.

you can disable the implicit call to Sync by setting the new property AutoValidate to false on your input attribute.

here’s an example code how a sample and hold could look like:

[](Input("Input",%20AutoValidate%20=%20false))
ISpread<T> FInput;
[](Input("Set"))
ISpread<bool> FSetIn;
[](Output("Output"))
ISpread<T> FOutput;
...
public void Evaluate(int spreadMax) {
  if (FSetIn[](0)) {
    FInput.Sync();
    FOutput.AssignFrom(FInput);
  }
}

the implicit call to Flush cannot be disabled. if someone comes up with a good use case it shouldn’t be that hard to implement though.


Comments:

Comments are no longer accepted for this post.

zeos
27.07.2012 - 03:11

That’s great! Does it make sense, to also allow to overwrite the flush method, when there is a parallel task started inside the node (this nice .net 4 task/continueWith,…) and when the task is finished, loads the result into the output pin(should be locked in that moment or with continueWith you and up in the parent thread, so.. Or?) hm or there is better way (IStream…?)

Cheers

Elias
27.07.2012 - 12:20
calling Sync or Flush can lead to calls on COM interfaces, which will immediately throw an exception if called from another thread than the vvvv main thread. as i explained in the blog post, Sync will definitely lead to a COM call, as it calls the Validate method on the underlying IPluginIO interface. so this is a no go. on the other hand calling Flush from another thread could work depending on the used datatype, as for example the int/float/double/bool/vector/matrix stream implementations work directly on the unmanaged data pointer. but in those cases the Flush is either a no op, if you work with IOutStream directly or when working with an IIOStream or an ISpread it leads to a very fast mem copy for the above mentioned data types, so i doubt that it would make much of a difference.
zeos
27.07.2012 - 17:36

Hi Elias!

Many thanks for your answer and for all this vvvvunderfull new stuff!!!

How do you recommend to use the new .net4 parallels library (http://msdn.microsoft.com/en-us/library/dd537609.aspx) inside vvvv dynamic plugin?

Let’s say we have one node (plugin) that has an enable pin. When enabled is set to it starts a TASK to read and process data from elsewhere, when the TASK is done it “load” the result into a FOutput pin via IOutStream? And the re-start the TASK from the beginning.

I want to use the new TASK library to do some things parallel and increase performance, also to make a “Task Template” that uses .NET4 Tasks and shared it, when I figure it out ;) I do not know the v4 internals and some directions will help a lot ;)

Many, many thanks!

Elias
28.07.2012 - 13:13

i guess you do not want to block the main thread as long as the task is running? in that case use a ConcurrentQueue where you enqueue your results from your tasks and try to dequeue them from the main thread.

something like this should work…

private readonly ConcurrentQueue<T> FResultQueue = new ConcurrentQueue<T>();
...
public void Evaluate(int spreadMax) {
  if (FEnabled[](0)) {
    Parallel.Invoke(() => FResultQueue.Enqueue(default(T));
  }
  T result;
  if (FResultQueue.TryDequeue(out result)) {
    FOutput[](0) = result;
  }
}
zeos
01.08.2012 - 05:02
Thanks!!! I will experiment and report.

Contact


Imprint

vvvv - Dießl & Gregor GbR
Oranienstrasse 10
10997 Berlin/Germany
VAT: DE275566955

groupӘvvvv.org

Follow us

Mastodon.social
Pixelfed.social
Github
Vimeo
Youtube

Sign up for our Newsletter

Your subscription could not be saved. Please try again.
Your subscription has been successful.